From dae8919d34ece500e3f75a4fdf7ba3f591a1f54f Mon Sep 17 00:00:00 2001 From: Boyuan Yang Date: Mon, 16 Dec 2024 17:48:45 -0500 Subject: [PATCH] New upstream version 5.7.4 --- .clang-format | 196 + .github/ISSUE_TEMPLATE/config.yml | 21 +- .github/ISSUE_TEMPLATE/document.md | 17 + .github/ISSUE_TEMPLATE/empty-issue.md | 8 - .github/ISSUE_TEMPLATE/unit-test-report.md | 12 - .github/workflows/backup-to-gitlab.yml | 6 +- .github/workflows/call-build-deb.yml | 17 - .github/workflows/call-build-distribution.yml | 6 +- .github/workflows/call-chatOps.yml | 3 +- .github/workflows/call-clacheck.yml | 3 +- .github/workflows/call-deploy-dev-doc.yml | 26 + .github/workflows/call-doc-check.yml | 3 +- .../workflows/call-synchronize-to-dtk6.yml | 19 + .github/workflows/call-tag-build.yml | 13 - .github/workflows/cppcheck.yml | 2 +- .gitignore | 17 +- .obs/workflows.yml | 51 + .reuse/dep5 | 20 +- .syncexclude | 11 + CMakeLists.txt | 105 +- LICENSES/BSD-3-Clause.txt | 11 + LICENSES/MIT.txt | 9 - README.md | 15 + README.zh_CN.md | 14 + archlinux/PKGBUILD | 37 +- cmake/DtkCMake/DtkCMakeConfig.cmake.in | 76 + cmake/DtkDConfig/DtkDConfigConfig.cmake | 101 + cmake/DtkDConfig/DtkDConfigConfig.cmake.in | 95 + cmake/DtkTools/DtkDBusMacros.cmake | 79 + cmake/DtkTools/DtkSettingsToolsMacros.cmake | 6 +- cmake/DtkTools/DtkToolsConfig.cmake | 9 - cmake/DtkTools/DtkToolsConfig.cmake.in | 14 + debian/changelog | 288 +- debian/compat | 1 - debian/control | 13 +- debian/libdtkcore5-bin.install | 3 +- .../doxygen-awesome-darkmode-toggle.js | 157 - debian/rules | 14 +- debian/symbols.amd64 | 909 - docs/CMakeLists.txt | 69 +- docs/MainPage.zh_CN.md | 52 + docs/dci/ddcifile.zh_CN.dox | 113 + docs/dci/index.zh_CN.md | 92 + docs/doxygentheme/custom-alternative.css | 54 - docs/doxygentheme/custom.css | 101 - .../doxygen-awesome-darkmode-toggle.js | 157 - .../doxygen-awesome-fragment-copy-button.js | 85 - .../doxygen-awesome-interactive-toc.js | 81 - .../doxygen-awesome-paragraph-link.js | 51 - ...n-awesome-sidebar-only-darkmode-toggle.css | 40 - .../doxygen-awesome-sidebar-only.css | 115 - docs/doxygentheme/doxygen-awesome.css | 2405 - docs/doxygentheme/header.html | 147 - docs/doxygentheme/logo.drawio.svg | 1 - docs/doxygentheme/toggle-alternative-theme.js | 12 - docs/dsysinfo.zh_CN.dox | 221 - docs/filesystem/dbasefilewatcher.zh_CN.dox | 68 + docs/filesystem/dcapfile.zh_CN.dox | 192 + docs/filesystem/dfilesystemwatcher.zh_CN.dox | 73 + docs/filesystem/dfilewarcher.zh_CN.dox | 44 + docs/filesystem/dfilewatchermanager.zh_CN.dox | 92 + docs/filesystem/dstandardpaths.zh_CN.dox | 47 + docs/filesystem/dtrashmanager.zh_CN.dox | 21 + docs/filesystem/index.zh_CN.md | 8 + docs/global/dconfig.zh_CN.dox | 388 + docs/global/dconfigfile.zh_CN.dox | 448 + docs/global/ddesktopentry.zh_CN.dox | 361 + docs/global/dlicenseinfo.zh_CN.dox | 51 + docs/global/dsysinfo.zh_CN.dox | 307 + docs/global/index.zh_CN.md | 50 + docs/log/AbstractAppender.zh_CN.dox | 70 + docs/log/AbstractStringAppender.zh_CN.dox | 60 + docs/log/ConsoleAppender.zh_CN.dox | 23 + docs/log/FileAppender.zh_CN.dox | 29 + docs/log/Logger.zh_CN.dox | 176 + docs/log/RollingFileAppender.zh_CN.dox | 64 + docs/log/dlogmanager.zh_CN.dox | 41 + docs/log/index.zh_CN.md | 84 + .../backend/dsettingsdconfigbackend.zh_CN.dox | 32 + .../backend/gsettingsbackend.zh_CN.dox | 27 + .../backend/qsettingbackend.zh_CN.dox | 31 + docs/settings/dsettings.zh_CN.dox | 230 + docs/settings/dsettingsgroup.zh_CN.dox | 60 + docs/settings/dsettingsoption.zh_CN.dox | 87 + docs/settings/index.zh_CN.md | 166 + docs/src/dciicon-tree.png | Bin 0 -> 58801 bytes docs/src/dconfig_example1.png | Bin 0 -> 60295 bytes docs/src/dconfigfile_example1.png | Bin 0 -> 52955 bytes docs/src/dconfigfile_example2.jpg | Bin 0 -> 195869 bytes docs/src/ddesktopentry_example1.png | Bin 0 -> 254041 bytes docs/src/dsettings.png | Bin 0 -> 123942 bytes docs/src/layout.png | Bin 0 -> 18169 bytes docs/util/dabstractunitformatter.zh_CN.dox | 70 + .../ddbusextentedabstractinterface.zh_CN.dox | 127 + docs/util/ddbussender.zh_CN.dox | 89 + docs/util/ddisksizeformatter.zh_CN.dox | 46 + docs/util/dtextencoding.zh_CN.dox | 72 + docs/util/dthreadutils.zh_CN.dox | 55 + docs/util/dtimeunitformatter.zh_CN.dox | 40 + docs/util/dutil.zh_CN.dox | 31 + docs/util/index.zh_CN.md | 13 + dtkcore.cmake | 153 + examples/CMakeLists.txt | 4 +- examples/dasync-example/CMakeLists.txt | 21 - examples/dasync-example/main.cpp | 444 - examples/dlog-example/CMakeLists.txt | 16 + examples/dlog-example/main.cpp | 34 + examples/expintf-example/CMakeLists.txt | 14 +- examples/filewatcher-example/CMakeLists.txt | 18 + examples/filewatcher-example/main.cpp | 48 + examples/textcodec-example/CMakeLists.txt | 18 + examples/textcodec-example/main.cpp | 102 + include/DtkCore/DDBusExtended | 1 - include/DtkCore/DLicenseInfo | 1 + include/DtkCore/DLog | 16 +- include/DtkCore/DTextEncoding | 1 + include/base/dexpected.h | 33 +- include/base/dsingleton.h | 3 +- include/dci/ddcifile.h | 2 +- include/filesystem/dcapfile.h | 2 +- include/filesystem/dcapmanager.h | 5 +- include/filesystem/dfilewatchermanager.h | 6 +- include/filesystem/dstandardpaths.h | 27 +- include/global/dconfig.h | 8 + include/global/dconfigfile.h | 10 +- include/global/ddesktopentry.h | 20 +- include/global/dlicenseinfo.h | 51 + include/global/dsysinfo.h | 24 +- include/global/dtkcore_global.h | 12 + include/log/AbstractAppender.h | 40 - include/log/AbstractStringAppender.h | 35 - include/log/ConsoleAppender.h | 30 - include/log/FileAppender.h | 43 - include/log/LogManager.h | 19 +- include/log/Logger.h | 149 - include/log/RollingFileAppender.h | 75 - include/log/dloggerdefs.h | 56 - include/log/win32/OutputDebugAppender.h | 23 - include/util/dasync.h | 418 +- include/util/ddbusextended.h | 14 - include/util/ddbusextendedabstractinterface.h | 25 +- include/util/ddbusinterface.h | 3 +- include/util/ddbussender.h | 9 +- include/util/dpinyin.h | 16 +- include/util/dtextencoding.h | 45 + include/util/dthreadutils.h | 176 +- include/util/dutil.h | 92 +- include/util/dvtablehook.h | 53 +- linglong.yaml | 29 + misc/DtkConfig.cmake.in | 14 - misc/DtkCoreConfig.cmake.in | 27 + misc/dtk_install_dconfig.prf | 83 + misc/dtkcore.pc.in | 11 +- misc/qt_lib_dtkcore.pri.in | 12 +- rpm/dtkcore.spec | 2 + src/CMakeLists.txt | 161 +- src/dbus/dbus.cmake | 35 +- .../org.desktopspec.ConfigManager.Manager.xml | 4 + src/dci/ddcifile.cpp | 13 +- src/dci/private/ddcifileengine.cpp | 80 +- src/dci/private/ddcifileengine_p.h | 31 + src/dconfig.cpp | 293 +- src/dconfigfile.cpp | 585 +- src/ddesktopentry.cpp | 103 +- src/dlicenseinfo.cpp | 205 + src/dsecurestring.cpp | 1 + src/dsgapplication.cpp | 111 +- src/dsysinfo.cpp | 182 +- src/dtkcore_global.cpp | 39 +- src/filesystem/dbasefilewatcher.cpp | 69 +- src/filesystem/dcapfile.cpp | 7 +- src/filesystem/dcapfsfileengine.cpp | 41 +- src/filesystem/dcapmanager.cpp | 35 +- src/filesystem/dfilesystemwatcher_dummy.cpp | 48 +- src/filesystem/dfilesystemwatcher_linux.cpp | 3 +- src/filesystem/dfilewatcher.cpp | 2 +- src/filesystem/dfilewatchermanager.cpp | 60 +- src/filesystem/dstandardpaths.cpp | 17 +- src/filesystem/dtrashmanager_linux.cpp | 2 +- src/filesystem/private/dcapfsfileengine_p.h | 20 + src/glob.cmake | 61 +- src/log/AbstractAppender.cpp | 159 - src/log/AbstractStringAppender.cpp | 433 - src/log/ConsoleAppender.cpp | 68 - src/log/FileAppender.cpp | 112 - src/log/LogManager.cpp | 189 +- src/log/Logger.cpp | 1050 - src/log/OutputDebugAppender.cpp | 48 - src/log/README.md | 63 - src/log/RollingFileAppender.cpp | 243 - src/log/log.cmake | 29 +- .../backend/dsettingsdconfigbackend.cpp | 24 +- src/settings/backend/gsettingsbackend.cpp | 21 +- src/settings/backend/qsettingbackend.cpp | 24 +- src/settings/dsettings.cpp | 121 +- src/settings/dsettingsgroup.cpp | 83 +- src/settings/dsettingsoption.cpp | 132 +- src/settings/settings.cmake | 18 +- src/util/dabstractunitformatter.cpp | 212 +- src/util/ddbusextendedabstractinterface.cpp | 220 +- src/util/ddbusextendedpendingcallwatcher.cpp | 12 +- src/util/ddbusextendedpendingcallwatcher_p.h | 15 +- src/util/ddbusinterface.cpp | 89 +- src/util/ddbusinterface_p.h | 1 - src/util/ddbussender.cpp | 28 +- src/util/ddisksizeformatter.cpp | 76 +- src/util/dpinyin.cpp | 186 +- src/util/drecentmanager.cpp | 11 + src/util/dtextencoding.cpp | 469 + src/util/dthreadutils.cpp | 66 +- src/util/dtimeunitformatter.cpp | 80 +- src/util/dvtablehook.cpp | 124 +- src/util/resources/dpinyin.dict | 50666 ++++++++-------- src/util/util.cmake | 28 +- tests/CMakeLists.txt | 211 +- tests/data.qrc | 3 + tests/data/LGPLv3.txt | 164 + tests/data/dconf-example.meta.json | 10 + .../dconf-example.override.noexistitem.json | 11 + tests/data/example-license.json | 8 + tests/fakedbus/fakedbusservice.cpp | 56 + tests/fakedbus/fakedbusservice.h | 61 + tests/main.cpp | 11 +- tests/test-recoverage.sh | 11 +- tests/test_helper.hpp | 37 +- tests/testso/CMakeLists.txt | 12 + tests/testso/testso.cpp | 12 + tests/testso/testso.h | 37 + tests/ut_dasync.cpp | 5 +- tests/ut_dcapfile.cpp | 179 +- tests/ut_dconfig.cpp | 118 +- tests/ut_dconfigfile.cpp | 281 +- tests/ut_ddbusextendedabstractinterface.cpp | 157 + tests/ut_ddbusinterface.cpp | 52 + tests/ut_ddbussender.cpp | 69 + tests/ut_ddesktopentrytest.cpp | 8 + tests/ut_dexpected.cpp | 59 + tests/ut_dexportedinterface.cpp | 97 + tests/ut_dfilesystemwatcher.cpp | 3 + tests/ut_dfilewatcher.cpp | 4 + tests/ut_dfilewatchermanager.cpp | 54 +- tests/ut_dlicenseinfo.cpp | 30 + tests/ut_dlog.cpp | 39 + tests/ut_dnotifysender.cpp | 40 + tests/ut_dpinyin.cpp | 46 +- tests/ut_dsgapplication.cpp | 27 + tests/ut_dstandardpaths.cpp | 106 +- tests/ut_dsysinfo.cpp | 381 + tests/ut_dtextencoding.cpp | 283 + tests/ut_dthreadutils.cpp | 217 +- tests/ut_dutil.cpp | 407 - tests/ut_dutil.h | 7 +- tests/ut_dvtablehook.cpp | 87 +- tests/ut_gsettingsbackend.cpp | 1 + tests/ut_logger.cpp | 162 - tests/ut_singleton.cpp | 50 +- tools/CMakeLists.txt | 1 + tools/ch2py/CMakeLists.txt | 21 + tools/ch2py/main.cpp | 73 + tools/dci/CMakeLists.txt | 13 +- tools/dci/dci.pro | 23 - tools/dci/main.cpp | 94 +- tools/deepin-os-release/CMakeLists.txt | 15 +- tools/deepin-os-release/deepin-os-release.pro | 20 - tools/deepin-os-release/main.cpp | 24 +- tools/qdbusxml2cpp/CMakeLists.txt | 35 +- tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 107 +- tools/qdbusxml2cpp/qdbusxml2cpp.pro | 16 - tools/settings/CMakeLists.txt | 32 +- tools/settings/main.cpp | 65 + tools/settings/settings.pro | 34 - 271 files changed, 38157 insertions(+), 36006 deletions(-) create mode 100644 .clang-format create mode 100644 .github/ISSUE_TEMPLATE/document.md delete mode 100644 .github/ISSUE_TEMPLATE/empty-issue.md delete mode 100644 .github/ISSUE_TEMPLATE/unit-test-report.md delete mode 100644 .github/workflows/call-build-deb.yml create mode 100644 .github/workflows/call-deploy-dev-doc.yml create mode 100644 .github/workflows/call-synchronize-to-dtk6.yml delete mode 100644 .github/workflows/call-tag-build.yml create mode 100644 .obs/workflows.yml create mode 100644 .syncexclude create mode 100644 LICENSES/BSD-3-Clause.txt delete mode 100644 LICENSES/MIT.txt create mode 100644 cmake/DtkCMake/DtkCMakeConfig.cmake.in create mode 100644 cmake/DtkDConfig/DtkDConfigConfig.cmake create mode 100644 cmake/DtkDConfig/DtkDConfigConfig.cmake.in create mode 100644 cmake/DtkTools/DtkDBusMacros.cmake delete mode 100644 cmake/DtkTools/DtkToolsConfig.cmake create mode 100644 cmake/DtkTools/DtkToolsConfig.cmake.in delete mode 100644 debian/compat delete mode 100644 debian/missing-sources/doxygen-awesome-darkmode-toggle.js delete mode 100644 debian/symbols.amd64 create mode 100644 docs/MainPage.zh_CN.md create mode 100644 docs/dci/ddcifile.zh_CN.dox create mode 100644 docs/dci/index.zh_CN.md delete mode 100644 docs/doxygentheme/custom-alternative.css delete mode 100644 docs/doxygentheme/custom.css delete mode 100644 docs/doxygentheme/doxygen-awesome-darkmode-toggle.js delete mode 100644 docs/doxygentheme/doxygen-awesome-fragment-copy-button.js delete mode 100644 docs/doxygentheme/doxygen-awesome-interactive-toc.js delete mode 100644 docs/doxygentheme/doxygen-awesome-paragraph-link.js delete mode 100644 docs/doxygentheme/doxygen-awesome-sidebar-only-darkmode-toggle.css delete mode 100644 docs/doxygentheme/doxygen-awesome-sidebar-only.css delete mode 100644 docs/doxygentheme/doxygen-awesome.css delete mode 100644 docs/doxygentheme/header.html delete mode 100644 docs/doxygentheme/logo.drawio.svg delete mode 100644 docs/doxygentheme/toggle-alternative-theme.js delete mode 100644 docs/dsysinfo.zh_CN.dox create mode 100644 docs/filesystem/dbasefilewatcher.zh_CN.dox create mode 100644 docs/filesystem/dcapfile.zh_CN.dox create mode 100644 docs/filesystem/dfilesystemwatcher.zh_CN.dox create mode 100644 docs/filesystem/dfilewarcher.zh_CN.dox create mode 100644 docs/filesystem/dfilewatchermanager.zh_CN.dox create mode 100644 docs/filesystem/dstandardpaths.zh_CN.dox create mode 100644 docs/filesystem/dtrashmanager.zh_CN.dox create mode 100644 docs/filesystem/index.zh_CN.md create mode 100644 docs/global/dconfig.zh_CN.dox create mode 100644 docs/global/dconfigfile.zh_CN.dox create mode 100644 docs/global/ddesktopentry.zh_CN.dox create mode 100644 docs/global/dlicenseinfo.zh_CN.dox create mode 100644 docs/global/dsysinfo.zh_CN.dox create mode 100644 docs/global/index.zh_CN.md create mode 100644 docs/log/AbstractAppender.zh_CN.dox create mode 100644 docs/log/AbstractStringAppender.zh_CN.dox create mode 100644 docs/log/ConsoleAppender.zh_CN.dox create mode 100644 docs/log/FileAppender.zh_CN.dox create mode 100644 docs/log/Logger.zh_CN.dox create mode 100644 docs/log/RollingFileAppender.zh_CN.dox create mode 100644 docs/log/dlogmanager.zh_CN.dox create mode 100644 docs/log/index.zh_CN.md create mode 100644 docs/settings/backend/dsettingsdconfigbackend.zh_CN.dox create mode 100644 docs/settings/backend/gsettingsbackend.zh_CN.dox create mode 100644 docs/settings/backend/qsettingbackend.zh_CN.dox create mode 100644 docs/settings/dsettings.zh_CN.dox create mode 100644 docs/settings/dsettingsgroup.zh_CN.dox create mode 100644 docs/settings/dsettingsoption.zh_CN.dox create mode 100644 docs/settings/index.zh_CN.md create mode 100644 docs/src/dciicon-tree.png create mode 100644 docs/src/dconfig_example1.png create mode 100644 docs/src/dconfigfile_example1.png create mode 100644 docs/src/dconfigfile_example2.jpg create mode 100644 docs/src/ddesktopentry_example1.png create mode 100644 docs/src/dsettings.png create mode 100644 docs/src/layout.png create mode 100644 docs/util/dabstractunitformatter.zh_CN.dox create mode 100644 docs/util/ddbusextentedabstractinterface.zh_CN.dox create mode 100644 docs/util/ddbussender.zh_CN.dox create mode 100644 docs/util/ddisksizeformatter.zh_CN.dox create mode 100644 docs/util/dtextencoding.zh_CN.dox create mode 100644 docs/util/dthreadutils.zh_CN.dox create mode 100644 docs/util/dtimeunitformatter.zh_CN.dox create mode 100644 docs/util/dutil.zh_CN.dox create mode 100644 docs/util/index.zh_CN.md create mode 100644 dtkcore.cmake delete mode 100644 examples/dasync-example/CMakeLists.txt delete mode 100644 examples/dasync-example/main.cpp create mode 100644 examples/dlog-example/CMakeLists.txt create mode 100644 examples/dlog-example/main.cpp create mode 100644 examples/filewatcher-example/CMakeLists.txt create mode 100644 examples/filewatcher-example/main.cpp create mode 100644 examples/textcodec-example/CMakeLists.txt create mode 100644 examples/textcodec-example/main.cpp delete mode 100644 include/DtkCore/DDBusExtended create mode 100644 include/DtkCore/DLicenseInfo create mode 100644 include/DtkCore/DTextEncoding create mode 100644 include/global/dlicenseinfo.h delete mode 100644 include/log/AbstractAppender.h delete mode 100644 include/log/AbstractStringAppender.h delete mode 100644 include/log/ConsoleAppender.h delete mode 100644 include/log/FileAppender.h delete mode 100644 include/log/Logger.h delete mode 100644 include/log/RollingFileAppender.h delete mode 100644 include/log/dloggerdefs.h delete mode 100644 include/log/win32/OutputDebugAppender.h delete mode 100644 include/util/ddbusextended.h create mode 100644 include/util/dtextencoding.h create mode 100644 linglong.yaml delete mode 100644 misc/DtkConfig.cmake.in create mode 100644 misc/DtkCoreConfig.cmake.in create mode 100644 misc/dtk_install_dconfig.prf create mode 100644 src/dlicenseinfo.cpp delete mode 100644 src/log/AbstractAppender.cpp delete mode 100644 src/log/AbstractStringAppender.cpp delete mode 100644 src/log/ConsoleAppender.cpp delete mode 100644 src/log/FileAppender.cpp delete mode 100644 src/log/Logger.cpp delete mode 100644 src/log/OutputDebugAppender.cpp delete mode 100644 src/log/README.md delete mode 100644 src/log/RollingFileAppender.cpp create mode 100644 src/util/dtextencoding.cpp create mode 100644 tests/data/LGPLv3.txt create mode 100644 tests/data/dconf-example.override.noexistitem.json create mode 100644 tests/data/example-license.json create mode 100644 tests/fakedbus/fakedbusservice.cpp create mode 100644 tests/fakedbus/fakedbusservice.h create mode 100644 tests/testso/CMakeLists.txt create mode 100644 tests/testso/testso.cpp create mode 100644 tests/testso/testso.h create mode 100644 tests/ut_ddbusextendedabstractinterface.cpp create mode 100644 tests/ut_ddbusinterface.cpp create mode 100644 tests/ut_ddbussender.cpp create mode 100644 tests/ut_dexpected.cpp create mode 100644 tests/ut_dexportedinterface.cpp create mode 100644 tests/ut_dlicenseinfo.cpp create mode 100644 tests/ut_dlog.cpp create mode 100644 tests/ut_dnotifysender.cpp create mode 100644 tests/ut_dsgapplication.cpp create mode 100644 tests/ut_dsysinfo.cpp create mode 100644 tests/ut_dtextencoding.cpp delete mode 100644 tests/ut_logger.cpp create mode 100644 tools/ch2py/CMakeLists.txt create mode 100644 tools/ch2py/main.cpp delete mode 100644 tools/dci/dci.pro delete mode 100644 tools/deepin-os-release/deepin-os-release.pro delete mode 100644 tools/qdbusxml2cpp/qdbusxml2cpp.pro delete mode 100644 tools/settings/settings.pro diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..b8ab781 --- /dev/null +++ b/.clang-format @@ -0,0 +1,196 @@ +--- +# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto +Language: Cpp +# BasedOnStyle: LLVM +# 访问说明符(public、private等)的偏移 +AccessModifierOffset: -4 +# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行) +AlignAfterOpenBracket: Align +# 连续赋值时,对齐所有等号 +AlignConsecutiveAssignments: None +# 连续声明时,对齐所有声明的变量名 +AlignConsecutiveDeclarations: None + +AlignEscapedNewlines: Right + +# 左对齐逃脱换行(使用反斜杠换行)的反斜杠 +#AlignEscapedNewlinesLeft: true +# 水平对齐二元和三元表达式的操作数 +AlignOperands: true +# 对齐连续的尾随的注释 +AlignTrailingComments: true + +# 允许函数声明的所有参数在放在下一行 +AllowAllParametersOfDeclarationOnNextLine: true +# 允许短的块放在同一行 +AllowShortBlocksOnASingleLine: Empty +# 允许短的case标签放在同一行 +AllowShortCaseLabelsOnASingleLine: false +# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All +AllowShortFunctionsOnASingleLine: Inline +# 允许短的if语句保持在同一行 +AllowShortIfStatementsOnASingleLine: false +# 允许短的循环保持在同一行 +AllowShortLoopsOnASingleLine: false + +# 总是在定义返回类型后换行(deprecated) +AlwaysBreakAfterDefinitionReturnType: None +# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数), +# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义) +AlwaysBreakAfterReturnType: None +# 总是在多行string字面量前换行 +AlwaysBreakBeforeMultilineStrings: false +# 总是在template声明后换行 +AlwaysBreakTemplateDeclarations: Yes +# false表示函数实参要么都在同一行,要么都各自一行 +BinPackArguments: false +# false表示所有形参要么都在同一行,要么都各自一行 +BinPackParameters: false +# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效 +BraceWrapping: + # class定义后面 + AfterClass: true + # 控制语句后面 + AfterControlStatement: Never + # enum定义后面 + AfterEnum: false + # 函数定义后面 + AfterFunction: true + # 命名空间定义后面 + AfterNamespace: false + # ObjC定义后面 + AfterObjCDeclaration: false + # struct定义后面 + AfterStruct: true + # union定义后面 + AfterUnion: true + + AfterExternBlock: false + # catch之前 + BeforeCatch: false + # else之前 + BeforeElse: false + # 缩进大括号 + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true + +# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行) +BreakBeforeBinaryOperators: None +# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似), +# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似), +# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom +# 注:这里认为语句块也属于函数 +BreakBeforeBraces: Custom +# 在三元运算符前换行 +BreakBeforeTernaryOperators: false + +# 在构造函数的初始化列表的逗号前换行 +BreakConstructorInitializersBeforeComma: true +BreakConstructorInitializers: BeforeColon +# 每行字符的限制,0表示没有限制 +ColumnLimit: 130 +# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +# 构造函数的初始化列表要么都在同一行,要么都各自一行 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +# 构造函数的初始化列表的缩进宽度 +ConstructorInitializerIndentWidth: 4 +# 延续的行的缩进宽度 +ContinuationIndentWidth: 4 +# 去除C++11的列表初始化的大括号{后和}前的空格 +Cpp11BracedListStyle: true +# 继承最常用的指针和引用的对齐方式 +DerivePointerAlignment: false +# 关闭格式化 +DisableFormat: false +# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental) +ExperimentalAutoDetectBinPacking: false +# 需要被解读为foreach循环而不是函数调用的宏 +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前), +# 可以定义负数优先级从而保证某些#include永远在最前面 +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +# 缩进case标签 +IndentCaseLabels: true + +#IndentPPDirectives: AfterHash +# 缩进宽度 +IndentWidth: 4 +# 函数返回类型换行时,缩进函数声明或函数定义的函数名 +IndentWrappedFunctionNames: false +# 保留在块开始处的空行 +KeepEmptyLinesAtTheStartOfBlocks: false +# 开始一个块的宏的正则表达式 +MacroBlockBegin: '' +# 结束一个块的宏的正则表达式 +MacroBlockEnd: '' +# 连续空行的最大数量 +MaxEmptyLinesToKeep: 1 +# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All +NamespaceIndentation: Inner +# 使用ObjC块时缩进宽度 +ObjCBlockIndentWidth: 4 +# 在ObjC的@property后添加一个空格 +ObjCSpaceAfterProperty: false +# 在ObjC的protocol列表前添加一个空格 +ObjCSpaceBeforeProtocolList: true + + +# 在call(后对函数调用换行的penalty +PenaltyBreakBeforeFirstCallParameter: 19 +# 在一个注释中引入换行的penalty +PenaltyBreakComment: 300 +# 第一次在<<前换行的penalty +PenaltyBreakFirstLessLess: 120 +# 在一个字符串字面量中引入换行的penalty +PenaltyBreakString: 1000 +# 对于每个在行字符数限制之外的字符的penalty +PenaltyExcessCharacter: 1000000 +# 将函数的返回类型放到它自己的行的penalty +PenaltyReturnTypeOnItsOwnLine: 60 + +# 指针和引用的对齐: Left, Right, Middle +PointerAlignment: Right +# 允许重新排版注释 +ReflowComments: true +# 允许排序#include +SortIncludes: Never + +# 在C风格类型转换后添加空格 +SpaceAfterCStyleCast: false + +SpaceAfterTemplateKeyword: true + +# 在赋值运算符之前添加空格 +SpaceBeforeAssignmentOperators: true +# 开圆括号之前添加一个空格: Never, ControlStatements, Always +SpaceBeforeParens: ControlStatements +# 在空的圆括号中添加空格 +SpaceInEmptyParentheses: false +# 在尾随的评论前添加的空格数(只适用于//) +SpacesBeforeTrailingComments: 2 +# 在尖括号的<后和>前添加空格 +SpacesInAngles: false +# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格 +SpacesInContainerLiterals: false +# 在C风格类型转换的括号中添加空格 +SpacesInCStyleCastParentheses: false +# 在圆括号的(后和)前添加空格 +SpacesInParentheses: false +# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响 +SpacesInSquareBrackets: false +# 标准: Cpp03, Cpp11, Auto +Standard: Auto +# tab宽度 +TabWidth: 4 +# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always +UseTab: Never diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0086358..3e5e40b 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1,20 @@ -blank_issues_enabled: true +blank_issues_enabled: false +contact_links: + - name: BUG Report | 缺陷报告 + url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=bug-report.yml + about: Please create bug reports to the issue board in our dtk repo. + + - name: docs-update | 文档补充 + url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=docs-update.yml + about: Please create docs-update to the issue board in our dtk repo. + + - name: unit-test-report | 单元测试报告 + url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=unit-test-report.yml + about: Please create unit-test-report to the issue board in our dtk repo. + + - 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: 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.md b/.github/ISSUE_TEMPLATE/document.md new file mode 100644 index 0000000..c5a1585 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/document.md @@ -0,0 +1,17 @@ +--- +name: Docs update +about: Document Normalization +title: 'Doc: [Document Type][file name]' +labels: 'Doc' +assignees: '' +--- +## Target files (目标文件) + +## Planned completion time (计划完成时间) + +## Document Type (文档类型) + +[] New documents +[] Standardized documents +[] Internationalization of documents +[] Example documents diff --git a/.github/ISSUE_TEMPLATE/empty-issue.md b/.github/ISSUE_TEMPLATE/empty-issue.md deleted file mode 100644 index 84240c8..0000000 --- a/.github/ISSUE_TEMPLATE/empty-issue.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: Empty issue -about: File a Empty issue -title: '' -labels: '' -assignees: '' - ---- diff --git a/.github/ISSUE_TEMPLATE/unit-test-report.md b/.github/ISSUE_TEMPLATE/unit-test-report.md deleted file mode 100644 index 9a6743c..0000000 --- a/.github/ISSUE_TEMPLATE/unit-test-report.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Unit test report -about: File a unit test report. -title: 'Test: [class name]' -labels: '' -assignees: '' - ---- - -Path: [class file path] -Interface: [class interface name] - diff --git a/.github/workflows/backup-to-gitlab.yml b/.github/workflows/backup-to-gitlab.yml index c176335..9863040 100644 --- a/.github/workflows/backup-to-gitlab.yml +++ b/.github/workflows/backup-to-gitlab.yml @@ -8,10 +8,8 @@ concurrency: jobs: backup-to-gitlabwh: uses: linuxdeepin/.github/.github/workflows/backup-to-gitlabwh.yml@master - secrets: - BRIDGETOKEN: ${{ secrets.BRIDGETOKEN }} + secrets: inherit backup-to-gitee: uses: linuxdeepin/.github/.github/workflows/backup-to-gitee.yml@master - secrets: - GITEE_SYNC_TOKEN: ${{ secrets.GITEE_SYNC_TOKEN }} + secrets: inherit diff --git a/.github/workflows/call-build-deb.yml b/.github/workflows/call-build-deb.yml deleted file mode 100644 index fd67cbe..0000000 --- a/.github/workflows/call-build-deb.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Call build-deb -on: - pull_request_target: - paths-ignore: - - ".github/workflows/**" - types: [ opened, closed, synchronize ] - -concurrency: - group: ${{ github.workflow }}-pull/${{ github.event.number }} - cancel-in-progress: true - -jobs: - check_job: - if: github.event.action != 'closed' || github.event.pull_request.merged - uses: linuxdeepin/.github/.github/workflows/build-deb.yml@master - secrets: - BridgeToken: ${{ secrets.BridgeToken }} diff --git a/.github/workflows/call-build-distribution.yml b/.github/workflows/call-build-distribution.yml index c4c277e..a509d5f 100644 --- a/.github/workflows/call-build-distribution.yml +++ b/.github/workflows/call-build-distribution.yml @@ -10,8 +10,4 @@ on: jobs: check_job: uses: linuxdeepin/.github/.github/workflows/build-distribution.yml@master - secrets: - BUILD_GPG_PRIVATE_KEY: ${{ secrets.BUILD_GPG_PRIVATE_KEY }} - BUILD_SSH_PRIVATE_KEY: ${{ secrets.BUILD_SSH_PRIVATE_KEY }} - WEBDAV_PASSWD: ${{ secrets.WEBDAV_PASSWD }} - WEBDAV_USER: ${{ secrets.WEBDAV_USER }} + secrets: inherit diff --git a/.github/workflows/call-chatOps.yml b/.github/workflows/call-chatOps.yml index 0eb0b7b..18c76bc 100644 --- a/.github/workflows/call-chatOps.yml +++ b/.github/workflows/call-chatOps.yml @@ -6,5 +6,4 @@ on: jobs: chatopt: uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master - secrets: - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + secrets: inherit diff --git a/.github/workflows/call-clacheck.yml b/.github/workflows/call-clacheck.yml index 3fa07a3..fe16a07 100644 --- a/.github/workflows/call-clacheck.yml +++ b/.github/workflows/call-clacheck.yml @@ -12,5 +12,4 @@ concurrency: jobs: clacheck: uses: linuxdeepin/.github/.github/workflows/cla-check.yml@master - secrets: - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + secrets: inherit diff --git a/.github/workflows/call-deploy-dev-doc.yml b/.github/workflows/call-deploy-dev-doc.yml new file mode 100644 index 0000000..38ce0d2 --- /dev/null +++ b/.github/workflows/call-deploy-dev-doc.yml @@ -0,0 +1,26 @@ +name: deploy docs +on: + push: + branches: ["master"] + workflow_dispatch: + inputs: + tag: + required: true + type: string + +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + deploydocs: + uses: linuxdeepin/.github/.github/workflows/deploy-dev-doc.yml@master + with: + ref: ${{ inputs.tag }} + secrets: inherit diff --git a/.github/workflows/call-doc-check.yml b/.github/workflows/call-doc-check.yml index 4779992..1a4f18a 100644 --- a/.github/workflows/call-doc-check.yml +++ b/.github/workflows/call-doc-check.yml @@ -11,5 +11,4 @@ concurrency: jobs: check_job: uses: linuxdeepin/.github/.github/workflows/doc-check.yml@master - secrets: - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + secrets: inherit diff --git a/.github/workflows/call-synchronize-to-dtk6.yml b/.github/workflows/call-synchronize-to-dtk6.yml new file mode 100644 index 0000000..fa185b1 --- /dev/null +++ b/.github/workflows/call-synchronize-to-dtk6.yml @@ -0,0 +1,19 @@ +name: Call synchronize to dtk6 +on: + pull_request_target: + paths-ignore: + - "debian/**" + - "archlinux/**" + - "rpm/**" + - ".obs/**" + - ".github/**" + +jobs: + call-synchronize: + uses: linuxdeepin/dtk/.github/workflows/synchronize-to-dtk6.yml@master + secrets: inherit + with: + dest_repo: linuxdeepin/dtk6core + source_repo: ${{ github.event.pull_request.head.repo.full_name }} + source_ref: ${{ github.event.pull_request.head.ref }} + pull_number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/call-tag-build.yml b/.github/workflows/call-tag-build.yml deleted file mode 100644 index 3b1850a..0000000 --- a/.github/workflows/call-tag-build.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: tag build -on: - push: - tags: "*" - -concurrency: - group: ${{ github.workflow }} - cancel-in-progress: true - -jobs: - build: - uses: linuxdeepin/.github/.github/workflows/build-tag.yml@master - secrets: inherit diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml index 6a92b54..e808a89 100644 --- a/.github/workflows/cppcheck.yml +++ b/.github/workflows/cppcheck.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - run: export - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false diff --git a/.gitignore b/.gitignore index 3325f3c..f966e9b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,6 @@ build*/ *.qm src/DtkCores -src/dtkcore_config.h -cmake/DtkCore/DtkCoreConfig.cmake -src/qt_lib_d*.pri bin/ .qmake* @@ -31,8 +28,14 @@ Makefile cmake/DtkCore* .cache -DtkCoreConfig.cmake -dtkcore.pc -qt_lib_dtkcore.pri +*.pc +*.pri dtkcore_config.h -CMakeLists.txt.user +*.user + +#tools +.vscode +.idea + +# Ignore Doxygen theme files +docs/doxygen-theme/ diff --git a/.obs/workflows.yml b/.obs/workflows.yml new file mode 100644 index 0000000..09caed7 --- /dev/null +++ b/.obs/workflows.yml @@ -0,0 +1,51 @@ +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: + - branch_package: + source_project: deepin:Develop:dde + source_package: %{SCM_REPOSITORY_NAME} + target_project: deepin:Unstable:dde + filters: + event: tag_push + +commit_build: + steps: + - trigger_services: + project: deepin:Develop:dde + package: %{SCM_REPOSITORY_NAME} + filters: + event: push diff --git a/.reuse/dep5 b/.reuse/dep5 index 2f81f1d..d10a694 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -10,7 +10,7 @@ Source: https://github.com/linuxdeepin/dtkcore # License: ... # ci -Files: .github/* *.yml *.yaml +Files: .github/* *.yml *.yaml .obs/* .syncexclude Copyright: None License: CC0-1.0 @@ -20,12 +20,12 @@ Copyright: None License: CC0-1.0 # config -Files: *.toml *.conf *.json +Files: *.toml *.conf *.json .clang-format Copyright: None License: CC0-1.0 # qt -Files: *.pro *.pri *.qrc +Files: *.pro *.pri *.qrc *.prf Copyright: None License: CC0-1.0 @@ -54,13 +54,18 @@ Files: *.dox *.md src/util/README.dpinyin tools/qdbusxml2cpp/README Copyright: UnionTech Software Technology Co., Ltd. License: CC-BY-4.0 +# doxygen src +Files: docs/src/* +Copyright: None +License: CC0-1.0 + # interface Files: include/DtkCore/D* Copyright: None License: CC0-1.0 # others -Files: src/util/resources/dpinyin.dict +Files: src/util/resources/dpinyin.dict tests/data/LGPLv3.txt Copyright: None License: CC0-1.0 @@ -72,4 +77,9 @@ License: LGPL-3.0-or-later #doxygentheme Files: docs/doxygentheme/* Copyright: Copyright (c) 2021 - 2022 jothepro -License: MIT \ No newline at end of file +License: MIT + +#reference +Files: docs/references/* +Copyright: UnionTech Software Technology Co., Ltd. +License: CC-BY-4.0 diff --git a/.syncexclude b/.syncexclude new file mode 100644 index 0000000..7b42c60 --- /dev/null +++ b/.syncexclude @@ -0,0 +1,11 @@ +# Paths that will be exclude from synchronize workflow +# Please use relative path which use project directory as root +# Notice that +# * .git +# * debian +# * archlinux +# * .obs +# * .github +# are always ignored +linglong.yaml +conanfile.py diff --git a/CMakeLists.txt b/CMakeLists.txt index ea82a74..bce068c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,106 +1,27 @@ -cmake_minimum_required (VERSION 3.10) - -set (DVERSION "5.6.2" CACHE STRING "define project version") +cmake_minimum_required (VERSION 3.13) +set (DTK_VERSION "5.6.12" CACHE STRING "define project version") project (DtkCore - VERSION ${DVERSION} + VERSION ${DTK_VERSION} DESCRIPTION "DTK Core module" HOMEPAGE_URL "https://github.com/linuxdeepin/dtkcore" LANGUAGES CXX C ) -message(STATUS ${PROJECT_VERSION}) - -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX /usr) endif () -set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libdtk-${CMAKE_PROJECT_VERSION}/DCore") -set (TOOL_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/libdtk-${PROJECT_VERSION}/DCore/bin") -set (LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") -set (MKSPECS_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/qt5/mkspecs/modules" CACHE STRING "INSTALL DIR FOR qt pri files") - -set (BUILD_EXAMPLES ON CACHE BOOL "Build examples") -option(BUILD_VERSION "buildversion" "0") -if(NOT BUILD_VERSION) - set(BUILD_VERSION "0") -endif() -if(UNIX AND NOT APPLE) - set(LINUX TRUE) -endif() -set (BUILD_DOCS ON CACHE BOOL "Generate doxygen-based documentation") - -# CXX FILAGS -set(CMAKE_CXX_STANDARD 11) -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed") - if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") - set(BUILD_TESTING ON) - endif () - string(REPLACE "-O3" "-Ofast" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) -endif() - -if (BUILD_DOCS) - add_subdirectory(docs) -endif () +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) -add_subdirectory(src) -if(BUILD_TESTING) - message("==================================") - message(" Now Testing is enabled ") - message("==================================") - enable_testing() - add_subdirectory(tests) -endif() -if(BUILD_EXAMPLES) - message("===================================") - message("You can build and run examples now ") - message("===================================") - add_subdirectory(examples) +if("${PROJECT_VERSION_MAJOR}" STREQUAL "5") + set(QT_VERSION_MAJOR "5") +elseif("${PROJECT_VERSION_MAJOR}" STREQUAL "6") + set(QT_VERSION_MAJOR "6") + set(DTK_VERSION_MAJOR "6") +else() + message(SEND_ERROR "not support Prject Version ${PROJECT_VERSION}.") endif() -add_subdirectory(tools) -install(FILES cmake/DtkCMake/DtkCMakeConfig.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkCMake/") -install(FILES cmake/DtkTools/DtkToolsConfig.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkTools") -install(FILES cmake/DtkTools/DtkSettingsToolsMacros.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkTools") - -configure_package_config_file(misc/DtkConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/DtkCoreConfig.cmake - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkCore" - PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR TOOL_INSTALL_DIR) -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/DtkCoreConfigVersion.cmake" - VERSION ${DVERSION} - COMPATIBILITY SameMajorVersion -) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/DtkCoreConfig.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkCore") -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/DtkCoreConfigVersion.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DtkCore") - -configure_file(misc/dtkcore.pc.in dtkcore.pc @ONLY) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dtkcore.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - -configure_file(misc/qt_lib_dtkcore.pri.in qt_lib_dtkcore.pri @ONLY) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qt_lib_dtkcore.pri DESTINATION "${MKSPECS_INSTALL_DIR}") -set(CONFIGNAME include/global/dtkcore_config.h) -file(WRITE ${CONFIGNAME} - "// it is auto make config\n" - "#define DTK_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}\n" - "#define DTK_VERSION_MINOR ${PROJECT_VERSION_MINOR}\n" - "#define DTK_VERSION_PATCH ${PROJECT_VERSION_PATCH}\n" - "#define DTK_VERSION_BUILD ${BUILD_VERSION}\n" - "#define DTK_VERSION_STR \"${PROJECT_VERSION}\"\n" - "\n" -) -file(GLOB CONFIGSOURCE include/DtkCore/*) -foreach(FILENAME ${CONFIGSOURCE}) - get_filename_component(thefile ${FILENAME} NAME) - file(APPEND ${CONFIGNAME} "#define DTKCORE_CLASS_${thefile}\n") -endforeach() +include(dtkcore.cmake) diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 0000000..ea890af --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,11 @@ +Copyright (c) . + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt deleted file mode 100644 index 2071b23..0000000 --- a/LICENSES/MIT.txt +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 484359d..e1a345e 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,27 @@ Deepin Tool Kit (DtkCore) is the base development tool of all C++/Qt Developer w You should read the Deepin Application Specification firstly. +中文说明:[README.zh_CN.md](./README.zh_CN.md) + +## Document + +中文文档:[dtkcore文档](https://linuxdeepin.github.io/dtkcore/index.html) + ## Dependencies ### Build dependencies * Qt >= 5.10 +## Compile option + +| **Compile option** | **meaning** | **Default state** | +|--------------------|-------------|---------------| +| BUILD_DOCS | Compile document | ON | +| BUILD_TESTING | Compile test | Default is ON in debug mode | +| BUILD_EXAMPLES | Compile example | ON | +| BUILD_WITH_SYSTEMD | Support Systemd function | OFF | +| BUILD_THEME | Add themes to the document | OFF | ## Installation ### Build from source code diff --git a/README.zh_CN.md b/README.zh_CN.md index f395e04..da03ce7 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -4,12 +4,26 @@ Deepin Tool Kit Core(DtkCore) 是所有C++/Qt开发人员在Deepin上工作的 您应该首先阅读 Deepin应用程序规范. +## 文档 + +中文文档:[dtkcore文档](https://linuxdeepin.github.io/dtkcore/index.html) + ## 依赖 ### 编译依赖 * Qt >= 5.10 +## 编译选项 + +| **编译选项** | **含义** | **默认状态** | +|--------------------|-------------|---------------| +| BUILD_DOCS | 编译文档 | ON | +| BUILD_TESTING | 编译测试 | Debug模式下默认为ON | +| BUILD_EXAMPLES | 编译示例 | ON | +| BUILD_WITH_SYSTEMD | 支持Systmed功能 | OFF | +| BUILD_THEME | 为文档添加主题 | OFF | + ## 安装 ### 从源代码构建 diff --git a/archlinux/PKGBUILD b/archlinux/PKGBUILD index 5ee33de..749bc57 100644 --- a/archlinux/PKGBUILD +++ b/archlinux/PKGBUILD @@ -1,33 +1,42 @@ # Maintainer: justforlxz pkgname=dtkcore-git -pkgver=5.5.23.r5.g74f86b0 +pkgver=5.6.16 pkgrel=1 +sourcename=dtkcore +sourcetars=("$sourcename"_"$pkgver".tar.xz) +sourcedir="$sourcename" pkgdesc='DTK core modules' arch=('x86_64' 'aarch64') url="https://github.com/linuxdeepin/dtkcore" license=('LGPL3') -depends=('dconf' 'deepin-desktop-base-git' 'python' 'gsettings-qt' 'lshw') -makedepends=('git' 'qt5-tools' 'dtkcommon-git' 'ninja' 'cmake' 'doxygen') +depends=('deepin-desktop-base-git' 'gsettings-qt' 'dtkcommon-git' 'lshw' 'uchardet' 'icu' 'libsystemd' 'spdlog') +makedepends=('git' 'qt5-tools' 'ninja' 'cmake' 'doxygen') conflicts=('dtkcore') provides=('dtkcore') groups=('deepin-git') -source=('source.tar.gz') +source=("${sourcetars[@]}") sha512sums=('SKIP') build() { - cd $deepin_source_name - cmake -GNinja \ - -DMKSPECS_INSTALL_DIR=/usr/lib/qt/mkspecs/modules/\ - -DBUILD_DOCS=ON \ - -DBUILD_EXAMPLES=OFF \ - -DQCH_INSTALL_DESTINATION=/usr/share/doc/qt \ - -DCMAKE_INSTALL_LIBDIR=/usr/lib \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=Release + cd $sourcedir + version=$(echo $pkgver | awk -F'[+_~-]' '{print $1}') + cmake \ + -GNinja \ + -DMKSPECS_INSTALL_DIR=lib/qt/mkspecs/modules \ + -DBUILD_DOCS=ON \ + -DBUILD_WITH_SYSTEMD=ON \ + -DBUILD_EXAMPLES=OFF \ + -DQCH_INSTALL_DESTINATION=share/doc/qt \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_BUILD_TYPE=Release \ + -DD_DSG_APP_DATA_FALLBACK=/var/dsg/appdata \ + -DBUILD_WITH_SYSTEMD=ON \ + -DDTK_VERSION=$version ninja } package() { - cd $deepin_source_name + cd $sourcedir DESTDIR="$pkgdir" ninja install } diff --git a/cmake/DtkCMake/DtkCMakeConfig.cmake.in b/cmake/DtkCMake/DtkCMakeConfig.cmake.in new file mode 100644 index 0000000..c115ebc --- /dev/null +++ b/cmake/DtkCMake/DtkCMakeConfig.cmake.in @@ -0,0 +1,76 @@ +function(addDefinitions macro) + string(TOUPPER ${macro} macro) + add_definitions(-D${macro}) +endfunction() + +add_definitions(-DQ_HOST_NAME=\"${CMAKE_HOST_SYSTEM_PROCESSOR}\") +addDefinitions(Q_HOST_${CMAKE_HOST_SYSTEM_PROCESSOR}) + +find_package(Dtk@DTK_VERSION_MAJOR@Core REQUIRED) + +set(DEEPIN_OS_RELEASE_TOOL_PATH ${DtkCore_TOOL_DIRS}) +set(DEEPIN_OS_RELEASE_TOOL ${DEEPIN_OS_RELEASE_TOOL_PATH}/deepin-os-release) + +if(NOT EXISTS "${DEEPIN_OS_RELEASE_TOOL}") + message(FATAL_ERROR "\"${DEEPIN_OS_RELEASE_TOOL}\" is not exists. Install \"dtkcore-bin\" first") +endif() + +function(formatString string) + string(REGEX REPLACE "\\s+" "_" string ${string}) +endfunction() + +macro(execDeepinOsRelease args output) + exec_program(${DEEPIN_OS_RELEASE_TOOL} ARGS ${args} OUTPUT_VARIABLE ${output} RETURN_VALUE exitCode) + + if(NOT ${exitCode} EQUAL 0) + message(FATAL_ERROR "exec deepin-os-release failed, with args: ${args}, error message: ${output}") + endif() +endmacro() + +execDeepinOsRelease(--deepin-type DEEPIN_OS_TYPE) +execDeepinOsRelease(--deepin-version DEEPIN_OS_VERSION) +execDeepinOsRelease(--product-type CMAKE_PLATFORM_ID) +execDeepinOsRelease(--product-version CMAKE_PLATFORM_VERSION) + +if("${CMAKE_PLATFORM_ID}" STREQUAL "") + message(WARNING "No value of the \"--product-type\" in the process \"${DEEPIN_OS_RELEASE_TOOL}\"") +else() + formatString(CMAKE_PLATFORM_ID) + + message("OS: ${CMAKE_PLATFORM_ID}, Version: ${CMAKE_PLATFORM_VERSION}") + + if(NOT "${CMAKE_PLATFORM_ID}" STREQUAL "") + addDefinitions(Q_OS_${CMAKE_PLATFORM_ID}) + string(TOUPPER ${CMAKE_PLATFORM_ID} CMAKE_PLATFORM_ID) + set(OS_${CMAKE_PLATFORM_ID} TRUE) + endif() + + formatString(CMAKE_PLATFORM_VERSION) + add_definitions(-DQ_OS_VERSION=\"${CMAKE_PLATFORM_VERSION}\") + + #uos base with deepin + if("${CMAKE_PLATFORM_ID}" STREQUAL "UOS") + addDefinitions(Q_OS_DEEPIN) + set(OS_DEEPIN TRUE) + endif() +endif() + +if("${DEEPIN_OS_TYPE}" STREQUAL "") + message(WARNING "No value of the \"--deepin-type\" in the process \"${DEEPIN_OS_RELEASE_TOOL}\"") +else() + formatString(DEEPIN_OS_TYPE) + + message("Deepin OS Type: ${DEEPIN_OS_TYPE}") + message("Deepin OS Version: ${DEEPIN_OS_VERSION}") + + if(NOT "${DEEPIN_OS_TYPE}" STREQUAL "") + addDefinitions(Q_OS_DEEPIN_${DEEPIN_OS_TYPE}) + addDefinitions(DEEPIN_DDE) + string(TOUPPER ${DEEPIN_OS_TYPE} DEEPIN_OS_TYPE) + set(OS_DEEPIN_${DEEPIN_OS_TYPE} TRUE) + set(DEEPIN_DDE TRUE) + endif() + + formatString(DEEPIN_OS_VERSION) + add_definitions(-DQ_OS_DEEPIN_VERSION=\"${DEEPIN_OS_VERSION}\") +endif() diff --git a/cmake/DtkDConfig/DtkDConfigConfig.cmake b/cmake/DtkDConfig/DtkDConfigConfig.cmake new file mode 100644 index 0000000..bc23052 --- /dev/null +++ b/cmake/DtkDConfig/DtkDConfigConfig.cmake @@ -0,0 +1,101 @@ +# SPDX-FileCopyrightText: 2022 - 2023 Uniontech Software Technology Co.,Ltd. +# +# SPDX-License-Identifier: LGPL-3.0-or-later + +# This cmake file is used to deploy files that dconfig's meta and override configure. + +include(CMakeParseArguments) + +# get subpath according `FILE` and `BASE`. +# e.g: FILE = /a/b/c/d/foo.json, BASE = /a/b, then return SUBPATH = /c/d/ +function(get_subpath FILE BASE SUBPATH) + get_filename_component(BASE_FILE_PATH ${BASE} REALPATH) + get_filename_component(FILE_PATH ${FILE} REALPATH) + string(REPLACE ${BASE_FILE_PATH} "" SUBPATH_FILE_NAME ${FILE_PATH}) + get_filename_component(SUBPATH_PATH ${SUBPATH_FILE_NAME} DIRECTORY) + + set(${SUBPATH} ${SUBPATH_PATH} PARENT_SCOPE) +endfunction() + +if(NOT DEFINED DSG_DATA_DIR) + set(DSG_DATA_DIR ${CMAKE_INSTALL_PREFIX}/share/dsg) +endif() + +add_definitions(-DDSG_DATA_DIR=\"${DSG_DATA_DIR}\") +# deploy some `meta` 's configure. +# +# FILES - deployed files. +# BASE - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# APPID - working for the app. +# COMMONID - working for common. +# +# e.g: +# dtk_add_config_meta_files(APPID dconfigexample BASE ./configs FILES ./configs/example.json ./configs/a/example.json) +# +function(dtk_add_config_meta_files) + set(oneValueArgs BASE APPID COMMONID) + set(multiValueArgs FILES) + + cmake_parse_arguments(METAITEM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(_current_FILE ${METAITEM_FILES}) + set(SUBPATH "") + if (DEFINED METAITEM_BASE) + GET_SUBPATH(${_current_FILE} ${METAITEM_BASE} SUBPATH) + endif() + + if (DEFINED METAITEM_APPID) + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/${METAITEM_APPID}/${SUBPATH}) + elseif (DEFINED METAITEM_COMMONID) + install(FILES ${_current_FILE} DESTINATION ${DSG_DATA_DIR}/configs/${SUBPATH}) + else() + message(FATAL_ERROR "Please set APPID or COMMONID for the meta item." ${_current_FILE}) + endif() + endforeach() +endfunction() + + +# deploy some `meta` 's override configure. +# +# configuration for the `meta_name` 's override configure. +# +# FILES - deployed files. +# BASE - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# APPID - working for the app, if it's empty, working for all app. +# META_NAME - override for the meta configure. +# +# e.g : +#dtk_add_config_override_files(APPID dconfigexample BASE ./configs META_NAME example FILES ./configs/dconf-example.override.json ./configs/a/dconf-example.override.a.json) +# +function(dtk_add_config_override_files) + set(options) + set(oneValueArgs BASE APPID META_NAME) + set(multiValueArgs FILES) + + cmake_parse_arguments(OVERRIDEITEM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT DEFINED OVERRIDEITEM_META_NAME) + message(FATAL_ERROR "Please set meta_name for the override configuration." ${FILES}) + endif() + + foreach(_current_FILE ${OVERRIDEITEM_FILES}) + set(SUBPATH "") + if (DEFINED OVERRIDEITEM_BASE) + GET_SUBPATH(${_current_FILE} ${OVERRIDEITEM_BASE} SUBPATH) + endif() + + if (DEFINED OVERRIDEITEM_APPID) + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/overrides/${OVERRIDEITEM_APPID}/${OVERRIDEITEM_META_NAME}/${SUBPATH}) + else() + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/overrides/${OVERRIDEITEM_META_NAME}/${SUBPATH}) + endif() + endforeach() +endfunction() + +# deprecated since dtk6 +function(dconfig_meta_files) + dtk_add_config_meta_files(${ARGV}) +endfunction() +function(dconfig_override_files) + dtk_add_config_override_files(${ARGV}) +endfunction() diff --git a/cmake/DtkDConfig/DtkDConfigConfig.cmake.in b/cmake/DtkDConfig/DtkDConfigConfig.cmake.in new file mode 100644 index 0000000..689c1b5 --- /dev/null +++ b/cmake/DtkDConfig/DtkDConfigConfig.cmake.in @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: 2022 - 2023 Uniontech Software Technology Co.,Ltd. +# +# SPDX-License-Identifier: LGPL-3.0-or-later + +# This cmake file is used to deploy files that dconfig's meta and override configure. + +include(CMakeParseArguments) + +# get subpath according `FILE` and `BASE`. +# e.g: FILE = /a/b/c/d/foo.json, BASE = /a/b, then return SUBPATH = /c/d/ +function(get_subpath FILE BASE SUBPATH) + get_filename_component(BASE_FILE_PATH ${BASE} REALPATH) + get_filename_component(FILE_PATH ${FILE} REALPATH) + string(REPLACE ${BASE_FILE_PATH} "" SUBPATH_FILE_NAME ${FILE_PATH}) + get_filename_component(SUBPATH_PATH ${SUBPATH_FILE_NAME} DIRECTORY) + + set(${SUBPATH} ${SUBPATH_PATH} PARENT_SCOPE) +endfunction() + +if(NOT DEFINED DSG_DATA_DIR) + set(DSG_DATA_DIR ${CMAKE_INSTALL_PREFIX}/share/dsg) +endif() + +add_definitions(-DDSG_DATA_DIR=\"${DSG_DATA_DIR}\") +# deploy some `meta` 's configure. +# +# FILES - deployed files. +# BASE - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# APPID - working for the app. +# COMMONID - working for common. +# +# e.g: +# dtk_add_config_meta_files(APPID dconfigexample BASE ./configs FILES ./configs/example.json ./configs/a/example.json) +# +function(dtk_add_config_meta_files) + set(oneValueArgs BASE APPID COMMONID) + set(multiValueArgs FILES) + + cmake_parse_arguments(METAITEM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(_current_FILE ${METAITEM_FILES}) + set(SUBPATH "") + if (DEFINED METAITEM_BASE) + GET_SUBPATH(${_current_FILE} ${METAITEM_BASE} SUBPATH) + endif() + + if (DEFINED METAITEM_APPID) + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/${METAITEM_APPID}/${SUBPATH}) + elseif (DEFINED METAITEM_COMMONID) + install(FILES ${_current_FILE} DESTINATION ${DSG_DATA_DIR}/configs/${SUBPATH}) + else() + message(FATAL_ERROR "Please set APPID or COMMONID for the meta item." ${_current_FILE}) + endif() + endforeach() +endfunction() + + +# deploy some `meta` 's override configure. +# +# configuration for the `meta_name` 's override configure. +# +# FILES - deployed files. +# BASE - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# APPID - working for the app, if it's empty, working for all app. +# META_NAME - override for the meta configure. +# +# e.g : +#dtk_add_config_override_files(APPID dconfigexample BASE ./configs META_NAME example FILES ./configs/dconf-example.override.json ./configs/a/dconf-example.override.a.json) +# +function(dtk_add_config_override_files) + set(options) + set(oneValueArgs BASE APPID META_NAME) + set(multiValueArgs FILES) + + cmake_parse_arguments(OVERRIDEITEM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT DEFINED OVERRIDEITEM_META_NAME) + message(FATAL_ERROR "Please set meta_name for the override configuration." ${FILES}) + endif() + + foreach(_current_FILE ${OVERRIDEITEM_FILES}) + set(SUBPATH "") + if (DEFINED OVERRIDEITEM_BASE) + GET_SUBPATH(${_current_FILE} ${OVERRIDEITEM_BASE} SUBPATH) + endif() + + if (DEFINED OVERRIDEITEM_APPID) + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/overrides/${OVERRIDEITEM_APPID}/${OVERRIDEITEM_META_NAME}/${SUBPATH}) + else() + install(FILES "${_current_FILE}" DESTINATION ${DSG_DATA_DIR}/configs/overrides/${OVERRIDEITEM_META_NAME}/${SUBPATH}) + endif() + endforeach() +endfunction() + +@DCONFIG_DEPRECATED_FUNCS@ diff --git a/cmake/DtkTools/DtkDBusMacros.cmake b/cmake/DtkTools/DtkDBusMacros.cmake new file mode 100644 index 0000000..296b24d --- /dev/null +++ b/cmake/DtkTools/DtkDBusMacros.cmake @@ -0,0 +1,79 @@ +# Copyright 2005-2011 Kitware, Inc. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +include(MacroAddFileDependencies) +include(CMakeParseArguments) + +function(dtk_add_dbus_interface _sources _interface _relativename) + get_filename_component(_infile ${_interface} ABSOLUTE) + get_filename_component(_basepath ${_relativename} DIRECTORY) + get_filename_component(_basename ${_relativename} NAME) + set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.h") + set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.cpp") + + if(${QT_VERSION_MAJOR} EQUAL "5") + if(_basepath) + set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/${_basename}.moc") + else() + set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc") + endif() + else() + if(_basepath) + set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/moc_${_basename}.cpp") + else() + set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp") + endif() + endif() + + get_source_file_property(_nonamespace ${_interface} NO_NAMESPACE) + if(_nonamespace) + set(_params -N -m) + else() + set(_params -m) + endif() + + get_source_file_property(_skipincludeannotations ${_interface} SKIP_INCLUDE_ANNOTATIONS) + if(_skipincludeannotations) + set(_params ${_params} -S) + endif() + + get_source_file_property(_classname ${_interface} CLASSNAME) + if(_classname) + set(_params ${_params} -c ${_classname}) + endif() + + get_source_file_property(_include ${_interface} INCLUDE) + if(_include) + set(_params ${_params} -i ${_include}) + endif() + + add_custom_command(OUTPUT "${_impl}" "${_header}" + COMMAND ${DTK_XML2CPP} ${_params} -p ${_relativename} ${_infile} + DEPENDS ${_infile} ${DTK_XML2CPP} + VERBATIM + ) + + set_source_files_properties("${_impl}" "${_header}" PROPERTIES + SKIP_AUTOMOC TRUE + SKIP_AUTOUIC TRUE + ) + + qt_generate_moc("${_header}" "${_moc}") + + list(APPEND ${_sources} "${_impl}" "${_header}") + set_property(SOURCE "${_impl}" APPEND PROPERTY OBJECT_DEPENDS "${_moc}") + set(${_sources} ${${_sources}} PARENT_SCOPE) +endfunction() + +function(dtk_add_dbus_interfaces _sources) + foreach(_current_FILE ${ARGN}) + get_filename_component(_infile ${_current_FILE} ABSOLUTE) + get_filename_component(_basename ${_current_FILE} NAME) + # get the part before the ".xml" suffix + string(TOLOWER ${_basename} _basename) + string(REGEX REPLACE "(.*\\.)?([^\\.]+)\\.xml" "\\2" _basename ${_basename}) + dtk_add_dbus_interface(${_sources} ${_infile} ${_basename}interface) + endforeach() + set(${_sources} ${${_sources}} PARENT_SCOPE) +endfunction() diff --git a/cmake/DtkTools/DtkSettingsToolsMacros.cmake b/cmake/DtkTools/DtkSettingsToolsMacros.cmake index da1cd10..15b986c 100644 --- a/cmake/DtkTools/DtkSettingsToolsMacros.cmake +++ b/cmake/DtkTools/DtkSettingsToolsMacros.cmake @@ -32,12 +32,12 @@ #============================================================================= function(DTK_CREATE_I18N_FROM_JSON _generated_file_list _input_json_file _output_cpp_file_name) - set (generated_file_list) # 0(failed) or 1(successed) files in the list. + set (generated_file_list) # 0(failed) or 1(succeeded) files in the list. get_filename_component(_input_json_abs_path ${_input_json_file} ABSOLUTE) get_filename_component(_input_json_abs_dir ${_input_json_abs_path} DIRECTORY) set (_output_cpp_abs_path ${_input_json_abs_dir}/${_output_cpp_file_name}) - + if (DTK_SETTINGS_TOOLS_FOUND) add_custom_command(OUTPUT ${_output_cpp_abs_path} COMMAND ${DTK_SETTINGS_TOOLS_EXECUTABLE} @@ -46,7 +46,7 @@ function(DTK_CREATE_I18N_FROM_JSON _generated_file_list _input_json_file _output list(APPEND generated_file_list ${_output_cpp_abs_path}) else () message (WARNING "The dtk-settings tools could not be found at ${DTK_SETTINGS_TOOLS_EXECUTABLE}") - message (WARNING "Package distributor may create a seprated package for tools like `libdtkcore-bin`.") + message (WARNING "Package distributor may create a separated package for tools like `libdtkcore-bin`.") endif () set(${_generated_file_list} ${generated_file_list} PARENT_SCOPE) diff --git a/cmake/DtkTools/DtkToolsConfig.cmake b/cmake/DtkTools/DtkToolsConfig.cmake deleted file mode 100644 index 49b1f5e..0000000 --- a/cmake/DtkTools/DtkToolsConfig.cmake +++ /dev/null @@ -1,9 +0,0 @@ -find_package(DtkCore REQUIRED) - -set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DtkCore_TOOL_DIRS}/dtk-settings) - -if (EXISTS ${DTK_SETTINGS_TOOLS_EXECUTABLE}) - set(DTK_SETTINGS_TOOLS_FOUND TRUE) -endif () - -include("${CMAKE_CURRENT_LIST_DIR}/DtkSettingsToolsMacros.cmake") \ No newline at end of file diff --git a/cmake/DtkTools/DtkToolsConfig.cmake.in b/cmake/DtkTools/DtkToolsConfig.cmake.in new file mode 100644 index 0000000..b3a14f1 --- /dev/null +++ b/cmake/DtkTools/DtkToolsConfig.cmake.in @@ -0,0 +1,14 @@ +include(CMakeFindDependencyMacro) +find_dependency(Dtk@DTK_VERSION_MAJOR@Core REQUIRED) + +set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DtkCore_TOOL_DIRS}/dtk-settings) + +if (EXISTS ${DTK_SETTINGS_TOOLS_EXECUTABLE}) + set(DTK_SETTINGS_TOOLS_FOUND TRUE) +endif () + +include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@SettingsToolsMacros.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@ToolsTargets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/DtkDBusMacros.cmake") + +get_target_property(DTK_XML2CPP Dtk@DTK_VERSION_MAJOR@::Xml2Cpp LOCATION) diff --git a/debian/changelog b/debian/changelog index a62246e..68b83c2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,289 @@ +dtkcore (5.7.4) unstable; urgency=medium + + * fix: hasVtable is incorrect when destructing + + -- Deepin Packages Builder Tue, 03 Dec 2024 02:00:45 +0000 + +dtkcore (5.7.3) unstable; urgency=medium + + [ root ] + * UNRELEASED + + -- Deepin Packages Builder Wed, 20 Nov 2024 02:19:06 +0000 + +dtkcore (5.7.2) unstable; urgency=medium + + [ root ] + * UNRELEASED + + -- Deepin Packages Builder Wed, 13 Nov 2024 01:53:26 +0000 + +dtkcore (5.7.1) unstable; urgency=medium + + * feat: 增加智能终端设备类型 (#434) + Thanks to Whale107 + * fix: remove unnecessary link libraries + * fix: DDBusInterface signal loss + * fix(util): error appid from `getAppIdFromAbsolutePath` + + -- Deepin Packages Builder Wed, 16 Oct 2024 03:30:45 +0000 + +dtkcore (5.6.34) unstable; urgency=medium + + [ root ] + * UNRELEASED + + -- Deepin Packages Builder Tue, 20 Aug 2024 05:03:51 +0000 + +dtkcore (5.6.32) unstable; urgency=medium + + * refactor: log files move to dtklog(Issue: #182) + + -- Deepin Packages Builder Mon, 08 Jul 2024 02:29:21 +0000 + +dtkcore (5.6.31) unstable; urgency=medium + + * chore: use '&&' and '||' instead of 'and' and 'or' + + -- Deepin Packages Builder Thu, 27 Jun 2024 09:11:34 +0000 + +dtkcore (5.6.30) unstable; urgency=medium + + * feat: 允许基于dtk开发的应用动态控制其日志输出等级(Task: 307567)(Influence: 允许基于dtk开发的应用动态控制其日志输出等级) + * fix: lshw查询内存大小时返回多元素数组,修正解析过程(Bug: 228681)(Influence: DSysInfo::memoryInstalledSize解析过程) + * fix: 从文件中读取deepinType和productType值时因为权限问题会失败(Influence: 正常显示版本和说明) + * feat: 增加registerLoggingRulesWatcher接口(Task: 303379) + * fix: 修复计算 build 版本号错误的问题(Influence: 构建版本号(BUILD_VERSION )) + * feat: DeepinType类型增加军用版(Task: 316703)(Influence: DeepinType类型) + * fix: 修复日志格式时间戳显示异常问题(Bug: 236239)(Influence: 使用DLogManager的应用日志输出格式) + * chore: loggingrules config move to preference + * refactor: remove LoggingRules interface + * fix: crashed when access DSGApplication::id early + * chore: fallback to dsgconfig value + * fix(build): build faild on Qt 6.7.1 + + -- Deepin Packages Builder Thu, 30 May 2024 02:46:32 +0000 + +dtkcore (5.6.29) unstable; urgency=medium + + * chore: remove warning for dbusxml2cpp in qt6 + + -- Deepin Packages Builder Mon, 13 May 2024 03:02:53 +0000 + +dtkcore (5.6.28) unstable; urgency=medium + + * fix: fix undefined reference errors on spdlog 1.14.0 + Thanks to hillwoodroc + + -- Deepin Packages Builder Mon, 29 Apr 2024 08:23:39 +0000 + +dtkcore (5.6.27) unstable; urgency=medium + + * fix: lossing value when save DConfig + * fix(qdbusxml2cpp): support qt 6.7 + + -- Deepin Packages Builder Fri, 19 Apr 2024 08:55:35 +0000 + +dtkcore (5.6.26) unstable; urgency=medium + + [ root ] + * UNRELEASED + + -- Deepin Packages Builder Tue, 26 Mar 2024 05:47:35 +0000 + +dtkcore (5.6.25) unstable; urgency=medium + + * chore: fix docs typo + * feat: support to set appId for DConfig + * fix: DConfig add check for name(Issue: #1211374) + + -- Deepin Packages Builder Mon, 11 Mar 2024 01:16:26 +0000 + +dtkcore (5.6.22) unstable; urgency=medium + + * Release 5.6.22 + + -- Deepin Packages Builder Wed, 10 Jan 2024 02:30:59 +0000 + +dtkcore (5.6.21) unstable; urgency=medium + + * fix: app blocked when AM is unavailable + * chore: remove decltype(auto) for dutil + * chore: fix relative path invalid link + * feat: allow skip including headers of annotations(Issue: #147) + + -- Deepin Packages Builder Tue, 09 Jan 2024 01:45:43 +0000 + +dtkcore (5.6.20) unstable; urgency=medium + + * feat: add utils function + * chore: Implement DSGApplication::getId + * feat(dstandardpaths): add XDG_STATE_HOME + * chore: keep order when deduplication + * fix: log files limit not work + * chore: add dtk dbus generate function + + -- Deepin Packages Builder Tue, 28 Nov 2023 05:40:53 +0000 + +dtkcore (5.6.19) unstable; urgency=medium + + * fix: Type error for qdbusxml2cpp + * fix: correct Dtk6SettingsToolsMacros.cmake path + * chore: add flag UserPublic(Issue: https://github.com/linuxdeepin/developer-center/issues/5928) + + -- Deepin Packages Builder Mon, 23 Oct 2023 07:33:19 +0000 + +dtkcore (5.6.18) unstable; urgency=medium + + * fix: Can't clear cache when reset for DConfig in FileBackend + * feat: Add isDefaultValue for DConfig(Issue: #3) + * fix: Compiling failed in lower libspdlog-dev + * fix: missing parameter passing for synchronization + * fix(build): skip failed unit test + * chore(tools): show help if argc < 2 + * fix: Compiling failed in libspdlog-dev before 1.4.0 + Thanks to Shiroko + * fix: cmake failure when env is null + * chore: correct typos in DtkSettingsToolsMacros.cmake + Thanks to Felix Yan + * chore: dpinyin tweak(Issue: #109) + + -- Deepin Packages Builder Wed, 18 Oct 2023 06:01:45 +0000 + +dtkcore (5.6.17) unstable; urgency=medium + + * Release 5.6.17 + + -- Deepin Packages Builder Fri, 08 Sep 2023 15:12:36 +0800 + +dtkcore (5.6.16) unstable; urgency=medium + + * fix: FileAppender log level not set + * chore: ut linked dtkcore instead of source code + * chore: tweak CMakeLists + * chore: support Qt 6.4 build + * chore: qch docs tweak + * chore: add DtkBuildHelper depends + * chore: console with color at tty + * fix: missing dependency qttools5-dev + * feat: add synchronization workflow + + -- Deepin Packages Builder Tue, 22 Aug 2023 06:13:45 +0000 + +dtkcore (5.6.15) unstable; urgency=medium + + * chore: dlog example tweak + + -- Yixue Wang Fri, 11 Aug 2023 13:42:20 +0800 + +dtkcore (5.6.14) unstable; urgency=medium + + * chore: function need to be marked as override + * chore: ignore doxygen-theme folder + Thanks to Skye-rs + * chore: change OUTPUT_DIR variable in cmake + * chore: remove unused pro files + * refactor!: deprecate some interfaces in dtk6 + * fix: updateProp cannot convert to property type + * fix: typo in xdg + * chore: reduce compilation warnings + Thanks to SPUER(Issue: #96) + * chore(dcapmanager): RuntimeTime -> RuntimeDir + * chore: Sync by https://github.com/linuxdeepin/.github/commit/559e91167d4919644f37bbcf123eb0651c1528ea(Influence: none) + * chore: make test-recoverage.sh runable again + * chore: add ut for DDbusSender + * feat: add systembus send support + * fix: internalPropSet nerver emit propertyChanged + * chore: should include QVector headers + * chore: dsysinfo tweak + * chore: add some unit test + + -- Deepin Packages Builder Thu, 27 Jul 2023 06:56:33 +0000 + +dtkcore (5.6.13) unstable; urgency=medium + + * feat: DConfig add check for no existed item when override + * fix(cmake): wrong use of option and wrong macro + * fix: calling delay in DDBusSender(Issue: https://github.com/linuxdeepin/developer-center/issues/4415) + * feat: DConfig add check for subpath(Issue: #54) + * feat: DConfig exports metadir's implementation(Issue: #10) + * fix(dccinterface): fix cannot get the right type + * fix: DConfig's `subpathIsValid` produces error + * fix(ut): failed ut + * fix(build): build faild on Qt6 + * fix: fix build failed due to gcc compiler bug + * fix: ut_dfilewater failed on Qt6 + * fix: DTextEncoding ut failed in Qt6. + * fix: fix DTextEncoding warnings. + * feat: support dtk6core build + * feat: add DThreadUtils class + * fix: move Qt CorePrivate to target private link + * fix: qdbusxml2cpp-fix not in path + * chore: remove ddbusinterface property cache + * chore: remove libdtkcommon depends + + -- Deepin Packages Builder Sun, 25 Jun 2023 14:40:49 +0800 + +dtkcore (5.6.12) unstable; urgency=medium + + * Release 5.6.12 + * add DLicenseInfo + * cached memoryInstalledSize + * FIX developer-center#4348 + + -- Deepin Packages Builder Mon, 15 May 2023 11:18:15 +0800 + +dtkcore (5.6.11) unstable; urgency=medium + + * Release 5.6.11 + * add color to ConsoleAppender + * remove build warning + + -- Deepin Packages Builder Mon, 08 May 2023 11:48:45 +0800 + +dtkcore (5.6.10) unstable; urgency=medium + + * Release 5.6.10 + * support XDG_SESSION_DESKTOP set to DDE + + -- Deepin Packages Builder Mon, 17 Apr 2023 17:08:28 +0800 + +dtkcore (5.6.9) unstable; urgency=medium + + * Release 5.6.9 + + -- Deepin Packages Builder Mon, 03 Apr 2023 09:48:07 +0800 + +dtkcore (5.6.8) unstable; urgency=medium + + * Release 5.6.8 + + -- Deepin Packages Builder Wed, 22 Feb 2023 14:09:56 +0800 + +dtkcore (5.6.6) unstable; urgency=medium + + * Release 5.6.6 + + -- Deepin Packages Builder Tue, 21 Feb 2023 12:25:24 +0800 + +dtkcore (5.6.5) unstable; urgency=medium + + * Release 5.6.5 + + -- Deepin Packages Builder Thu, 02 Feb 2023 14:25:36 +0800 + +dtkcore (5.6.4) unstable; urgency=medium + + * Release 5.6.4 + + -- Deepin Packages Builder Fri, 06 Jan 2023 16:30:40 +0800 + +dtkcore (5.6.3) unstable; urgency=medium + + * Release 5.6.3 + + -- Deepin Packages Builder Mon, 12 Dec 2022 14:40:31 +0800 + dtkcore (5.6.2.2) unstable; urgency=medium * release 5.6.2.2 @@ -42,6 +328,6 @@ dtkcore (2.0.8) unstable; urgency=medium dtkcore (0.3.3-1) unstable; urgency=medium - * Initial release + * Initial release -- Deepin Packages Builder Mon, 10 Oct 2016 16:58:07 +0800 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/debian/control b/debian/control index c4727bd..51da329 100644 --- a/debian/control +++ b/debian/control @@ -2,14 +2,15 @@ Source: dtkcore Section: libdevel Priority: optional Maintainer: Deepin Packages Builder -Build-Depends: debhelper (>= 9), pkg-config, - qttools5-dev-tools, qtbase5-private-dev, doxygen, - libgsettings-qt-dev, libgtest-dev, libdtkcommon-dev, cmake +Build-Depends: debhelper-compat ( =12), pkg-config, + qttools5-dev-tools, qttools5-dev, qtbase5-private-dev, doxygen, + libgsettings-qt-dev, libgtest-dev, libdtkcommon-dev, cmake, + libuchardet-dev, libicu-dev, libdtklog-dev Standards-Version: 3.9.8 Package: libdtkcore5 Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, lshw, libdtkcommon +Depends: ${shlibs:Depends}, ${misc:Depends}, lshw Multi-Arch: same Description: Deepin Tool Kit Core library DtkCore is base library of Deepin Qt/C++ applications. @@ -27,7 +28,8 @@ Description: Deepin Tool Kit Core Utilities Package: libdtkcore-dev Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkcore5( =${binary:Version}), libdtkcommon-dev +Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkcore5( =${binary:Version}), + libdtkcommon-dev(>=5.6.16), libdtklog-dev Description: Deepin Tool Kit Core Devel library DtkCore is base devel library of Deepin Qt/C++ applications. . @@ -39,4 +41,3 @@ Description: Deepin Tool Kit Core (document) DtkCore is base devel library of Deepin Qt/C++ applications. . This package contains the doc files of DtkCore - diff --git a/debian/libdtkcore5-bin.install b/debian/libdtkcore5-bin.install index 0b8a68c..643e56c 100644 --- a/debian/libdtkcore5-bin.install +++ b/debian/libdtkcore5-bin.install @@ -1,2 +1 @@ -usr/lib/*/*/DCore/bin/* -usr/bin/* \ No newline at end of file +usr/*/*/DCore/bin/* \ No newline at end of file diff --git a/debian/missing-sources/doxygen-awesome-darkmode-toggle.js b/debian/missing-sources/doxygen-awesome-darkmode-toggle.js deleted file mode 100644 index 05ae338..0000000 --- a/debian/missing-sources/doxygen-awesome-darkmode-toggle.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2021 - 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -class DoxygenAwesomeDarkModeToggle extends HTMLElement { - // SVG icons from https://fonts.google.com/icons - // Licensed under the Apache 2.0 license: - // https://www.apache.org/licenses/LICENSE-2.0.html - static lightModeIcon = `` - static darkModeIcon = `` - static title = "Toggle Light/Dark Mode" - - static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" - static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" - - static _staticConstructor = function () { - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) - // Update the color scheme when the browsers preference changes - // without user interaction on the website. - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { - DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() - }) - // Update the color scheme when the tab is made visible again. - // It is possible that the appearance was changed in another tab - // while this tab was in the background. - document.addEventListener("visibilitychange", visibilityState => { - if (document.visibilityState === 'visible') { - DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() - } - }); - }() - - static init() { - $(function () { - $(document).ready(function () { - const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') - toggleButton.title = DoxygenAwesomeDarkModeToggle.title - toggleButton.updateIcon() - - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { - toggleButton.updateIcon() - }) - document.addEventListener("visibilitychange", visibilityState => { - if (document.visibilityState === 'visible') { - toggleButton.updateIcon() - } - }); - - $(document).ready(function () { - document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) - }) - $(window).resize(function () { - document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) - }) - }) - }) - } - - constructor() { - super(); - this.onclick = this.toggleDarkMode - } - - /** - * @returns `true` for dark-mode, `false` for light-mode system preference - */ - static get systemPreference() { - return window.matchMedia('(prefers-color-scheme: dark)').matches - } - - /** - * @returns `true` for dark-mode, `false` for light-mode user preference - */ - static get userPreference() { - return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || - (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) - } - - static set userPreference(userPreference) { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference - if (!userPreference) { - if (DoxygenAwesomeDarkModeToggle.systemPreference) { - localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) - } else { - localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) - } - } else { - if (!DoxygenAwesomeDarkModeToggle.systemPreference) { - localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) - } else { - localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) - } - } - DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() - } - - static enableDarkMode(enable) { - if (enable) { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = true - document.documentElement.classList.add("dark-mode") - document.documentElement.classList.remove("light-mode") - } else { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = false - document.documentElement.classList.remove("dark-mode") - document.documentElement.classList.add("light-mode") - } - } - - static onSystemPreferenceChanged() { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) - } - - static onUserPreferenceChanged() { - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) - } - - toggleDarkMode() { - DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference - this.updateIcon() - } - - updateIcon() { - if (DoxygenAwesomeDarkModeToggle.darkModeEnabled) { - this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon - } else { - this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon - } - } -} - -customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); diff --git a/debian/rules b/debian/rules index a216f3b..f618c0b 100755 --- a/debian/rules +++ b/debian/rules @@ -8,15 +8,21 @@ DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) VERSION = $(DEB_VERSION_UPSTREAM) PACK_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$1}') -# Fix: invalid digit "8" in octal constant. e.g. u008 ==> 008 ==> 8 -BUILD_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$2}' | sed 's/[^0-9]//g' | awk '{print int($$1)}') +# Calculate build version: +# 5.6.8 -> 0; 5.6.8.7 -> 7; 5.6.8+u001 -> 1; 5.6.8.7+u001 -> 7; 5.6.8.0+u001 -> 0 +BUILD_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$1}' | awk -F'.' '{print $$4}' | sed 's/[^0-9]//g' | awk '{print int($$1)}') +ifeq ($(BUILD_VER), 0) +ifeq ($(shell expr $(shell echo "$(VERSION)" | awk -F. '{print NF-1}') '<' 3), 1) + BUILD_VER=$(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$2}' | sed 's/[^0-9]//g' | awk '{print int($$1)}') +endif +endif %: - dh $@ --parallel + dh $@ override_dh_auto_configure: - dh_auto_configure -- -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=ON -DBUILD_VERSION=$(BUILD_VER) -DDVERSION=$(PACK_VER) + dh_auto_configure -- -DBUILD_WITH_SYSTEMD=ON -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=ON -DBUILD_VERSION=$(BUILD_VER) -DDTK_VERSION=$(PACK_VER) -DD_DSG_APP_DATA_FALLBACK=/var/dsg/appdata #override_dh_auto_test: # echo "skip auto test" diff --git a/debian/symbols.amd64 b/debian/symbols.amd64 deleted file mode 100644 index 502b661..0000000 --- a/debian/symbols.amd64 +++ /dev/null @@ -1,909 +0,0 @@ -libdtkcore.so.5 libdtkcore5 #MINVER# - _Z19qInitResources_utilv@Base 5.0.3 - _Z22qCleanupResources_utilv@Base 5.0.3 - _ZGVZN3Dtk4Core11DLogManager8instanceEvE8instance@Base 5.0.3 - _ZN10QByteArrayD1Ev@Base 5.0.3 - _ZN10QByteArrayD2Ev@Base 5.0.3 - _ZN11DDBusCaller3argI7QStringEES_RKT_@Base 5.0.3 - _ZN11DDBusCaller4callEv@Base 5.0.3 - _ZN11DDBusCallerC1ERK7QStringSt10shared_ptrI9DDBusDataE@Base 5.0.3 - _ZN11DDBusCallerC2ERK7QStringSt10shared_ptrI9DDBusDataE@Base 5.0.3 - _ZN11DDBusCallerD1Ev@Base 5.0.3 - _ZN11DDBusCallerD2Ev@Base 5.0.3 - _ZN11DDBusSender4pathERK7QString@Base 5.0.3 - _ZN11DDBusSender4typeEN15QDBusConnection7BusTypeE@Base 5.0.3 - _ZN11DDBusSender6methodERK7QString@Base 5.0.3 - _ZN11DDBusSender7serviceERK7QString@Base 5.0.3 - _ZN11DDBusSender8propertyERK7QString@Base 5.0.3 - _ZN11DDBusSender9interfaceERK7QString@Base 5.0.3 - _ZN11DDBusSenderC1Ev@Base 5.0.3 - _ZN11DDBusSenderC2Ev@Base 5.0.3 - _ZN12QWeakPointerI7QObjectED1Ev@Base 5.0.3 - _ZN12QWeakPointerI7QObjectED2Ev@Base 5.0.3 - _ZN13DDBusProperty3getEv@Base 5.0.3 - _ZN13DDBusPropertyC1ERK7QStringSt10shared_ptrI9DDBusDataE@Base 5.0.3 - _ZN13DDBusPropertyC2ERK7QStringSt10shared_ptrI9DDBusDataE@Base 5.0.3 - _ZN14QScopedPointerIN3Dtk4Core23GSettingsBackendPrivateE21QScopedPointerDeleterIS2_EED1Ev@Base 5.0.3 - _ZN14QScopedPointerIN3Dtk4Core23GSettingsBackendPrivateE21QScopedPointerDeleterIS2_EED2Ev@Base 5.0.3 - _ZN15QVarLengthArrayIcLi4096EEC1Ei@Base 5.0.3 - _ZN15QVarLengthArrayIcLi4096EEC2Ei@Base 5.0.3 - _ZN3Dtk4Core10doUnescapeER7QStringRK5QHashI5QCharS4_E@Base 5.0.3 - _ZN3Dtk4Core11DLogManager12setLogFormatERK7QString@Base 5.0.3 - _ZN3Dtk4Core11DLogManager14getlogFilePathEv@Base 5.0.3 - _ZN3Dtk4Core11DLogManager14setlogFilePathERK7QString@Base 5.0.3 - _ZN3Dtk4Core11DLogManager19initConsoleAppenderEv@Base 5.0.3 - _ZN3Dtk4Core11DLogManager20registerFileAppenderEv@Base 5.0.3 - _ZN3Dtk4Core11DLogManager23initRollingFileAppenderEv@Base 5.0.3 - _ZN3Dtk4Core11DLogManager23registerConsoleAppenderEv@Base 5.0.3 - _ZN3Dtk4Core11DLogManager8joinPathERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core11DLogManagerC1Ev@Base 5.0.3 - _ZN3Dtk4Core11DLogManagerC2Ev@Base 5.0.3 - _ZN3Dtk4Core11DLogManagerD1Ev@Base 5.0.3 - _ZN3Dtk4Core11DLogManagerD2Ev@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook10copyVtableEPPy@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook11originalFunEPKvy@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook11resetVtableEPKv@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook12ensureVtableEPKvSt8functionIFvvEE@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook13resetVfptrFunEPKvy@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook14objDestructFunE@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook15autoCleanVtableEPKv@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook15objToGhostVfptrE@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook16clearGhostVtableEPKv@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook16forceWriteMemoryEPvPKvm@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook18objToOriginalVfptrE@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook19getDestructFunIndexEPPySt8functionIFvvEE@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook7resolveEPKc@Base 5.0.3 - _ZN3Dtk4Core11DVtableHook9hasVtableEPKv@Base 5.0.3 - _ZN3Dtk4Core11unqtifyNameERK7QString@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher11onFileMovedERK7QStringS4_S4_S4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher12onFileClosedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher13onFileCreatedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher13onFileDeletedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher14onFileModifiedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcher22onFileAttributeChangedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcherC1ERK7QStringP7QObject@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcherC2ERK7QStringP7QObject@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcherD0Ev@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcherD1Ev@Base 5.0.3 - _ZN3Dtk4Core12DFileWatcherD2Ev@Base 5.0.3 - _ZN3Dtk4Core12FileAppender11setFileNameERK7QString@Base 5.0.3 - _ZN3Dtk4Core12FileAppender6appendERK9QDateTimeNS0_6Logger8LogLevelEPKciS8_RK7QStringSB_@Base 5.0.3 - _ZN3Dtk4Core12FileAppender8openFileEv@Base 5.0.3 - _ZN3Dtk4Core12FileAppender9closeFileEv@Base 5.0.3 - _ZN3Dtk4Core12FileAppenderC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core12FileAppenderC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core12FileAppenderD0Ev@Base 5.0.3 - _ZN3Dtk4Core12FileAppenderD1Ev@Base 5.0.3 - _ZN3Dtk4Core12FileAppenderD2Ev@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry10escapeExecER7QString@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry11removeEntryERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry11setRawValueERK7QStringS4_S4_@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry12unescapeExecER7QString@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry14setStringValueERK7QStringS4_S4_@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry17setLocalizedValueERK7QStringS4_S4_S4_@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry6escapeER7QString@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry8unescapeER7QStringb@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntry9setStatusERKNS1_6StatusE@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntryC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntryC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntryD1Ev@Base 5.0.3 - _ZN3Dtk4Core13DDesktopEntryD2Ev@Base 5.0.3 - _ZN3Dtk4Core13DFileServices10showFolderE4QUrlRK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices10showFolderE7QStringRKS2_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices11showFoldersE5QListI4QUrlERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices11showFoldersE5QListI7QStringERKS3_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices12errorMessageEv@Base 5.0.3 - _ZN3Dtk4Core13DFileServices12showFileItemE4QUrlRK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices12showFileItemE7QStringRKS2_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices13showFileItemsE5QListI4QUrlERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices13showFileItemsE5QListI7QStringERKS3_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices21showFileItemPropertieE4QUrlRK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices21showFileItemPropertieE7QStringRKS2_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices22showFileItemPropertiesE5QListI4QUrlERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DFileServices22showFileItemPropertiesE5QListI7QStringERKS3_@Base 5.0.3 - _ZN3Dtk4Core13DFileServices5trashE4QUrl@Base 5.0.3 - _ZN3Dtk4Core13DFileServices5trashE5QListI4QUrlE@Base 5.0.3 - _ZN3Dtk4Core13DFileServices5trashE5QListI7QStringE@Base 5.0.3 - _ZN3Dtk4Core13DFileServices5trashE7QString@Base 5.0.3 - _ZN3Dtk4Core13DSecureStringC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DSecureStringC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core13DSecureStringD1Ev@Base 5.0.3 - _ZN3Dtk4Core13DSecureStringD2Ev@Base 5.0.3 - _ZN3Dtk4Core13DTrashManager10cleanTrashEv@Base 5.0.3 - _ZN3Dtk4Core13DTrashManager11moveToTrashERK7QStringb@Base 5.0.3 - _ZN3Dtk4Core13DTrashManager8instanceEv@Base 5.0.3 - _ZN3Dtk4Core13DTrashManagerC1Ev@Base 5.0.3 - _ZN3Dtk4Core13DTrashManagerC2Ev@Base 5.0.3 - _ZN3Dtk4Core13DTrashManagerD0Ev@Base 5.0.3 - _ZN3Dtk4Core13DTrashManagerD1Ev@Base 5.0.3 - _ZN3Dtk4Core13DTrashManagerD2Ev@Base 5.0.3 - _ZN3Dtk4Core13LoggerPrivate14globalInstanceE@Base 5.0.3 - _ZN3Dtk4Core13LoggerPrivate18globalInstanceLockE@Base 5.0.3 - _ZN3Dtk4Core14Chinese2PinyinERK7QString@Base 5.0.3 - _ZN3Dtk4Core14DObjectPrivateC1EPNS0_7DObjectE@Base 5.0.3 - _ZN3Dtk4Core14DObjectPrivateC2EPNS0_7DObjectE@Base 5.0.3 - _ZN3Dtk4Core14DObjectPrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core14DObjectPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core14DObjectPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core14DRecentManager10removeItemERK7QString@Base 5.0.3 - _ZN3Dtk4Core14DRecentManager11removeItemsERK11QStringList@Base 5.0.3 - _ZN3Dtk4Core14DRecentManager7addItemERK7QStringRNS0_11DRecentDataE@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup14setParentGroupE8QPointerIS1_E@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup8fromJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroup9parseJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroupC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroupC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroupD0Ev@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroupD1Ev@Base 5.0.3 - _ZN3Dtk4Core14DSettingsGroupD2Ev@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths14findExecutableERK7QStringRK11QStringList@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths16writableLocationEN14QStandardPaths16StandardLocationE@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths17standardLocationsEN14QStandardPaths16StandardLocationE@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths6locateEN14QStandardPaths16StandardLocationERK7QString6QFlagsINS2_12LocateOptionEE@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths7setModeENS1_4ModeE@Base 5.0.3 - _ZN3Dtk4Core14DStandardPaths9locateAllEN14QStandardPaths16StandardLocationERK7QString6QFlagsINS2_12LocateOptionEE@Base 5.0.3 - _ZN3Dtk4Core14DTrashManager_D0Ev@Base 5.0.3 - _ZN3Dtk4Core14DTrashManager_D1Ev@Base 5.0.3 - _ZN3Dtk4Core14DTrashManager_D2Ev@Base 5.0.3 - _ZN3Dtk4Core14loggerInstanceEv@Base 5.0.3 - _ZN3Dtk4Core14parentPathListERK7QString@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppender24ignoreEnvironmentPatternEb@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppender6appendERK9QDateTimeNS0_6Logger8LogLevelEPKciS8_RK7QStringSB_@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppenderC1Ev@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppenderC2Ev@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppenderD0Ev@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppenderD1Ev@Base 5.0.3 - _ZN3Dtk4Core15ConsoleAppenderD2Ev@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption11dataChangedERK7QString8QVariant@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption12valueChangedE8QVariant@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption14setParentGroupE8QPointerINS0_14DSettingsGroupEE@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption7setDataERK7QString8QVariant@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption8fromJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption8setValueE8QVariant@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOption9parseJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOptionC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOptionC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOptionD0Ev@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOptionD1Ev@Base 5.0.3 - _ZN3Dtk4Core15DSettingsOptionD2Ev@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivate13parseInfoFileER5QFile@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivate16ensureDeepinInfoEv@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivate17ensureReleaseInfoEv@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivate18ensureComputerInfoEv@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivateC1Ev@Base 5.0.3 - _ZN3Dtk4Core15DSysInfoPrivateC2Ev@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackend11doSetOptionERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackend11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackend11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackend16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackend6doSyncEv@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackendC1ERK7QStringP7QObject@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackendC2ERK7QStringP7QObject@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackendD0Ev@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackendD1Ev@Base 5.0.3 - _ZN3Dtk4Core15QSettingBackendD2Ev@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppender15setDetailsLevelENS0_6Logger8LogLevelE@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppender15setDetailsLevelERK7QString@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppender5writeERK9QDateTimeNS0_6Logger8LogLevelEPKciS8_RK7QStringSB_@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppenderC1Ev@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppenderC2Ev@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppenderD0Ev@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppenderD1Ev@Base 5.0.3 - _ZN3Dtk4Core16AbstractAppenderD2Ev@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher10fileClosedERK4QUrl@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11fileDeletedERK4QUrl@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11ghostSignalERK4QUrlMS1_FvS4_ES4_@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11ghostSignalERK4QUrlMS1_FvS4_S4_ES4_S4_@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher11stopWatcherEv@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher12fileModifiedERK4QUrl@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher12startWatcherEv@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher14restartWatcherEv@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher14subfileCreatedERK4QUrl@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher20fileAttributeChangedERK4QUrl@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher24setEnabledSubfileWatcherERK4QUrlb@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcher9fileMovedERK4QUrlS4_@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcherC1ERNS0_23DBaseFileWatcherPrivateERK4QUrlP7QObject@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcherC2ERNS0_23DBaseFileWatcherPrivateERK4QUrlP7QObject@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcherD0Ev@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcherD1Ev@Base 5.0.3 - _ZN3Dtk4Core16DBaseFileWatcherD2Ev@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend13optionChangedERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend4syncEv@Base 5.0.3 - _ZN3Dtk4Core16DSettingsBackend9setOptionERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackend11doSetOptionERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackend11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackend11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackend16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackend6doSyncEv@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackendC1EPNS0_9DSettingsEP7QObject@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackendC2EPNS0_9DSettingsEP7QObject@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackendD0Ev@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackendD1Ev@Base 5.0.3 - _ZN3Dtk4Core16GSettingsBackendD2Ev@Base 5.0.3 - _ZN3Dtk4Core16readLineFromDataERK10QByteArrayRiS4_S4_S4_@Base 5.0.3 - _ZN3Dtk4Core18DDiskSizeFormatter4rateEi@Base 5.0.3 - _ZN3Dtk4Core18DDiskSizeFormatterC1Ev@Base 5.0.3 - _ZN3Dtk4Core18DDiskSizeFormatterC2Ev@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher10fileClosedERK7QStringS4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher10removePathERK7QString@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher11fileCreatedERK7QStringS4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher11fileDeletedERK7QStringS4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher11removePathsERK11QStringList@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher12fileModifiedERK7QStringS4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher20fileAttributeChangedERK7QStringS4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher7addPathERK7QString@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher8addPathsERK11QStringList@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcher9fileMovedERK7QStringS4_S4_S4_NS1_14QPrivateSignalE@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherC1ERK11QStringListP7QObject@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherC2ERK11QStringListP7QObject@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherD0Ev@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherD1Ev@Base 5.0.3 - _ZN3Dtk4Core18DFileSystemWatcherD2Ev@Base 5.0.3 - _ZN3Dtk4Core18DTimeUnitFormatterC1Ev@Base 5.0.3 - _ZN3Dtk4Core18DTimeUnitFormatterC2Ev@Base 5.0.3 - _ZN3Dtk4Core18LoggerTimingHelper5startEPKcz@Base 5.0.3 - _ZN3Dtk4Core18LoggerTimingHelper5startERK7QString@Base 5.0.3 - _ZN3Dtk4Core18LoggerTimingHelperD1Ev@Base 5.0.3 - _ZN3Dtk4Core18LoggerTimingHelperD2Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager10fileClosedERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager11fileDeletedERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager12fileModifiedERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager14subfileCreatedERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager20fileAttributeChangedERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager3addERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager6removeERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManager9fileMovedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManagerC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManagerC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManagerD0Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManagerD1Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherManagerD2Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate10formatPathERK7QString@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate18_q_handleFileCloseERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate18_q_handleFileMovedERK7QStringS4_S4_S4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate20_q_handleFileCreatedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate20_q_handleFileDeletedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate21_q_handleFileModifiedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate22filePathToWatcherCountE@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate29_q_handleFileAttributeChangedERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate4stopEv@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivate5startEv@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core19DFileWatcherPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender14removeOldFilesEv@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender14setDatePatternENS1_11DatePatternE@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender14setDatePatternERK7QString@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender16computeFrequencyEv@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender16setLogFilesLimitEi@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender19computeRollOverTimeEv@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender20setDatePatternStringERK7QString@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender6appendERK9QDateTimeNS0_6Logger8LogLevelEPKciS8_RK7QStringSB_@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppender8rollOverEv@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppenderC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppenderC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppenderD0Ev@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppenderD1Ev@Base 5.0.3 - _ZN3Dtk4Core19RollingFileAppenderD2Ev@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivate20initSectionsFromDataERK10QByteArray@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivate3getERK7QStringS4_PS2_@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivate3setERK7QStringS4_S4_@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivate6removeERK7QStringS4_@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivate9fuzzyLoadEv@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivateC1ERK7QStringPNS0_13DDesktopEntryE@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivateC2ERK7QStringPNS0_13DDesktopEntryE@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntryPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntrySection23ensureSectionDataParsedEv@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntrySectionD1Ev@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntrySectionD2Ev@Base 5.0.3 - _ZN3Dtk4Core20DDesktopEntrySectionaSERKS1_@Base 5.0.3 - _ZN3Dtk4Core20DTrashManagerPrivate15removeFileOrDirERK7QString@Base 5.0.3 - _ZN3Dtk4Core20DTrashManagerPrivate18removeFromIteratorER12QDirIterator@Base 5.0.3 - _ZN3Dtk4Core20DTrashManagerPrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core20DTrashManagerPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core20DTrashManagerPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core21DSettingsGroupPrivate9parseJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppender16qCleanupFuncinfoEPKc@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppender17stripFunctionNameEPKc@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppender9setFormatERK7QString@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppenderC1Ev@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppenderC2Ev@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppenderD0Ev@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppenderD1Ev@Base 5.0.3 - _ZN3Dtk4Core22AbstractStringAppenderD2Ev@Base 5.0.3 - _ZN3Dtk4Core22DAbstractUnitFormatterC1Ev@Base 5.0.3 - _ZN3Dtk4Core22DAbstractUnitFormatterC2Ev@Base 5.0.3 - _ZN3Dtk4Core22DAbstractUnitFormatterD1Ev@Base 5.0.3 - _ZN3Dtk4Core22DAbstractUnitFormatterD2Ev@Base 5.0.3 - _ZN3Dtk4Core22DSettingsOptionPrivate9parseJsonERK7QStringRK11QJsonObject@Base 5.0.3 - _ZN3Dtk4Core23DBaseFileWatcherPrivate11watcherListE@Base 5.0.3 - _ZN3Dtk4Core23DBaseFileWatcherPrivateC1EPNS0_16DBaseFileWatcherE@Base 5.0.3 - _ZN3Dtk4Core23DBaseFileWatcherPrivateC2EPNS0_16DBaseFileWatcherE@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivate11removePathsERK11QStringListPS2_S5_@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivate13onFileChangedERK7QStringb@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivate18_q_readFromInotifyEv@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivate18onDirectoryChangedERK7QStringb@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivate8addPathsERK11QStringListPS2_S5_@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivateC1EiPNS0_18DFileSystemWatcherE@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivateC2EiPNS0_18DFileSystemWatcherE@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core25DFileSystemWatcherPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core26DFileWatcherManagerPrivateC1EPNS0_19DFileWatcherManagerE@Base 5.0.3 - _ZN3Dtk4Core26DFileWatcherManagerPrivateC2EPNS0_19DFileWatcherManagerE@Base 5.0.3 - _ZN3Dtk4Core26DFileWatcherManagerPrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core26DFileWatcherManagerPrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core26DFileWatcherManagerPrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender4callEv@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender5hintsERK4QMapI7QString8QVariantE@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender7actionsERK11QStringList@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender7appBodyERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender7appIconERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender7appNameERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender7timeOutEi@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySender9replaceIdEj@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySenderC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil13DNotifySenderC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterface11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterface11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterface14registerActionERK7QStringS5_St8functionIF8QVariantS3_EE@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterface16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterfaceC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterfaceC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterfaceD0Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterfaceD1Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil18DExportedInterfaceD2Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivate10actionHelpE7QStringi@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivateC1EPNS1_18DExportedInterfaceE@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivateC2EPNS1_18DExportedInterfaceE@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivateD0Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivateD1Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil25DExportedInterfacePrivateD2Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface4helpERK7QString@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface4listEv@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterface6invokeE7QStringS3_@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceC1EPNS1_25DExportedInterfacePrivateE@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceC2EPNS1_25DExportedInterfacePrivateE@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceD0Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceD1Ev@Base 5.0.3 - _ZN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceD2Ev@Base 5.0.3 - _ZN3Dtk4Core6Logger11writeAssertEPKciS3_S3_@Base 5.0.3 - _ZN3Dtk4Core6Logger13levelToStringENS1_8LogLevelE@Base 5.0.3 - _ZN3Dtk4Core6Logger14globalInstanceEv@Base 5.0.3 - _ZN3Dtk4Core6Logger15levelFromStringERK7QString@Base 5.0.3 - _ZN3Dtk4Core6Logger16registerAppenderEPNS0_16AbstractAppenderE@Base 5.0.3 - _ZN3Dtk4Core6Logger18setDefaultCategoryERK7QString@Base 5.0.3 - _ZN3Dtk4Core6Logger19logToGlobalInstanceERK7QStringb@Base 5.0.3 - _ZN3Dtk4Core6Logger24registerCategoryAppenderERK7QStringPNS0_16AbstractAppenderE@Base 5.0.3 - _ZN3Dtk4Core6Logger5writeENS1_8LogLevelEPKciS4_S4_@Base 5.0.3 - _ZN3Dtk4Core6Logger5writeENS1_8LogLevelEPKciS4_S4_RK7QString@Base 5.0.3 - _ZN3Dtk4Core6Logger5writeERK9QDateTimeNS1_8LogLevelEPKciS7_S7_RK7QString@Base 5.0.3 - _ZN3Dtk4Core6Logger5writeERK9QDateTimeNS1_8LogLevelEPKciS7_S7_RK7QStringb@Base 5.0.3 - _ZN3Dtk4Core6LoggerC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core6LoggerC1Ev@Base 5.0.3 - _ZN3Dtk4Core6LoggerC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core6LoggerC2Ev@Base 5.0.3 - _ZN3Dtk4Core6LoggerD1Ev@Base 5.0.3 - _ZN3Dtk4Core6LoggerD2Ev@Base 5.0.3 - _ZN3Dtk4Core7DObjectC1EPS1_@Base 5.0.3 - _ZN3Dtk4Core7DObjectC1ERNS0_14DObjectPrivateEPS1_@Base 5.0.3 - _ZN3Dtk4Core7DObjectC2EPS1_@Base 5.0.3 - _ZN3Dtk4Core7DObjectC2ERNS0_14DObjectPrivateEPS1_@Base 5.0.3 - _ZN3Dtk4Core7DObjectD0Ev@Base 5.0.3 - _ZN3Dtk4Core7DObjectD1Ev@Base 5.0.3 - _ZN3Dtk4Core7DObjectD2Ev@Base 5.0.3 - _ZN3Dtk4Core8DPathBufC1ERK7QString@Base 5.0.3 - _ZN3Dtk4Core8DPathBufC1Ev@Base 5.0.3 - _ZN3Dtk4Core8DPathBufC2ERK7QString@Base 5.0.3 - _ZN3Dtk4Core8DPathBufC2Ev@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo10deepinTypeEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo11productTypeEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo12computerNameEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo12cpuModelNameEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo13deepinEditionEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo13deepinVersionEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo14productVersionEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo14systemDiskSizeEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo15deepinCopyrightEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo15memoryTotalSizeEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo17productTypeStringEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo18isCommunityEditionEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo19distributionOrgLogoENS1_7OrgTypeENS1_8LogoTypeERK7QString@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo19distributionOrgNameENS1_7OrgTypeERK7QLocale@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo19memoryInstalledSizeEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo19operatingSystemNameEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo20distributionInfoPathEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo21deepinDistributorLogoENS1_8LogoTypeERK7QString@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo21deepinDistributorNameEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo21deepinTypeDisplayNameERK7QLocale@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo22distributionOrgWebsiteENS1_7OrgTypeE@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo24deepinDistributorWebsiteEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo26deepinDistributionInfoPathEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo27distributionInfoSectionNameENS1_7OrgTypeE@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo5isDDEEv@Base 5.0.3 - _ZN3Dtk4Core8DSysInfo8isDeepinEv@Base 5.0.3 - _ZN3Dtk4Core8doEscapeER7QStringRK5QHashI5QCharS4_E@Base 5.0.3 - _ZN3Dtk4Core9DSettings10setBackendEPNS0_16DSettingsBackendE@Base 5.0.3 - _ZN3Dtk4Core9DSettings11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.0.3 - _ZN3Dtk4Core9DSettings11qt_metacastEPKc@Base 5.0.3 - _ZN3Dtk4Core9DSettings12fromJsonFileERK7QString@Base 5.0.3 - _ZN3Dtk4Core9DSettings12valueChangedERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core9DSettings16staticMetaObjectE@Base 5.0.3 - _ZN3Dtk4Core9DSettings4syncEv@Base 5.0.3 - _ZN3Dtk4Core9DSettings5resetEv@Base 5.0.3 - _ZN3Dtk4Core9DSettings8fromJsonERK10QByteArray@Base 5.0.3 - _ZN3Dtk4Core9DSettings9loadValueEv@Base 5.0.3 - _ZN3Dtk4Core9DSettings9parseJsonERK10QByteArray@Base 5.0.3 - _ZN3Dtk4Core9DSettings9setOptionERK7QStringRK8QVariant@Base 5.0.3 - _ZN3Dtk4Core9DSettingsC1EP7QObject@Base 5.0.3 - _ZN3Dtk4Core9DSettingsC2EP7QObject@Base 5.0.3 - _ZN3Dtk4Core9DSettingsD0Ev@Base 5.0.3 - _ZN3Dtk4Core9DSettingsD1Ev@Base 5.0.3 - _ZN3Dtk4Core9DSettingsD2Ev@Base 5.0.3 - _ZN3Dtk4Core9LogDevice8readDataEPcx@Base 5.0.3 - _ZN3Dtk4Core9LogDevice9writeDataEPKcx@Base 5.0.3 - _ZN3Dtk4Core9LogDeviceD0Ev@Base 5.0.3 - _ZN3Dtk4Core9LogDeviceD1Ev@Base 5.0.3 - _ZN3Dtk4Core9LogDeviceD2Ev@Base 5.0.3 - _ZN3Dtk4Core9qtifyNameERK7QString@Base 5.0.3 - _ZN4QMapI7QString5QPairIS0_yEE13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QString5QPairIS0_yEED1Ev@Base 5.0.3 - _ZN4QMapI7QString5QPairIS0_yEED2Ev@Base 5.0.3 - _ZN4QMapI7QString5QPairIS0_yEEixERKS0_@Base 5.0.3 - _ZN4QMapI7QString8QPointerIN3Dtk4Core15DSettingsOptionEEE13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QString8QVariantE6insertERKS0_RKS1_@Base 5.0.3 - _ZN4QMapI7QString8QVariantEC1ERKS2_@Base 5.0.3 - _ZN4QMapI7QString8QVariantEC2ERKS2_@Base 5.0.3 - _ZN4QMapI7QStringN3Dtk4Core20DDesktopEntrySectionEE13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QStringN3Dtk4Core20DDesktopEntrySectionEED1Ev@Base 5.0.3 - _ZN4QMapI7QStringN3Dtk4Core20DDesktopEntrySectionEED2Ev@Base 5.0.3 - _ZN4QMapI7QStringN3Dtk4Core20DDesktopEntrySectionEEixERKS0_@Base 5.0.3 - _ZN4QMapI7QStringPN3Dtk4Core12DFileWatcherEE13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QStringS0_E13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QStringS0_E6removeERKS0_@Base 5.0.3 - _ZN4QMapI7QStringS0_EC1ERKS1_@Base 5.0.3 - _ZN4QMapI7QStringS0_EC2ERKS1_@Base 5.0.3 - _ZN4QMapI7QStringS0_ED1Ev@Base 5.0.3 - _ZN4QMapI7QStringS0_ED2Ev@Base 5.0.3 - _ZN4QMapI7QStringS0_EixERKS0_@Base 5.0.3 - _ZN4QMapI7QStringiE13detach_helperEv@Base 5.0.3 - _ZN4QMapI7QStringiED1Ev@Base 5.0.3 - _ZN4QMapI7QStringiED2Ev@Base 5.0.3 - _ZN4QMapI9QDateTime7QStringED1Ev@Base 5.0.3 - _ZN4QMapI9QDateTime7QStringED2Ev@Base 5.0.3 - _ZN4QMapIPKvPyE13detach_helperEv@Base 5.0.3 - _ZN4QMapIPKvPyED1Ev@Base 5.0.3 - _ZN4QMapIPKvPyED2Ev@Base 5.0.3 - _ZN4QMapIPKvyE13detach_helperEv@Base 5.0.3 - _ZN4QMapIPKvyED1Ev@Base 5.0.3 - _ZN4QMapIPKvyED2Ev@Base 5.0.3 - _ZN4QMapIPPyS0_E13detach_helperEv@Base 5.0.3 - _ZN4QMapIPPyS0_ED1Ev@Base 5.0.3 - _ZN4QMapIPPyS0_ED2Ev@Base 5.0.3 - _ZN4QMapIi7QStringED1Ev@Base 5.0.3 - _ZN4QMapIi7QStringED2Ev@Base 5.0.3 - _ZN5QHashI5QCharS0_E11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashI5QCharS0_E13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashI5QCharS0_E6insertERKS0_S3_@Base 5.0.3 - _ZN5QHashI5QCharS0_ED1Ev@Base 5.0.3 - _ZN5QHashI5QCharS0_ED2Ev@Base 5.0.3 - _ZN5QHashI7QString5QPairISt8functionIF8QVariantS0_EES0_EE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashI7QString5QPairISt8functionIF8QVariantS0_EES0_EE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashI7QStringiE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashI7QStringiE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashIPN3Dtk4Core16AbstractAppenderE15QHashDummyValueE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashIPN3Dtk4Core16AbstractAppenderE15QHashDummyValueE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashIPN3Dtk4Core16AbstractAppenderE15QHashDummyValueED1Ev@Base 5.0.3 - _ZN5QHashIPN3Dtk4Core16AbstractAppenderE15QHashDummyValueED2Ev@Base 5.0.3 - _ZN5QHashIi15QHashDummyValueE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashIi15QHashDummyValueE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashIi7QStringE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashIi7QStringE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashIi7QStringE5eraseENS1_14const_iteratorE@Base 5.0.3 - _ZN5QHashIi7QStringED1Ev@Base 5.0.3 - _ZN5QHashIi7QStringED2Ev@Base 5.0.3 - _ZN5QHashIj7QStringE11deleteNode2EPN9QHashData4NodeE@Base 5.0.3 - _ZN5QHashIj7QStringE13duplicateNodeEPN9QHashData4NodeEPv@Base 5.0.3 - _ZN5QHashIj7QStringED1Ev@Base 5.0.3 - _ZN5QHashIj7QStringED2Ev@Base 5.0.3 - _ZN5QListI10QByteArrayED1Ev@Base 5.0.3 - _ZN5QListI10QByteArrayED2Ev@Base 5.0.3 - _ZN5QListI4QUrlE13detach_helperEi@Base 5.0.3 - _ZN5QListI4QUrlE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI4QUrlE6appendERKS0_@Base 5.0.3 - _ZN5QListI4QUrlEC1ERKS1_@Base 5.0.3 - _ZN5QListI4QUrlEC2ERKS1_@Base 5.0.3 - _ZN5QListI4QUrlED1Ev@Base 5.0.3 - _ZN5QListI4QUrlED2Ev@Base 5.0.3 - _ZN5QListI5QPairI7QStringiEE13detach_helperEi@Base 5.0.3 - _ZN5QListI5QPairI7QStringiEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI5QPairI7QStringiEE6appendERKS2_@Base 5.0.3 - _ZN5QListI5QPairI7QStringiEED1Ev@Base 5.0.3 - _ZN5QListI5QPairI7QStringiEED2Ev@Base 5.0.3 - _ZN5QListI5QPairIdiEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI5QPairIdiEE6appendERKS1_@Base 5.0.3 - _ZN5QListI5QPairIdiEED1Ev@Base 5.0.3 - _ZN5QListI5QPairIdiEED2Ev@Base 5.0.3 - _ZN5QListI7QStringE13detach_helperEi@Base 5.0.3 - _ZN5QListI7QStringE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI7QStringE6appendERKS0_@Base 5.0.3 - _ZN5QListI7QStringE7reserveEi@Base 5.0.3 - _ZN5QListI7QStringE9removeAllERKS0_@Base 5.0.3 - _ZN5QListI7QStringEC1ERKS1_@Base 5.0.3 - _ZN5QListI7QStringEC2ERKS1_@Base 5.0.3 - _ZN5QListI7QStringED1Ev@Base 5.0.3 - _ZN5QListI7QStringED2Ev@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core14DSettingsGroupEEE13detach_helperEi@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core14DSettingsGroupEEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core14DSettingsGroupEEE6appendERKS4_@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core15DSettingsOptionEEE13detach_helperEi@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core15DSettingsOptionEEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core15DSettingsOptionEEE6appendERKS4_@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core15DSettingsOptionEEED1Ev@Base 5.0.3 - _ZN5QListI8QPointerIN3Dtk4Core15DSettingsOptionEEED2Ev@Base 5.0.3 - _ZN5QListI8QVariantE13detach_helperEi@Base 5.0.3 - _ZN5QListI8QVariantE18detach_helper_growEii@Base 5.0.3 - _ZN5QListI8QVariantE6appendERKS0_@Base 5.0.3 - _ZN5QListI8QVariantEC1ERKS1_@Base 5.0.3 - _ZN5QListI8QVariantEC2ERKS1_@Base 5.0.3 - _ZN5QListI8QVariantED1Ev@Base 5.0.3 - _ZN5QListI8QVariantED2Ev@Base 5.0.3 - _ZN5QListI9QFileInfoE13detach_helperEi@Base 5.0.3 - _ZN5QListI9QFileInfoED1Ev@Base 5.0.3 - _ZN5QListI9QFileInfoED2Ev@Base 5.0.3 - _ZN5QListIN3Dtk4Core8DSysInfo10DeepinTypeEE13detach_helperEi@Base 5.0.3 - _ZN5QListIN3Dtk4Core8DSysInfo10DeepinTypeEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListIN3Dtk4Core8DSysInfo10DeepinTypeEE6appendERKS3_@Base 5.0.3 - _ZN5QListIN3Dtk4Core8DSysInfo10DeepinTypeEED1Ev@Base 5.0.3 - _ZN5QListIN3Dtk4Core8DSysInfo10DeepinTypeEED2Ev@Base 5.0.3 - _ZN5QListIP13inotify_eventE13detach_helperEi@Base 5.0.3 - _ZN5QListIP13inotify_eventE18detach_helper_growEii@Base 5.0.3 - _ZN5QListIP13inotify_eventE6appendERKS1_@Base 5.0.3 - _ZN5QListIP13inotify_eventED1Ev@Base 5.0.3 - _ZN5QListIP13inotify_eventED2Ev@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEE6appendERKS3_@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEEC1ERKS4_@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEEC2ERKS4_@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEED1Ev@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16AbstractAppenderEED2Ev@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEE13detach_helperEi@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEE18detach_helper_growEii@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEE6appendERKS3_@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEE9removeOneERKS3_@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEED1Ev@Base 5.0.3 - _ZN5QListIPN3Dtk4Core16DBaseFileWatcherEED2Ev@Base 5.0.3 - _ZN5QPairISt8functionIF8QVariant7QStringEES2_ED1Ev@Base 5.0.3 - _ZN5QPairISt8functionIF8QVariant7QStringEES2_ED2Ev@Base 5.0.3 - _ZN7QStringC1EPKc@Base 5.0.3 - _ZN7QStringC2EPKc@Base 5.0.3 - _ZN7QStringD1Ev@Base 5.0.3 - _ZN7QStringD2Ev@Base 5.0.3 - _ZN8QMapDataI7QStringN3Dtk4Core20DDesktopEntrySectionEE10createNodeERKS0_RKS3_P8QMapNodeIS0_S3_Eb@Base 5.0.3 - _ZN8QMapDataI7QStringPN3Dtk4Core12DFileWatcherEE7destroyEv@Base 5.0.3 - _ZN8QMapDataI7QStringPN3Dtk4Core16AbstractAppenderEE7destroyEv@Base 5.0.3 - _ZN8QMapDataI7QStringbE7destroyEv@Base 5.0.3 - _ZN8QMapDataI7QStringiE7destroyEv@Base 5.0.3 - _ZN8QMapDataI9QDateTime7QStringE7destroyEv@Base 5.0.3 - _ZN8QMapDataIi7QStringE7destroyEv@Base 5.0.3 - _ZN8QMapNodeI7QString5QPairIS0_yEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QString8QPointerIN3Dtk4Core14DSettingsGroupEEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QString8QPointerIN3Dtk4Core15DSettingsOptionEEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QString8QVariantE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringN3Dtk4Core20DDesktopEntrySectionEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringPN3Dtk4Core12DFileWatcherEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringPN3Dtk4Core16AbstractAppenderEE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringS0_E14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringbE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI7QStringiE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeI9QDateTime7QStringE14destroySubTreeEv@Base 5.0.3 - _ZN8QMapNodeIi7QStringE14destroySubTreeEv@Base 5.0.3 - _ZN9DDBusDataC1Ev@Base 5.0.3 - _ZN9DDBusDataC2Ev@Base 5.0.3 - _ZN9QtPrivate11QSlotObjectIMN3Dtk4Core12DFileWatcherEFvRK7QStringS6_ENS_4ListIJS6_S6_EEEvE4implEiPNS_15QSlotObjectBaseEP7QObjectPPvPb@Base 5.0.3 - _ZN9QtPrivate11QSlotObjectIMN3Dtk4Core12DFileWatcherEFvRK7QStringS6_S6_S6_ENS_4ListIJS6_S6_S6_S6_EEEvE4implEiPNS_15QSlotObjectBaseEP7QObjectPPvPb@Base 5.0.3 - _ZN9QtPrivate11QSlotObjectIMN3Dtk4Core16DSettingsBackendEFvRK7QStringRK8QVariantENS_4ListIJS6_S9_EEEvE4implEiPNS_15QSlotObjectBaseEP7QObjectPPvPb@Base 5.0.3 - _ZN9QtPrivate11QSlotObjectIMN3Dtk4Core16DSettingsBackendEFvvENS_4ListIJEEEvE4implEiPNS_15QSlotObjectBaseEP7QObjectPPvPb@Base 5.0.3 - _ZN9QtPrivate8RefCount3refEv@Base 5.0.3 - _ZNK3Dtk4Core12DFileWatcher10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core12FileAppender4sizeEv@Base 5.0.3 - _ZNK3Dtk4Core12FileAppender8fileNameEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry11genericNameEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry11stringValueERK7QStringS4_S4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry14ddeDisplayNameEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry14localizedValueERK7QStringRK7QLocaleS4_S4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry14localizedValueERK7QStringS4_S4_S4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry15stringListValueERK7QStringS4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry4keysERK7QString@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry4nameEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry4saveEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry6statusEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry7commentEv@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry8containsERK7QStringS4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry8rawValueERK7QStringS4_S4_@Base 5.0.3 - _ZNK3Dtk4Core13DDesktopEntry9allGroupsEb@Base 5.0.3 - _ZNK3Dtk4Core13DTrashManager12trashIsEmptyEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup10childGroupERK7QString@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup11childGroupsEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup11parentGroupEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup12childOptionsEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup3keyEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup4nameEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup6optionERK7QString@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup7optionsEv@Base 5.0.3 - _ZNK3Dtk4Core14DSettingsGroup8isHiddenEv@Base 5.0.3 - _ZNK3Dtk4Core15ConsoleAppender6formatEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption11parentGroupEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption12defaultValueEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption3keyEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption4dataERK7QString@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption4nameEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption5valueEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption8canResetEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption8isHiddenEv@Base 5.0.3 - _ZNK3Dtk4Core15DSettingsOption8viewTypeEv@Base 5.0.3 - _ZNK3Dtk4Core15QSettingBackend10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core15QSettingBackend4keysEv@Base 5.0.3 - _ZNK3Dtk4Core15QSettingBackend9getOptionERK7QString@Base 5.0.3 - _ZNK3Dtk4Core16AbstractAppender12detailsLevelEv@Base 5.0.3 - _ZNK3Dtk4Core16DBaseFileWatcher10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core16DBaseFileWatcher7fileUrlEv@Base 5.0.3 - _ZNK3Dtk4Core16DSettingsBackend10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core16GSettingsBackend10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core16GSettingsBackend4keysEv@Base 5.0.3 - _ZNK3Dtk4Core16GSettingsBackend9getOptionERK7QString@Base 5.0.3 - _ZNK3Dtk4Core17CuteMessageLogger5writeEPKcz@Base 5.0.3 - _ZNK3Dtk4Core17CuteMessageLogger5writeERK7QString@Base 5.0.3 - _ZNK3Dtk4Core17CuteMessageLogger5writeEv@Base 5.0.3 - _ZNK3Dtk4Core18DDiskSizeFormatter15unitConvertRateEi@Base 5.0.3 - _ZNK3Dtk4Core18DDiskSizeFormatter7unitMaxEv@Base 5.0.3 - _ZNK3Dtk4Core18DDiskSizeFormatter7unitMinEv@Base 5.0.3 - _ZNK3Dtk4Core18DDiskSizeFormatter7unitStrEi@Base 5.0.3 - _ZNK3Dtk4Core18DFileSystemWatcher10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core18DFileSystemWatcher11directoriesEv@Base 5.0.3 - _ZNK3Dtk4Core18DFileSystemWatcher5filesEv@Base 5.0.3 - _ZNK3Dtk4Core18DTimeUnitFormatter15unitConvertRateEi@Base 5.0.3 - _ZNK3Dtk4Core18DTimeUnitFormatter7unitMaxEv@Base 5.0.3 - _ZNK3Dtk4Core18DTimeUnitFormatter7unitMinEv@Base 5.0.3 - _ZNK3Dtk4Core18DTimeUnitFormatter7unitStrEi@Base 5.0.3 - _ZNK3Dtk4Core19DFileWatcherManager10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core19RollingFileAppender11datePatternEv@Base 5.0.3 - _ZNK3Dtk4Core19RollingFileAppender13logFilesLimitEv@Base 5.0.3 - _ZNK3Dtk4Core19RollingFileAppender17datePatternStringEv@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate10isWritableEv@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate10sectionPosERK7QString@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate4keysERK7QString@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate5writeER9QIODevice@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate8containsERK7QStringS4_@Base 5.0.3 - _ZNK3Dtk4Core20DDesktopEntryPrivate9setStatusERKNS0_13DDesktopEntry6StatusE@Base 5.0.3 - _ZNK3Dtk4Core22AbstractStringAppender15formattedStringERK9QDateTimeNS0_6Logger8LogLevelEPKciS8_RK7QStringSB_@Base 5.0.3 - _ZNK3Dtk4Core22AbstractStringAppender6formatEv@Base 5.0.3 - _ZNK3Dtk4Core22DAbstractUnitFormatter12unitValueMaxEi@Base 5.0.3 - _ZNK3Dtk4Core22DAbstractUnitFormatter12unitValueMinEi@Base 5.0.3 - _ZNK3Dtk4Core22DAbstractUnitFormatter16formatAsUnitListEdi@Base 5.0.3 - _ZNK3Dtk4Core22DAbstractUnitFormatter6formatEdi@Base 5.0.3 - _ZNK3Dtk4Core22DAbstractUnitFormatter8formatAsEdii@Base 5.0.3 - _ZNK3Dtk4Core5DUtil18DExportedInterface10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core5DUtil18DExportedInterface6invokeERK7QStringS5_@Base 5.0.3 - _ZNK3Dtk4Core5DUtil31DExportedInterfaceDBusInterface10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core6Logger15defaultCategoryEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings10metaObjectEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings4keysEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings4metaEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings5groupERK7QString@Base 5.0.3 - _ZNK3Dtk4Core9DSettings5valueERK7QString@Base 5.0.3 - _ZNK3Dtk4Core9DSettings6groupsEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings6optionERK7QString@Base 5.0.3 - _ZNK3Dtk4Core9DSettings7optionsEv@Base 5.0.3 - _ZNK3Dtk4Core9DSettings9getOptionERK7QString@Base 5.0.3 - _ZNK3Dtk4Core9DSettings9groupKeysEv@Base 5.0.3 - _ZNK4QMapI7QString8QPointerIN3Dtk4Core15DSettingsOptionEEE6valuesEv@Base 5.0.3 - _ZNK4QMapI7QStringN3Dtk4Core20DDesktopEntrySectionEE4keysEv@Base 5.0.3 - _ZNK4QMapIi7QStringE6valuesERKi@Base 5.0.3 - _ZNK5QHashI5QCharS0_E8findNodeERKS0_Pj@Base 5.0.3 - _ZNK5QHashI7QString5QPairISt8functionIF8QVariantS0_EES0_EE4keysEv@Base 5.0.3 - _ZNK5QHashI7QString5QPairISt8functionIF8QVariantS0_EES0_EE8findNodeERKS0_Pj@Base 5.0.3 - _ZNK5QHashI7QString5QPairISt8functionIF8QVariantS0_EES0_EE8findNodeERKS0_j@Base 5.0.3 - _ZNK5QHashI7QStringiE8findNodeERKS0_Pj@Base 5.0.3 - _ZNK5QHashI7QStringiE8findNodeERKS0_j@Base 5.0.3 - _ZNK5QHashIPN3Dtk4Core16AbstractAppenderE15QHashDummyValueE8findNodeERKS3_Pj@Base 5.0.3 - _ZNK5QHashIi15QHashDummyValueE8findNodeERKiPj@Base 5.0.3 - _ZNK5QHashIi7QStringE6valuesERKi@Base 5.0.3 - _ZNK5QHashIi7QStringE8findNodeERKiPj@Base 5.0.3 - _ZNK5QHashIj7QStringE8findNodeERKjPj@Base 5.0.3 - _ZNK5QListIPN3Dtk4Core16AbstractAppenderEE5toSetEv@Base 5.0.3 - _ZNK8QMapDataI7QString8QPointerIN3Dtk4Core14DSettingsGroupEEE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QString8QPointerIN3Dtk4Core15DSettingsOptionEEE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QString8QVariantE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QStringN3Dtk4Core20DDesktopEntrySectionEE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QStringPN3Dtk4Core12DFileWatcherEE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QStringPN3Dtk4Core16AbstractAppenderEE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QStringS0_E8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataI7QStringiE8findNodeERKS0_@Base 5.0.3 - _ZNK8QMapDataIPKvPyE8findNodeERKS1_@Base 5.0.3 - _ZNK8QMapDataIPKvyE8findNodeERKS1_@Base 5.0.3 - _ZNK8QMapNodeI7QString5QPairIS0_yEE4copyEP8QMapDataIS0_S2_E@Base 5.0.3 - _ZNK8QMapNodeI7QString8QPointerIN3Dtk4Core14DSettingsGroupEEE4copyEP8QMapDataIS0_S5_E@Base 5.0.3 - _ZNK8QMapNodeI7QString8QPointerIN3Dtk4Core15DSettingsOptionEEE4copyEP8QMapDataIS0_S5_E@Base 5.0.3 - _ZNK8QMapNodeI7QString8QVariantE4copyEP8QMapDataIS0_S1_E@Base 5.0.3 - _ZNK8QMapNodeI7QStringN3Dtk4Core20DDesktopEntrySectionEE4copyEP8QMapDataIS0_S3_E@Base 5.0.3 - _ZNK8QMapNodeI7QStringPN3Dtk4Core12DFileWatcherEE4copyEP8QMapDataIS0_S4_E@Base 5.0.3 - _ZNK8QMapNodeI7QStringPN3Dtk4Core16AbstractAppenderEE4copyEP8QMapDataIS0_S4_E@Base 5.0.3 - _ZNK8QMapNodeI7QStringS0_E4copyEP8QMapDataIS0_S0_E@Base 5.0.3 - _ZNK8QMapNodeI7QStringbE4copyEP8QMapDataIS0_bE@Base 5.0.3 - _ZNK8QMapNodeI7QStringiE4copyEP8QMapDataIS0_iE@Base 5.0.3 - _ZNK8QMapNodeI9QDateTime7QStringE4copyEP8QMapDataIS0_S1_E@Base 5.0.3 - _ZNK8QMapNodeIPKvPyE4copyEP8QMapDataIS1_S2_E@Base 5.0.3 - _ZNK8QMapNodeIPKvyE4copyEP8QMapDataIS1_yE@Base 5.0.3 - _ZNK8QMapNodeIPPyS0_E4copyEP8QMapDataIS1_S0_E@Base 5.0.3 - _ZNK8QMapNodeIi7QStringE4copyEP8QMapDataIiS0_E@Base 5.0.3 - _ZNKSt5ctypeIcE8do_widenEc@Base 5.0.3 - _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_releaseEv@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE10_M_disposeEv@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE14_M_get_deleterERKSt9type_info@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EED0Ev@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EED1Ev@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EED2Ev@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE10_M_disposeEv@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE14_M_get_deleterERKSt9type_info@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EED0Ev@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EED1Ev@Base 5.0.3 - _ZNSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EED2Ev@Base 5.0.3 - _ZNSt8functionIF8QVariant7QStringEEC1ERKS3_@Base 5.0.3 - _ZNSt8functionIF8QVariant7QStringEEC2ERKS3_@Base 5.0.3 - _ZSt9__find_ifIPK7QStringN9__gnu_cxx5__ops16_Iter_equals_valIS1_EEET_S7_S7_T0_St26random_access_iterator_tag@Base 5.0.3 - _ZTI12QDBusContext@Base 5.0.3 - _ZTIN3Dtk4Core12DFileWatcherE@Base 5.0.3 - _ZTIN3Dtk4Core12FileAppenderE@Base 5.0.3 - _ZTIN3Dtk4Core13DTrashManagerE@Base 5.0.3 - _ZTIN3Dtk4Core14DObjectPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core14DSettingsGroupE@Base 5.0.3 - _ZTIN3Dtk4Core14DTrashManager_E@Base 5.0.3 - _ZTIN3Dtk4Core15ConsoleAppenderE@Base 5.0.3 - _ZTIN3Dtk4Core15DSettingsOptionE@Base 5.0.3 - _ZTIN3Dtk4Core15QSettingBackendE@Base 5.0.3 - _ZTIN3Dtk4Core16AbstractAppenderE@Base 5.0.3 - _ZTIN3Dtk4Core16DBaseFileWatcherE@Base 5.0.3 - _ZTIN3Dtk4Core16DSettingsBackendE@Base 5.0.3 - _ZTIN3Dtk4Core16GSettingsBackendE@Base 5.0.3 - _ZTIN3Dtk4Core18DDiskSizeFormatterE@Base 5.0.3 - _ZTIN3Dtk4Core18DFileSystemWatcherE@Base 5.0.3 - _ZTIN3Dtk4Core18DTimeUnitFormatterE@Base 5.0.3 - _ZTIN3Dtk4Core19DFileWatcherManagerE@Base 5.0.3 - _ZTIN3Dtk4Core19DFileWatcherPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core19RollingFileAppenderE@Base 5.0.3 - _ZTIN3Dtk4Core20DTrashManagerPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core22AbstractStringAppenderE@Base 5.0.3 - _ZTIN3Dtk4Core22DAbstractUnitFormatterE@Base 5.0.3 - _ZTIN3Dtk4Core23DBaseFileWatcherPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core25DFileSystemWatcherPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core26DFileWatcherManagerPrivateE@Base 5.0.3 - _ZTIN3Dtk4Core5DUtil18DExportedInterfaceE@Base 5.0.3 - _ZTIN3Dtk4Core5DUtil25DExportedInterfacePrivateE@Base 5.0.3 - _ZTIN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceE@Base 5.0.3 - _ZTIN3Dtk4Core7DObjectE@Base 5.0.3 - _ZTIN3Dtk4Core9DSettingsE@Base 5.0.3 - _ZTIN3Dtk4Core9LogDeviceE@Base 5.0.3 - _ZTISt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTISt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTISt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTISt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTS12QDBusContext@Base 5.0.3 - _ZTSN3Dtk4Core12DFileWatcherE@Base 5.0.3 - _ZTSN3Dtk4Core12FileAppenderE@Base 5.0.3 - _ZTSN3Dtk4Core13DTrashManagerE@Base 5.0.3 - _ZTSN3Dtk4Core14DObjectPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core14DSettingsGroupE@Base 5.0.3 - _ZTSN3Dtk4Core14DTrashManager_E@Base 5.0.3 - _ZTSN3Dtk4Core15ConsoleAppenderE@Base 5.0.3 - _ZTSN3Dtk4Core15DSettingsOptionE@Base 5.0.3 - _ZTSN3Dtk4Core15QSettingBackendE@Base 5.0.3 - _ZTSN3Dtk4Core16AbstractAppenderE@Base 5.0.3 - _ZTSN3Dtk4Core16DBaseFileWatcherE@Base 5.0.3 - _ZTSN3Dtk4Core16DSettingsBackendE@Base 5.0.3 - _ZTSN3Dtk4Core16GSettingsBackendE@Base 5.0.3 - _ZTSN3Dtk4Core18DDiskSizeFormatterE@Base 5.0.3 - _ZTSN3Dtk4Core18DFileSystemWatcherE@Base 5.0.3 - _ZTSN3Dtk4Core18DTimeUnitFormatterE@Base 5.0.3 - _ZTSN3Dtk4Core19DFileWatcherManagerE@Base 5.0.3 - _ZTSN3Dtk4Core19DFileWatcherPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core19RollingFileAppenderE@Base 5.0.3 - _ZTSN3Dtk4Core20DTrashManagerPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core22AbstractStringAppenderE@Base 5.0.3 - _ZTSN3Dtk4Core22DAbstractUnitFormatterE@Base 5.0.3 - _ZTSN3Dtk4Core23DBaseFileWatcherPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core25DFileSystemWatcherPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core26DFileWatcherManagerPrivateE@Base 5.0.3 - _ZTSN3Dtk4Core5DUtil18DExportedInterfaceE@Base 5.0.3 - _ZTSN3Dtk4Core5DUtil25DExportedInterfacePrivateE@Base 5.0.3 - _ZTSN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceE@Base 5.0.3 - _ZTSN3Dtk4Core7DObjectE@Base 5.0.3 - _ZTSN3Dtk4Core9DSettingsE@Base 5.0.3 - _ZTSN3Dtk4Core9LogDeviceE@Base 5.0.3 - _ZTSSt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTSSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTSSt19_Sp_make_shared_tag@Base 5.0.3 - _ZTSSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTSSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTVN3Dtk4Core12DFileWatcherE@Base 5.0.3 - _ZTVN3Dtk4Core12FileAppenderE@Base 5.0.3 - _ZTVN3Dtk4Core13DTrashManagerE@Base 5.0.3 - _ZTVN3Dtk4Core14DObjectPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core14DSettingsGroupE@Base 5.0.3 - _ZTVN3Dtk4Core14DTrashManager_E@Base 5.0.3 - _ZTVN3Dtk4Core15ConsoleAppenderE@Base 5.0.3 - _ZTVN3Dtk4Core15DSettingsOptionE@Base 5.0.3 - _ZTVN3Dtk4Core15QSettingBackendE@Base 5.0.3 - _ZTVN3Dtk4Core16AbstractAppenderE@Base 5.0.3 - _ZTVN3Dtk4Core16DBaseFileWatcherE@Base 5.0.3 - _ZTVN3Dtk4Core16DSettingsBackendE@Base 5.0.3 - _ZTVN3Dtk4Core16GSettingsBackendE@Base 5.0.3 - _ZTVN3Dtk4Core18DDiskSizeFormatterE@Base 5.0.3 - _ZTVN3Dtk4Core18DFileSystemWatcherE@Base 5.0.3 - _ZTVN3Dtk4Core18DTimeUnitFormatterE@Base 5.0.3 - _ZTVN3Dtk4Core19DFileWatcherManagerE@Base 5.0.3 - _ZTVN3Dtk4Core19DFileWatcherPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core19RollingFileAppenderE@Base 5.0.3 - _ZTVN3Dtk4Core20DTrashManagerPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core22AbstractStringAppenderE@Base 5.0.3 - _ZTVN3Dtk4Core22DAbstractUnitFormatterE@Base 5.0.3 - _ZTVN3Dtk4Core23DBaseFileWatcherPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core25DFileSystemWatcherPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core26DFileWatcherManagerPrivateE@Base 5.0.3 - _ZTVN3Dtk4Core5DUtil18DExportedInterfaceE@Base 5.0.3 - _ZTVN3Dtk4Core5DUtil25DExportedInterfacePrivateE@Base 5.0.3 - _ZTVN3Dtk4Core5DUtil31DExportedInterfaceDBusInterfaceE@Base 5.0.3 - _ZTVN3Dtk4Core7DObjectE@Base 5.0.3 - _ZTVN3Dtk4Core9DSettingsE@Base 5.0.3 - _ZTVN3Dtk4Core9LogDeviceE@Base 5.0.3 - _ZTVSt23_Sp_counted_ptr_inplaceI9DDBusDataSaIS0_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZTVSt23_Sp_counted_ptr_inplaceIN3Dtk4Core5DUtil11DNotifyDataESaIS3_ELN9__gnu_cxx12_Lock_policyE2EE@Base 5.0.3 - _ZThn16_N3Dtk4Core12DFileWatcherD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core12DFileWatcherD1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core13DTrashManagerD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core13DTrashManagerD1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core14DTrashManager_D0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core14DTrashManager_D1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core16DBaseFileWatcherD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core16DBaseFileWatcherD1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core18DFileSystemWatcherD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core18DFileSystemWatcherD1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core19DFileWatcherManagerD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core19DFileWatcherManagerD1Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core5DUtil18DExportedInterfaceD0Ev@Base 5.0.3 - _ZThn16_N3Dtk4Core5DUtil18DExportedInterfaceD1Ev@Base 5.0.3 - _ZZN3Dtk4Core11DLogManager8instanceEvE8instance@Base 5.0.3 - _ZZN9QtPrivate15ConnectionTypesINS_4ListIJRK7QStringRK8QVariantEEELb1EE5typesEvE1t@Base 5.0.3 - _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag@Base 5.0.3 diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 0abf026..357b712 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,8 +1,7 @@ cmake_minimum_required (VERSION 3.10) find_package (Doxygen REQUIRED) - -set (QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/qt5/doc CACHE STRING "QCH install location") +set (QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/qt${QT_VERSION_MAJOR}/doc CACHE STRING "QCH install location") set (DOXYGEN_GENERATE_HTML YES CACHE STRING "Doxygen HTML output") set (DOXYGEN_GENERATE_XML YES CACHE STRING "Doxygen XML output") @@ -11,40 +10,68 @@ set (DOXYGEN_FILE_PATTERNS *.cpp *.h *.zh_CN.md *.zh_CN.dox CACHE STRING "Doxyge set (DOXYGEN_PROJECT_NUMBER ${CMAKE_PROJECT_VERSION} CACHE STRING "") # Should be the same as this project is using. set (DOXYGEN_EXTRACT_STATIC YES) set (DOXYGEN_OUTPUT_LANGUAGE "Chinese") -set (DOXYGEN_QHG_LOCATION "qhelpgenerator") + +if("${QT_VERSION_MAJOR}" STREQUAL "5") + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Help) +else() + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS ToolsTools) +endif() +get_target_property(_qhelpgenerator_location Qt${QT_VERSION_MAJOR}::qhelpgenerator IMPORTED_LOCATION) + +if("${_qhelpgenerator_location}" STREQUAL "") + set(_qhelpgenerator_location "qhelpgenerator") +endif() +set (DOXYGEN_QHG_LOCATION ${_qhelpgenerator_location} CACHE STRING "Doxygen QHG path") + set (DOXYGEN_QHP_NAMESPACE "org.deepin.dtk.core") set (DOXYGEN_QCH_FILE "dtkcore.qch") set (DOXYGEN_QHP_VIRTUAL_FOLDER "dtkcore") +set (DOXYGEN_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/docs/) + set (DOXYGEN_HTML_EXTRA_STYLESHEET "" CACHE STRING "Doxygen custom stylesheet for HTML output") set (DOXYGEN_TAGFILES "qtcore.tags=qthelp://org.qt-project.qtcore/qtcore/" CACHE STRING "Doxygen tag files") +set (DOXYGEN_IMAGE_PATH ${PROJECT_SOURCE_DIR}/docs/src) +set (DOXYGEN_SOURCE_BROWSE "YES") -set (DOXYGEN_MACRO_EXPANSION "YES") -set (DOXYGEN_PREDEFINED - "\"DCORE_BEGIN_NAMESPACE=namespace Dtk { namespace Core {\"" - "\"DCORE_END_NAMESPACE=}}\"" - "\"DCORE_USE_NAMESPACE=using namespace Dtk::Core\;\"" - "Q_OS_LINUX=1" -) -set (DOXYGEN_EXPAND_ONLY_PREDEF "YES") - +set (BUILD_THEME OFF CACHE BOOL "Build doxgen theme") if(BUILD_THEME) -set (DOXYGEN_HTML_EXTRA_STYLESHEET "docs/doxygentheme/doxygen-awesome.css" - "docs/doxygentheme/doxygen-awesome-sidebar-only.css" - "docs/doxygentheme/doxygen-awesome-sidebar-only-darkmode-toggle.css" +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/doxygen-theme") +message(STATUS "doxygen-theme exists") +else() +execute_process(COMMAND git clone https://github.com/linuxdeepin/doxygen-theme.git --depth=1 + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + TIMEOUT 60 + ) +execute_process(COMMAND bash themesetting.sh + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/doxygen-theme/ +) +endif() +set (DOXYGEN_HTML_EXTRA_STYLESHEET "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome.css" + "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-sidebar-only.css" + "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css" ) -set (DOXYGEN_HTML_EXTRA_FILES "docs/doxygentheme/doxygen-awesome-darkmode-toggle.js" - "docs/doxygentheme/doxygen-awesome-fragment-copy-button.js" - "docs/doxygentheme/doxygen-awesome-paragraph-link.js" - "docs/doxygentheme/doxygen-awesome-interactive-toc.js" +set (DOXYGEN_HTML_EXTRA_FILES "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js" + "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js" + "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-paragraph-link.js" + "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-interactive-toc.js" ) set (DOXYGEN_GENERATE_TREEVIEW "YES") set (DOXYGEN_DISABLE_INDEX "NO") set (DOXYGEN_FULL_SIDEBAR "NO") -set (DOXYGEN_HTML_HEADER "docs/doxygentheme/header.html") +set (DOXYGEN_HTML_HEADER "docs/doxygen-theme/doxygen-awesome-css/header.html") +set (DOXYGEN_HTML_FOOTER "docs/doxygen-theme/doxygen-awesome-css/footer.html") endif() +set (DOXYGEN_MACRO_EXPANSION "YES") +set (DOXYGEN_PREDEFINED + "DCORE_BEGIN_NAMESPACE=namespace Dtk { namespace Core {" + "DCORE_END_NAMESPACE=}}" + "DCORE_USE_NAMESPACE=using namespace Dtk::Core;" + "Q_OS_LINUX=1" +) +set (DOXYGEN_EXPAND_ONLY_PREDEF "YES") + doxygen_add_docs (doxygen - ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/docs ALL diff --git a/docs/MainPage.zh_CN.md b/docs/MainPage.zh_CN.md new file mode 100644 index 0000000..5d94ebf --- /dev/null +++ b/docs/MainPage.zh_CN.md @@ -0,0 +1,52 @@ +\mainpage dtkcore +@brief dtk + +# dtkcore + +## 简介 + +dtkcore 是一个基于Qt的C++库,它提供了一些常用的工具类,以及一些基础的模块,如日志、插件、网络、线程、数据库、文件、图形、音频、视频、系统信息等 + +## 使用 + +现在的dtkcore>=5.6版本使用CMake来管理各个模块,所以使用dtkcore时,需要先安装CMake(CMake>=3.10),然后需要在你的CMake项目中引入dtkcore的CMake模块,如下: + +```cmake +find_package(Dtk6Core REQUIRED) + +target_link_libraries( + Dtk6::Core +) +``` + +```qmake +QT += dtkcore +``` + +```bash +pkg-config --cflags --libs dtk6core + +# pkgconfig find Dtk6Core in qmake +# CONFIG += link_pkgconfig +# PKGCONFIG += dtk6core + +# pkgconfig find Dtk6Core in cmake +# find_package(PkgConfig REQUIRED) +# pkg_check_modules(Dtk6Core REQUIRED IMPORTED_TARGET dtk6core) +# target_link_libraries( PkgConfig::Dtk6Core ) +``` + +以上示例仅为最小示例,并不能单独作为CMake项目使用,需要你自己添加其他的CMake模块,如Qt的CMake模块,以及你自己的CMake模块. +@note 注意:dtkcore的QMake模块会自动引入Qt5的QMake模块,所以不需要再次引入Qt5的QMake模块,但是在使用CMake的时候必须手动引入Qtcore的CMake模块 + +## 文档 + +阅读文档建议从模块页面开始,模块页面提供了dtkcore的各个模块的简介,以及各个模块的使用示例。 +@subpage DLog + +dtkcore的文档使用doxygen管理,由deepin_doc_doc_go_sig提供维护支持, 如果你也想加入sig,请访问[deepin_doc_doc_go_sig](https://matrix.to/#/#deepin_doc_doc_go:matrix.org) + +## 许可 + +dtkcore使用LGPLv3许可证,你可在此许可证下自由使用dtkcore
+dtkcore的文档使用[CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/)许可证,你可在此许可证下自由使用dtkcore的文档,但是转发或者引用时必须注明出处。 diff --git a/docs/dci/ddcifile.zh_CN.dox b/docs/dci/ddcifile.zh_CN.dox new file mode 100644 index 0000000..f4ec4ce --- /dev/null +++ b/docs/dci/ddcifile.zh_CN.dox @@ -0,0 +1,113 @@ +/*! +@~chinese +@file include/dci/ddcifile.h +@ingroup dci + +@class Dtk::Core::DDciFile ddcifile.h +@brief ddcifile.h 是关于dci文件相关操作的一个类,实现了 DCI 文件的逻辑。其只是对数据的打包 +dci文件的结构路径如下: +![DCI图标结构路径](@ref dciicon-tree.png ) + +@enum Dtk::Core::DDciFile::FileType +@var Dtk::Core::DDciFile::FileType Dtk::Core::DDciFile::UnknowFile +@brief 未知文件 +@var Dtk::Core::DDciFile::FileType Dtk::Core::DDciFile::File +@brief 文件 +@var Dtk::Core::DDciFile::FileType Dtk::Core::DDciFile::Directory +@brief 目录 +@var Dtk::Core::DDciFile::FileType Dtk::Core::DDciFile::Symlink +@brief 软链接 + +@fn bool Dtk::Core::DDciFile::isValid() +@brief 判断读取的dci文件是否有效 +@details 当指定的dci文件未成功加载时,此函数会返回false,一般会出现在文件格式错误(不是一个dci格式的文件),或者是dci文件数据被篡改而无法识别的情况 +@note 本类中所有涉及文件操作的函数均会首先执行此方法,故如无必要,无需手动确保文件是否有效 + +@fn QString Dtk::Core::DDciFile::lastErrorString() +@brief 获取上一个报错信息,为人类可读字符串,可以通过此报错信息来获取错误内容,一般情况下是因为文件不存在或者文件名过长(>62个字符)导致。 + +@fn bool Dtk::Core::DDciFile::writeToFile(const QString &fileName) +@brief 写入文件,在做完对于dci文件的操作之后调用此接口,为保存的作用 +@param[in] fileName 文件名 + +@fn bool Dtk::Core::DDciFile::writeToDevice(QIODevice *device) +@brief 写入到设备,设备指的是qt中的io设备,可以在qt文档中找到相关信息 +@param[in] device IO设备 +@sa [QIODevice](https://doc.qt.io/qt-6/qiodevice.html) + +@fn QByteArray Dtk::Core::DDciFile::toData() +@brief 返回dci文件的原始数据,以QByteArray形式返回 +@retval 如果返回为空字符串则说明读取失败 +@sa DDciFile::writeFile + +@fn static constexpr int Dtk::Core::DDciFile::metadataSizeV1() +@brief MAGIC_SIZE + VERSION_SIZE + FILE_COUNT_SIZE: 4+1+3 = 8 + +@fn QStringList Dtk::Core::DDciFile::list(const QString &dir, bool onlyFileName = false) +@brief 列出文件列表 +@param[in] dir 文件夹地址 +@param[in] onlyFileName 是否只显示文件名 默认为false + +@fn int Dtk::Core::DDciFile::childrenCount(const QString &dir) +@brief 子文件计数 + +@fn bool Dtk::Core::DDciFile::exists(const QString &filePath) +@brief 判断文件是否存在 +@param[in] filePath DCI图标结构路径 + +@fn FileType Dtk::Core::DDciFile::type(const QString &filePath) +@brief 判断文件类型 +@sa DDciFile::FileType +@param[in] filePath DCI图标结构路径 + +@fn QByteArray Dtk::Core::DDciFile::dataRef(const QString &filePath) +@brief 获取dci内部文件的数据,以一种引用(软连接)的方式获取,不会产生数据的的复制 +@param[in] filePath DCI图标结构路径 +@retval 如果返回为空字符串,则说明此文件不存在或者无效 + +@fn QString Dtk::Core::DDciFile::name(const QString &filePath) +@brief 获取dci内文件的文件名 +@param[in] filePath DCI图标结构路径 +@retval 如果返回为空字符串,则说明此文件不存在或者无效 + +@fn QString Dtk::Core::DDciFile::symlinkTarget(const QString &filePath, bool originData = false) +@brief 获取软链目标 +@param[in] filePath DCI图标结构路径 +@param[in] originData +@retval 如果返回为空字符串,则说明此文件不存在或者无效 +@note 链接的目标只能是“不存在的路径”、“文件”、“链接”,不可是目录 + +@fn bool Dtk::Core::DDciFile::mkdir(const QString &filePath) +@brief 创建目录(注意:此目录指的是在dci文件内部的目录,而不是指的是传统目录) +@param[in] filePath DCI图标结构路径 +@return 操作是否成功 + +@fn bool Dtk::Core::DDciFile::writeFile(const QString &filePath, const QByteArray &data, bool override = false) +@brief 写入文件 +@param[in] filePath DCI图标结构路径 +@param[in] data 数据内容 +@param[in] override 当文件已经存在时,是否覆盖此文件,默认状态下不执行覆盖,会在lasterror中记录"The target file is existed"错误信息。 +如果传入为true,则会执行覆盖操作,** 此操作不可逆 **。 +@return 操作是否成功 +@sa QByteArray DDciFile::toData() + +@fn bool Dtk::Core::DDciFile::remove(const QString &filePath) +@brief 移除文件 +@param[in] filePath DCI图标结构路径 +@return 操作是否成功 + +@fn bool Dtk::Core::DDciFile::rename(const QString &filePath, const QString &newFilePath, bool override = false) +@brief 重命名文件 +@param[in] filePath DCI图标结构路径 +@param[in] newFilePath 新文件的路径 +@param[in] override 当文件已经存在时,是否覆盖此文件,默认状态下不执行覆盖,会在lasterror中记录"The target file is existed"错误信息。 +如果传入为true,则会执行覆盖操作,** 此操作不可逆 **。 +@return 操作是否成功 + +@fn bool Dtk::Core::DDciFile::link(const QString &source, const QString &to) +@brief 链接文件 +@param[in] source 文件源 +@param[in] to 链接目标 +@return 操作是否成功 + +*/ diff --git a/docs/dci/index.zh_CN.md b/docs/dci/index.zh_CN.md new file mode 100644 index 0000000..9f0fc38 --- /dev/null +++ b/docs/dci/index.zh_CN.md @@ -0,0 +1,92 @@ +@page dci dci--dci图标工具类 +# DTk dci:dci工具类 + +关于dtkcore提供的dci工具见:[DCI](group__dci.html#files)
+下面内容是关于dci文件的简介,还有一部分使用以及工具将会在以后的文档中提供 +## 关于dci图标简介 + + +`DCI` 图标是一种整合性图标格式,应用可以使用该图标完成多种状态的自动变化。例如, `ListView` 控件中高亮的 `Item` 图标自动反白,`Menu` 中图标跟随当前 `Item` 变化等等。 + +`dtkcore` 中提供了一个 `DDciFile` 的类,实现 `DCI` 文件的逻辑。其只是对数据的打包,不限于图片数据,可以是任何文本和二进制数据。 `dtkcore` 中还提供了用于在文管中解析文件的文件引擎,专门用于通过 `QFile` 和 `QDir` 处理 `dci` 文件。 + +dtkgui 中提供了一个 `DDciIcon` 类,实现了对 `DCI` 图标的逻辑。区别于 `DDciFile` ,它是 `DDciFile` 的上层封装,即使用 DDciFile 可以将文件进行打包归档的功能,封装了一种图标格式。 `DDciIcon` 中提供的接口,都是针对图标的,并无 `DDciFile` 的数据处理操作,多个 `DDciIcon` 进行数据拷贝和交换时,可以进行数据共享。 `DDciIcon` 可以通过调用 pixmap 函数返回需要显示的图片数据,也可以通过调用 paint 函数直接将内容绘制到目标内部。解析 Dci 图标的过程,这里讲解一下,详细过程可以查看代码理解: +首先需要创建一个 DDciFile 来解析 (*.dci) 文件,无论是本地文本还是二进制数据,都可以通过 `DDciFile` 来解析内部内容。 +根据 `DDciIcon` 中规定好的路径格式,来解析出图标中拟定的各种信息,一般情况下的 `DDciIcon` 的路径格式是这样的: + +![DCI图标结构路径](@ref dciicon-tree.png ) + +最上层时 `/` 作为根目录( `DCI` 文件都必须使用 `/` 作为根目录)。 +第一层子目录( 16、32、512 )作为图标的大小。一般情况下是图标在 @1(1倍缩放比) 时的大小(在目前的使用设计师使用的 dci 图标插件的)。例如上述图标,传入的大小在 0-16时选择 16,传入大小在 16-32 时选择 32,... 以此类推。 + +第二层目录( `normal.light` )作为该层图标的状态和主题,其中状态分为 `Normal` , `Disabled` , `Hovered` 和 `Pressed` 四种,主题分为 `light` 和 `dark` 两种。四种状态和两种主题可产生 8 种组合,也就是说,每种大小的图标最多有八种不同状态和主题的子图标进行切换。需要注意的是:状态和主题存在缺省模式: `normal` 和 `light` 。如果传入的状态和主题在所属大小的子图标下未找到,则选择缺省模式的状态和主题。也就是说,当图标的 `Normal` 和 `light` 状态未找到任何图标时,该图标是无效的。一般情况下,如果图标不会在不同状态和主题下发生过大的样式修改,只修改内部颜色填充时,可以不添加特殊状态的图标,通过修改调色版解决。(后面提及) + + 第三层目录(1、2)作为缩放比系数,可以存放多个缩放比系数来适配系统的缩放比。例如上述示例:缩放比系数在1和2之间时,选择 2,大于 2 时,选择 2 ,默认情况下选择 1。目前提供的图标中,为了保证尽量减少图标文件的大小,仅保存缩放比为 3 的文件。在软件层面进行缩放。 +第四层(1.png)描述图标图片文件(图层)所携带的信息。这些信息中,包含:图层优先级、外边框数值、调色板格式、颜色调整数值、图层格式。可以通过下述文件表 +``` +├── 1.7p.3.png.alpha8 +├── 2.3.webp +└── 3.7p.3_0_0_-10_0_0_0_0.png.alpha8 + │ │ │ │ │ │ ┕━┳━┙┕━┳━┙ + │ │ │ │ │ │ rgba format + │ │ │ │ │ │ + │ │ │ │ │ └─ lightness (亮度) + │ │ │ │ └─ saturation (饱和度) + │ │ │ └─ hue (色调) + │ │ └─ palette (高亮色3) + │ └─ padding (填充间隔) + └─ prior (图层) + +.[padding].. +``` +下面进行一一介绍: + +* **图层优先级**(`prior`):优先级代表图层的绘制顺序,从 1-n 进行绘制,最底层的图层会被上层图层覆盖。 + +* **外边框数值**(`padding`):外边框在有阴影效果的图标中充分利用。 `padding` 代表图层外围不被控件大小覆盖的区域。 + + ![layout](@ref layout.png) + + 类似控件的布局方式,这里可以之看 `padding` 部分, `padding` 定义四周所有数据,举个例子,如果子图标的大小是 32 (第一层目录的数值),一倍缩放比下,如果该图层的 `padding` 大小时 5,那么该图层的真实图片大小是:[32 + 5 × 2, 32 + 5 × 2] = [42, 42]。但最终, `padding` 区域的大小并不计算在整个图标大小内(仅针对 QML,dtkwidget 不支持)。为了区别其他数据, `padding` 的数值后面使用 `'p'` 进行结尾。例如上述示例:`'7p'` 。 + +* **调色板格式** :当存在调色板时,就表示该图标的颜色是通过调色板的颜色进行动态变化的,外部修改调色板颜色后,预览效果会随之发生变化。因此该图标有两种特性:1. 可以转换成 alpha8 格式; 2. 可以不需要其他状态,通过调色板变化即可。当无调色板时,该部分的数值为空。调色板格式分为5种:无效(-1)、前景色(0)、背景色(1)、高亮前景色(2)、高亮色(3)。 + +* **颜色调整数值** :颜色调整只针对有调色板的图层(调色板格式部分数据不为空)时。一旦存在,必须要将其所有的数据写入,例如上述示例。颜色调整数值使用 '_' 进行分割。 + 每个部分表示:hu、saturation、lightness、red、green、blue、alpha。 + +* **图层格式** :图层格式可以使用:"png"、"jpg"、"webp"。如果图层存在调色板格式,就意味着可以优化其大小,转化为 alpha8 格式,使用".alpha8" 作为后缀,进行标识,在软件渲染时进行进行复原。 + +`DCI` 图标的细节介绍在 应用图标,上面主要介绍 `DCI` 图标的整个结构和在 `QML` 中的使用方式。其主要是设计实现了一种特殊格式的文件(.dci),该种格式通过路径,名称和文件数据,打包到同一个文件内,使不同状态、大小、主题的多个图标图片,整合到同一个文件内,在程序内部自动匹配当前状态,选择合适的图标图片。因此,总的来说, `DCI` 图标是对多个图标图片的打包归档。 + +本文将介绍 `DCI` 图标在 `dtkwidget` 和 `dtkdeclarative` 中的使用,对于一些 `DCI` 图标相关的高级知识(使用方无需过度关心),如 “DDciIconPalette”、“缩放比的适配”以及“图片的格式”等等。 + +**请注意:** 当使用 `DciIcon` 时,如果您认为控件在某种状态下需要进行图标变色或更换图标而未出现时,可能是由于**设计提供的图标未指定变色所需要的调色板对象(可以理解为图标出错)** 或 **设计认为该种场景下不需要变色(即固定样式图标)**,请及时与设计沟通。 + +### 1. 图标状态 + +大部分控件可以分为 `Normal` 、 `Hovered` 、 `Pressed` 和 `Disabled` 四种状态。这四种状态是每种控件的基础状态。因此将使用这几种状态作为图标的状态分类。 + +#### 答疑 + +1. 为什么没有 `Checked` 和 `Inactive` 类似这样的状态? + + `Checked` 状态属于复合状态,并不属于基础状态。 `Checked` 状态下,可以有 `Hovered` 、 `Pressed` 、 `Normal` 等等状态,相同地, `Unchecked` 状态也会存在一样的情况。因此, `Checked` 状态并不适合作为 `DCI` 图标的状态。对于需要时,可通过控件的 `checked` 状态属性,切换下不同的图标即可。 + + `Inactive` 状态作为窗口的状态,在 `DTK` 应用都会通过降低透明度的方式实现,而不是作为图标状态。 + +2. 为什么需要这些状态? + + 存在这些状态的原因是,为了让应用和开发者更加无感知的使用图标,而无需关心不同状态下进行图标切换的操作。方便设计师一次提供多种状态的图标到一个图标文件中,进行压缩整合。防止出现图标资源较多,占用较大系统内存,同时能够帮助设计师在控件的不同状态下,不仅仅只局限于修改图标颜色这一种功能,也可以通过不同的图标代替,更适合多样化的样式设计。 + +3. 图标不显示可能是什么原因? + + 很可能是 webp 格式的支持问题, 查看一下系统中是否安装 `qt5-image-formats-plugins` ,这个包中有对 webp 格式图片格式的支持。 + +### 2. 图标大小和缩放比 + +应用所关心的图标大小是否正常,是否能够适配高缩放比模式等等。 `DCI` 图标中都做到了这些,默认情况下,设计师所提供的图标大小能够满足应用开发的需求,应用只需要主动调用接口指定图标大小即可,例如 `dtkwidget`,中 `DIconButton` 可以使用 `setIconSize` 指定; `QML` 中可以指定 `DciIcon` 控件的 `sourceSize` 或者 `Button` 控件的 `icon.size` 等等。而对于高缩放比的适配, `DTK` 已经全部完成无需应用关心。 + + +@defgroup dci +@brief dtkdci图标工具类, 提供对于dci文件的操作方法 +@details 详细内容可见 [DCI图标简介](md_docs_dci_index_zh_CN.html#autotoc_md0) diff --git a/docs/doxygentheme/custom-alternative.css b/docs/doxygentheme/custom-alternative.css deleted file mode 100644 index e66c1ae..0000000 --- a/docs/doxygentheme/custom-alternative.css +++ /dev/null @@ -1,54 +0,0 @@ -html.alternative { - /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ - --primary-color: #AF7FE4; - --primary-dark-color: #9270E4; - --primary-light-color: #7aabd6; - --primary-lighter-color: #cae1f1; - --primary-lightest-color: #e9f1f8; - - /* page base colors */ - --page-background-color: white; - --page-foreground-color: #2c3e50; - --page-secondary-foreground-color: #67727e; - - - --border-radius-large: 22px; - --border-radius-small: 9px; - --border-radius-medium: 14px; - --spacing-small: 8px; - --spacing-medium: 14px; - --spacing-large: 19px; - - --top-height: 125px; - - --side-nav-background: #324067; - --side-nav-foreground: #F1FDFF; - --header-foreground: var(--side-nav-foreground); - --searchbar-background: var(--side-nav-foreground); - --searchbar-border-radius: var(--border-radius-medium); - --header-background: var(--side-nav-background); - --header-foreground: var(--side-nav-foreground); - - --toc-background: rgb(243, 240, 252); - --toc-foreground: var(--page-foreground-color); -} - -html.alternative.dark-mode { - color-scheme: dark; - - --primary-color: #AF7FE4; - --primary-dark-color: #9270E4; - --primary-light-color: #4779ac; - --primary-lighter-color: #191e21; - --primary-lightest-color: #191a1c; - - --page-background-color: #1C1D1F; - --page-foreground-color: #d2dbde; - --page-secondary-foreground-color: #859399; - --separator-color: #3a3246; - --side-nav-background: #171D32; - --side-nav-foreground: #F1FDFF; - --toc-background: #20142C; - --searchbar-background: var(--page-background-color); - -} \ No newline at end of file diff --git a/docs/doxygentheme/custom.css b/docs/doxygentheme/custom.css deleted file mode 100644 index 0e694c0..0000000 --- a/docs/doxygentheme/custom.css +++ /dev/null @@ -1,101 +0,0 @@ -.github-corner svg { - fill: var(--primary-light-color); - color: var(--page-background-color); - width: 72px; - height: 72px; -} - -@media screen and (max-width: 767px) { - .github-corner svg { - width: 50px; - height: 50px; - } - #projectnumber { - margin-right: 22px; - } -} - -.alter-theme-button { - display: inline-block; - cursor: pointer; - background: var(--primary-color); - color: var(--page-background-color) !important; - border-radius: var(--border-radius-medium); - padding: var(--spacing-small) var(--spacing-medium); - text-decoration: none; -} - -.next_section_button { - display: block; - padding: var(--spacing-large) 0 var(--spacing-small) 0; - color: var(--page-background-color); - user-select: none; -} - -.next_section_button::after { - /* clearfix */ - content: ""; - clear: both; - display: table; -} - -.next_section_button a { - overflow: hidden; - float: right; - border: 1px solid var(--separator-color); - padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large); - border-radius: var(--border-radius-medium); - color: var(--page-secondary-foreground-color) !important; - text-decoration: none; - background-color: var(--page-background-color); - transition: color .08s ease-in-out, background-color .1s ease-in-out; -} - -.next_section_button a:hover { - color: var(--page-foreground-color) !important; - background-color: var(--odd-color); -} - -.next_section_button a::after { - content: '〉'; - color: var(--page-secondary-foreground-color) !important; - padding-left: var(--spacing-large); - display: inline-block; - transition: color .08s ease-in-out, transform .09s ease-in-out; -} - -.next_section_button a:hover::after { - color: var(--page-foreground-color) !important; - transform: translateX(3px); -} - -.alter-theme-button:hover { - background: var(--primary-dark-color); -} - -html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */ -html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { - filter: brightness(87%) hue-rotate(180deg) invert(); -} - -.bordered_image { - border-radius: var(--border-radius-small); - border: 1px solid var(--separator-color); - display: inline-block; - overflow: hidden; -} - -html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */ -html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { - border-radius: var(--border-radius-small); -} - -.title_screenshot { - filter: drop-shadow(0px 3px 10px rgba(0,0,0,0.22)); - max-width: 500px; - margin: var(--spacing-large) 0; -} - -.title_screenshot .caption { - display: none; -} \ No newline at end of file diff --git a/docs/doxygentheme/doxygen-awesome-darkmode-toggle.js b/docs/doxygentheme/doxygen-awesome-darkmode-toggle.js deleted file mode 100644 index f2c5853..0000000 --- a/docs/doxygentheme/doxygen-awesome-darkmode-toggle.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2021 - 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -class DoxygenAwesomeDarkModeToggle extends HTMLElement { - // SVG icons from https://fonts.google.com/icons - // Licensed under the Apache 2.0 license: - // https://www.apache.org/licenses/LICENSE-2.0.html - static lightModeIcon = `` - static darkModeIcon = `` - static title = "Toggle Light/Dark Mode" - - static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" - static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" - - static _staticConstructor = function() { - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) - // Update the color scheme when the browsers preference changes - // without user interaction on the website. - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { - DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() - }) - // Update the color scheme when the tab is made visible again. - // It is possible that the appearance was changed in another tab - // while this tab was in the background. - document.addEventListener("visibilitychange", visibilityState => { - if (document.visibilityState === 'visible') { - DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() - } - }); - }() - - static init() { - $(function() { - $(document).ready(function() { - const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') - toggleButton.title = DoxygenAwesomeDarkModeToggle.title - toggleButton.updateIcon() - - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { - toggleButton.updateIcon() - }) - document.addEventListener("visibilitychange", visibilityState => { - if (document.visibilityState === 'visible') { - toggleButton.updateIcon() - } - }); - - $(document).ready(function(){ - document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) - }) - $(window).resize(function(){ - document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) - }) - }) - }) - } - - constructor() { - super(); - this.onclick=this.toggleDarkMode - } - - /** - * @returns `true` for dark-mode, `false` for light-mode system preference - */ - static get systemPreference() { - return window.matchMedia('(prefers-color-scheme: dark)').matches - } - - /** - * @returns `true` for dark-mode, `false` for light-mode user preference - */ - static get userPreference() { - return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || - (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) - } - - static set userPreference(userPreference) { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference - if(!userPreference) { - if(DoxygenAwesomeDarkModeToggle.systemPreference) { - localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) - } else { - localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) - } - } else { - if(!DoxygenAwesomeDarkModeToggle.systemPreference) { - localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) - } else { - localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) - } - } - DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() - } - - static enableDarkMode(enable) { - if(enable) { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = true - document.documentElement.classList.add("dark-mode") - document.documentElement.classList.remove("light-mode") - } else { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = false - document.documentElement.classList.remove("dark-mode") - document.documentElement.classList.add("light-mode") - } - } - - static onSystemPreferenceChanged() { - DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) - } - - static onUserPreferenceChanged() { - DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) - } - - toggleDarkMode() { - DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference - this.updateIcon() - } - - updateIcon() { - if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { - this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon - } else { - this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon - } - } -} - -customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); diff --git a/docs/doxygentheme/doxygen-awesome-fragment-copy-button.js b/docs/doxygentheme/doxygen-awesome-fragment-copy-button.js deleted file mode 100644 index 7d06b34..0000000 --- a/docs/doxygentheme/doxygen-awesome-fragment-copy-button.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -class DoxygenAwesomeFragmentCopyButton extends HTMLElement { - constructor() { - super(); - this.onclick=this.copyContent - } - static title = "Copy to clipboard" - static copyIcon = `` - static successIcon = `` - static successDuration = 980 - static init() { - $(function() { - $(document).ready(function() { - if(navigator.clipboard) { - const fragments = document.getElementsByClassName("fragment") - for(const fragment of fragments) { - const fragmentWrapper = document.createElement("div") - fragmentWrapper.className = "doxygen-awesome-fragment-wrapper" - const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button") - fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon - fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title - - fragment.parentNode.replaceChild(fragmentWrapper, fragment) - fragmentWrapper.appendChild(fragment) - fragmentWrapper.appendChild(fragmentCopyButton) - - } - } - }) - }) - } - - - copyContent() { - const content = this.previousSibling.cloneNode(true) - // filter out line number from file listings - content.querySelectorAll(".lineno, .ttc").forEach((node) => { - node.remove() - }) - let textContent = content.textContent - // remove trailing newlines that appear in file listings - let numberOfTrailingNewlines = 0 - while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') { - numberOfTrailingNewlines++; - } - textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines) - navigator.clipboard.writeText(textContent); - this.classList.add("success") - this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon - window.setTimeout(() => { - this.classList.remove("success") - this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon - }, DoxygenAwesomeFragmentCopyButton.successDuration); - } -} - -customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton) diff --git a/docs/doxygentheme/doxygen-awesome-interactive-toc.js b/docs/doxygentheme/doxygen-awesome-interactive-toc.js deleted file mode 100644 index b049f57..0000000 --- a/docs/doxygentheme/doxygen-awesome-interactive-toc.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -class DoxygenAwesomeInteractiveToc { - static topOffset = 38 - static hideMobileMenu = true - static headers = [] - - static init() { - window.addEventListener("load", () => { - let toc = document.querySelector(".contents > .toc") - if(toc) { - toc.classList.add("interactive") - if(!DoxygenAwesomeInteractiveToc.hideMobileMenu) { - toc.classList.add("open") - } - document.querySelector(".contents > .toc > h3")?.addEventListener("click", () => { - if(toc.classList.contains("open")) { - toc.classList.remove("open") - } else { - toc.classList.add("open") - } - }) - - document.querySelectorAll(".contents > .toc > ul a").forEach((node) => { - let id = node.getAttribute("href").substring(1) - DoxygenAwesomeInteractiveToc.headers.push({ - node: node, - headerNode: document.getElementById(id) - }) - - document.getElementById("doc-content")?.addEventListener("scroll", () => { - DoxygenAwesomeInteractiveToc.update() - }) - }) - DoxygenAwesomeInteractiveToc.update() - } - }) - } - - static update() { - let active = DoxygenAwesomeInteractiveToc.headers[0]?.node - DoxygenAwesomeInteractiveToc.headers.forEach((header) => { - let position = header.headerNode.getBoundingClientRect().top - header.node.classList.remove("active") - header.node.classList.remove("aboveActive") - if(position < DoxygenAwesomeInteractiveToc.topOffset) { - active = header.node - active?.classList.add("aboveActive") - } - }) - active?.classList.add("active") - active?.classList.remove("aboveActive") - } -} \ No newline at end of file diff --git a/docs/doxygentheme/doxygen-awesome-paragraph-link.js b/docs/doxygentheme/doxygen-awesome-paragraph-link.js deleted file mode 100644 index 6424dbd..0000000 --- a/docs/doxygentheme/doxygen-awesome-paragraph-link.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -class DoxygenAwesomeParagraphLink { - // Icon from https://fonts.google.com/icons - // Licensed under the Apache 2.0 license: - // https://www.apache.org/licenses/LICENSE-2.0.html - static icon = `` - static title = "Permanent Link" - static init() { - $(function() { - $(document).ready(function() { - document.querySelectorAll(".contents a.anchor[id], .contents .groupheader > a[id]").forEach((node) => { - let anchorlink = document.createElement("a") - anchorlink.setAttribute("href", `#${node.getAttribute("id")}`) - anchorlink.setAttribute("title", DoxygenAwesomeParagraphLink.title) - anchorlink.classList.add("anchorlink") - node.classList.add("anchor") - anchorlink.innerHTML = DoxygenAwesomeParagraphLink.icon - node.parentElement.appendChild(anchorlink) - }) - }) - }) - } -} diff --git a/docs/doxygentheme/doxygen-awesome-sidebar-only-darkmode-toggle.css b/docs/doxygentheme/doxygen-awesome-sidebar-only-darkmode-toggle.css deleted file mode 100644 index b988b6f..0000000 --- a/docs/doxygentheme/doxygen-awesome-sidebar-only-darkmode-toggle.css +++ /dev/null @@ -1,40 +0,0 @@ - -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2021 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -@media screen and (min-width: 768px) { - - #MSearchBox { - width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px); - } - - #MSearchField { - width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height)); - } -} diff --git a/docs/doxygentheme/doxygen-awesome-sidebar-only.css b/docs/doxygentheme/doxygen-awesome-sidebar-only.css deleted file mode 100644 index 656ebbf..0000000 --- a/docs/doxygentheme/doxygen-awesome-sidebar-only.css +++ /dev/null @@ -1,115 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2021 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - */ - -html { - /* side nav width. MUST be = `TREEVIEW_WIDTH`. - * Make sure it is wide enough to contain the page title (logo + title + version) - */ - --side-nav-fixed-width: 335px; - --menu-display: none; - - --top-height: 120px; - --toc-sticky-top: -25px; - --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px); -} - -#projectname { - white-space: nowrap; -} - - -@media screen and (min-width: 768px) { - html { - --searchbar-background: var(--page-background-color); - } - - #side-nav { - min-width: var(--side-nav-fixed-width); - max-width: var(--side-nav-fixed-width); - top: var(--top-height); - overflow: visible; - } - - #nav-tree, #side-nav { - height: calc(100vh - var(--top-height)) !important; - } - - #nav-tree { - padding: 0; - } - - #top { - display: block; - border-bottom: none; - height: var(--top-height); - margin-bottom: calc(0px - var(--top-height)); - max-width: var(--side-nav-fixed-width); - overflow: hidden; - background: var(--side-nav-background); - } - #main-nav { - float: left; - padding-right: 0; - } - - .ui-resizable-handle { - cursor: default; - width: 1px !important; - box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color); - } - - #nav-path { - position: fixed; - right: 0; - left: var(--side-nav-fixed-width); - bottom: 0; - width: auto; - } - - #doc-content { - height: calc(100vh - 31px) !important; - padding-bottom: calc(3 * var(--spacing-large)); - padding-top: calc(var(--top-height) - 80px); - box-sizing: border-box; - margin-left: var(--side-nav-fixed-width) !important; - } - - #MSearchBox { - width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium))); - } - - #MSearchField { - width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px); - } - - #MSearchResultsWindow { - left: var(--spacing-medium) !important; - right: auto; - } -} diff --git a/docs/doxygentheme/doxygen-awesome.css b/docs/doxygentheme/doxygen-awesome.css deleted file mode 100644 index abd2893..0000000 --- a/docs/doxygentheme/doxygen-awesome.css +++ /dev/null @@ -1,2405 +0,0 @@ -/** - -Doxygen Awesome -https://github.com/jothepro/doxygen-awesome-css - -MIT License - -Copyright (c) 2021 - 2022 jothepro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -html { - /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ - --primary-color: #1779c4; - --primary-dark-color: #335c80; - --primary-light-color: #70b1e9; - - /* page base colors */ - --page-background-color: #ffffff; - --page-foreground-color: #2f4153; - --page-secondary-foreground-color: #6f7e8e; - - /* color for all separators on the website: hr, borders, ... */ - --separator-color: #dedede; - - /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ - --border-radius-large: 8px; - --border-radius-small: 4px; - --border-radius-medium: 6px; - - /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ - --spacing-small: 5px; - --spacing-medium: 10px; - --spacing-large: 16px; - - /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ - --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); - - --odd-color: rgba(0,0,0,.028); - - /* font-families. will affect all text on the website - * font-family: the normal font for text, headlines, menus - * font-family-monospace: used for preformatted text in memtitle, code, fragments - */ - --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; - --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; - - /* font sizes */ - --page-font-size: 15.6px; - --navigation-font-size: 14.4px; - --toc-font-size: 13.4px; - --code-font-size: 14px; /* affects code, fragment */ - --title-font-size: 22px; - - /* content text properties. These only affect the page content, not the navigation or any other ui elements */ - --content-line-height: 27px; - /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ - --content-maxwidth: 1050px; - --table-line-height: 24px; - --toc-sticky-top: var(--spacing-medium); - --toc-width: 200px; - --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); - - /* colors for various content boxes: @warning, @note, @deprecated @bug */ - --warning-color: #f8d1cc; - --warning-color-dark: #b61825; - --warning-color-darker: #75070f; - --note-color: #faf3d8; - --note-color-dark: #f3a600; - --note-color-darker: #5f4204; - --todo-color: #e4f3ff; - --todo-color-dark: #1879C4; - --todo-color-darker: #274a5c; - --deprecated-color: #ecf0f3; - --deprecated-color-dark: #5b6269; - --deprecated-color-darker: #43454a; - --bug-color: #e4dafd; - --bug-color-dark: #5b2bdd; - --bug-color-darker: #2a0d72; - --invariant-color: #d8f1e3; - --invariant-color-dark: #44b86f; - --invariant-color-darker: #265532; - - /* blockquote colors */ - --blockquote-background: #f8f9fa; - --blockquote-foreground: #636568; - - /* table colors */ - --tablehead-background: #f1f1f1; - --tablehead-foreground: var(--page-foreground-color); - - /* menu-display: block | none - * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. - * `GENERATE_TREEVIEW` MUST be enabled! - */ - --menu-display: block; - - --menu-focus-foreground: var(--page-background-color); - --menu-focus-background: var(--primary-color); - --menu-selected-background: rgba(0,0,0,.05); - - - --header-background: var(--page-background-color); - --header-foreground: var(--page-foreground-color); - - /* searchbar colors */ - --searchbar-background: var(--side-nav-background); - --searchbar-foreground: var(--page-foreground-color); - - /* searchbar size - * (`searchbar-width` is only applied on screens >= 768px. - * on smaller screens the searchbar will always fill the entire screen width) */ - --searchbar-height: 33px; - --searchbar-width: 210px; - --searchbar-border-radius: var(--searchbar-height); - - /* code block colors */ - --code-background: #f5f5f5; - --code-foreground: var(--page-foreground-color); - - /* fragment colors */ - --fragment-background: #F8F9FA; - --fragment-foreground: #37474F; - --fragment-keyword: #bb6bb2; - --fragment-keywordtype: #8258b3; - --fragment-keywordflow: #d67c3b; - --fragment-token: #438a59; - --fragment-comment: #969696; - --fragment-link: #5383d6; - --fragment-preprocessor: #46aaa5; - --fragment-linenumber-color: #797979; - --fragment-linenumber-background: #f4f4f5; - --fragment-linenumber-border: #e3e5e7; - --fragment-lineheight: 20px; - - /* sidebar navigation (treeview) colors */ - --side-nav-background: #fbfbfb; - --side-nav-foreground: var(--page-foreground-color); - --side-nav-arrow-opacity: 0; - --side-nav-arrow-hover-opacity: 0.9; - - --toc-background: var(--side-nav-background); - --toc-foreground: var(--side-nav-foreground); - - /* height of an item in any tree / collapsable table */ - --tree-item-height: 30px; - - --memname-font-size: var(--code-font-size); - --memtitle-font-size: 18px; - - --webkit-scrollbar-size: 7px; - --webkit-scrollbar-padding: 4px; - --webkit-scrollbar-color: var(--separator-color); -} - -@media screen and (max-width: 767px) { - html { - --page-font-size: 16px; - --navigation-font-size: 16px; - --toc-font-size: 15px; - --code-font-size: 15px; /* affects code, fragment */ - --title-font-size: 22px; - } -} - -@media (prefers-color-scheme: dark) { - html:not(.light-mode) { - color-scheme: dark; - - --primary-color: #1982d2; - --primary-dark-color: #86a9c4; - --primary-light-color: #4779ac; - - --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); - - --odd-color: rgba(100,100,100,.06); - - --menu-selected-background: rgba(0,0,0,.4); - - --page-background-color: #1C1D1F; - --page-foreground-color: #d2dbde; - --page-secondary-foreground-color: #859399; - --separator-color: #38393b; - --side-nav-background: #252628; - - --code-background: #2a2c2f; - - --tablehead-background: #2a2c2f; - - --blockquote-background: #222325; - --blockquote-foreground: #7e8c92; - - --warning-color: #2e1917; - --warning-color-dark: #ad2617; - --warning-color-darker: #f5b1aa; - --note-color: #3b2e04; - --note-color-dark: #f1b602; - --note-color-darker: #ceb670; - --todo-color: #163750; - --todo-color-dark: #1982D2; - --todo-color-darker: #dcf0fa; - --deprecated-color: #2e323b; - --deprecated-color-dark: #738396; - --deprecated-color-darker: #abb0bd; - --bug-color: #2a2536; - --bug-color-dark: #7661b3; - --bug-color-darker: #ae9ed6; - --invariant-color: #303a35; - --invariant-color-dark: #76ce96; - --invariant-color-darker: #cceed5; - - --fragment-background: #282c34; - --fragment-foreground: #dbe4eb; - --fragment-keyword: #cc99cd; - --fragment-keywordtype: #ab99cd; - --fragment-keywordflow: #e08000; - --fragment-token: #7ec699; - --fragment-comment: #999999; - --fragment-link: #98c0e3; - --fragment-preprocessor: #65cabe; - --fragment-linenumber-color: #cccccc; - --fragment-linenumber-background: #35393c; - --fragment-linenumber-border: #1f1f1f; - } -} - -/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ -html.dark-mode { - color-scheme: dark; - - --primary-color: #1982d2; - --primary-dark-color: #86a9c4; - --primary-light-color: #4779ac; - - --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); - - --odd-color: rgba(100,100,100,.06); - - --menu-selected-background: rgba(0,0,0,.4); - - --page-background-color: #1C1D1F; - --page-foreground-color: #d2dbde; - --page-secondary-foreground-color: #859399; - --separator-color: #38393b; - --side-nav-background: #252628; - - --code-background: #2a2c2f; - - --tablehead-background: #2a2c2f; - - --blockquote-background: #222325; - --blockquote-foreground: #7e8c92; - - --warning-color: #2e1917; - --warning-color-dark: #ad2617; - --warning-color-darker: #f5b1aa; - --note-color: #3b2e04; - --note-color-dark: #f1b602; - --note-color-darker: #ceb670; - --todo-color: #163750; - --todo-color-dark: #1982D2; - --todo-color-darker: #dcf0fa; - --deprecated-color: #2e323b; - --deprecated-color-dark: #738396; - --deprecated-color-darker: #abb0bd; - --bug-color: #2a2536; - --bug-color-dark: #7661b3; - --bug-color-darker: #ae9ed6; - --invariant-color: #303a35; - --invariant-color-dark: #76ce96; - --invariant-color-darker: #cceed5; - - --fragment-background: #282c34; - --fragment-foreground: #dbe4eb; - --fragment-keyword: #cc99cd; - --fragment-keywordtype: #ab99cd; - --fragment-keywordflow: #e08000; - --fragment-token: #7ec699; - --fragment-comment: #999999; - --fragment-link: #98c0e3; - --fragment-preprocessor: #65cabe; - --fragment-linenumber-color: #cccccc; - --fragment-linenumber-background: #35393c; - --fragment-linenumber-border: #1f1f1f; -} - -body { - color: var(--page-foreground-color); - background-color: var(--page-background-color); - font-size: var(--page-font-size); -} - -body, table, div, p, dl, #nav-tree .label, .title, -.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, -.SelectItem, #MSearchField, .navpath li.navelem a, -.navpath li.navelem a:hover, p.reference, p.definition { - font-family: var(--font-family); -} - -h1, h2, h3, h4, h5 { - margin-top: .9em; - font-weight: 600; - line-height: initial; -} - -p, div, table, dl, p.reference, p.definition { - font-size: var(--page-font-size); -} - -p.reference, p.definition { - color: var(--page-secondary-foreground-color); -} - -a:link, a:visited, a:hover, a:focus, a:active { - color: var(--primary-color) !important; - font-weight: 500; -} - -a.anchor { - scroll-margin-top: var(--spacing-large); - display: block; -} - -/* - Title and top navigation - */ - -#top { - background: var(--header-background); - border-bottom: 1px solid var(--separator-color); -} - -@media screen and (min-width: 768px) { - #top { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-items: center; - } -} - -#main-nav { - flex-grow: 5; - padding: var(--spacing-small) var(--spacing-medium); -} - -#titlearea { - width: auto; - padding: var(--spacing-medium) var(--spacing-large); - background: none; - color: var(--header-foreground); - border-bottom: none; -} - -@media screen and (max-width: 767px) { - #titlearea { - padding-bottom: var(--spacing-small); - } -} - -#titlearea table tbody tr { - height: auto !important; -} - -#projectname { - font-size: var(--title-font-size); - font-weight: 600; -} - -#projectnumber { - font-family: inherit; - font-size: 60%; -} - -#projectbrief { - font-family: inherit; - font-size: 80%; -} - -#projectlogo { - vertical-align: middle; -} - -#projectlogo img { - max-height: calc(var(--title-font-size) * 2); - margin-right: var(--spacing-small); -} - -.sm-dox, .tabs, .tabs2, .tabs3 { - background: none; - padding: 0; -} - -.tabs, .tabs2, .tabs3 { - border-bottom: 1px solid var(--separator-color); - margin-bottom: -1px; -} - -.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { - background: var(--page-secondary-foreground-color); -} - -@media screen and (max-width: 767px) { - .sm-dox a span.sub-arrow { - background: var(--code-background); - } - - #main-menu a.has-submenu span.sub-arrow { - color: var(--page-secondary-foreground-color); - border-radius: var(--border-radius-medium); - } - - #main-menu a.has-submenu:hover span.sub-arrow { - color: var(--page-foreground-color); - } -} - -@media screen and (min-width: 768px) { - .sm-dox li, .tablist li { - display: var(--menu-display); - } - - .sm-dox a span.sub-arrow { - border-color: var(--header-foreground) transparent transparent transparent; - } - - .sm-dox a:hover span.sub-arrow { - border-color: var(--menu-focus-foreground) transparent transparent transparent; - } - - .sm-dox ul a span.sub-arrow { - border-color: transparent transparent transparent var(--page-foreground-color); - } - - .sm-dox ul a:hover span.sub-arrow { - border-color: transparent transparent transparent var(--menu-focus-foreground); - } -} - -.sm-dox ul { - background: var(--page-background-color); - box-shadow: var(--box-shadow); - border: 1px solid var(--separator-color); - border-radius: var(--border-radius-medium) !important; - padding: var(--spacing-small); - animation: ease-out 150ms slideInMenu; -} - -@keyframes slideInMenu { - from { - opacity: 0; - transform: translate(0px, -2px); - } - - to { - opacity: 1; - transform: translate(0px, 0px); - } -} - -.sm-dox ul a { - color: var(--page-foreground-color) !important; - background: var(--page-background-color); - font-size: var(--navigation-font-size); -} - -.sm-dox>li>ul:after { - border-bottom-color: var(--page-background-color) !important; -} - -.sm-dox>li>ul:before { - border-bottom-color: var(--separator-color) !important; -} - -.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { - font-size: var(--navigation-font-size) !important; - color: var(--menu-focus-foreground) !important; - text-shadow: none; - background-color: var(--menu-focus-background); - border-radius: var(--border-radius-small) !important; -} - -.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { - text-shadow: none; - background: transparent; - background-image: none !important; - color: var(--header-foreground) !important; - font-weight: normal; - font-size: var(--navigation-font-size); - border-radius: var(--border-radius-small) !important; -} - -.sm-dox a:focus { - outline: auto; -} - -.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { - text-shadow: none; - font-weight: normal; - background: var(--menu-focus-background); - color: var(--menu-focus-foreground) !important; - border-radius: var(--border-radius-small) !important; - font-size: var(--navigation-font-size); -} - -.tablist li.current { - border-radius: var(--border-radius-small); - background: var(--menu-selected-background); -} - -.tablist li { - margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); -} - -.tablist a { - padding: 0 var(--spacing-large); -} - - -/* - Search box - */ - -#MSearchBox { - height: var(--searchbar-height); - background: var(--searchbar-background); - border-radius: var(--searchbar-border-radius); - border: 1px solid var(--separator-color); - overflow: hidden; - width: var(--searchbar-width); - position: relative; - box-shadow: none; - display: block; - margin-top: 0; -} - -/* until Doxygen 1.9.4 */ -.left img#MSearchSelect { - left: 0; - user-select: none; - padding-left: 8px; -} - -/* Doxygen 1.9.5 */ -.left span#MSearchSelect { - left: 0; - user-select: none; - margin-left: 8px; - padding: 0; -} - -.left #MSearchSelect[src$=".png"] { - padding-left: 0 -} - -.SelectionMark { - user-select: none; -} - -.tabs .left #MSearchSelect { - padding-left: 0; -} - -.tabs #MSearchBox { - position: absolute; - right: var(--spacing-medium); -} - -@media screen and (max-width: 767px) { - .tabs #MSearchBox { - position: relative; - right: 0; - margin-left: var(--spacing-medium); - margin-top: 0; - } -} - -#MSearchSelectWindow, #MSearchResultsWindow { - z-index: 9999; -} - -#MSearchBox.MSearchBoxActive { - border-color: var(--primary-color); - box-shadow: inset 0 0 0 1px var(--primary-color); -} - -#main-menu > li:last-child { - margin-right: 0; -} - -@media screen and (max-width: 767px) { - #main-menu > li:last-child { - height: 50px; - } -} - -#MSearchField { - font-size: var(--navigation-font-size); - height: calc(var(--searchbar-height) - 2px); - background: transparent; - width: calc(var(--searchbar-width) - 64px); -} - -.MSearchBoxActive #MSearchField { - color: var(--searchbar-foreground); -} - -#MSearchSelect { - top: calc(calc(var(--searchbar-height) / 2) - 11px); -} - -#MSearchBox span.left, #MSearchBox span.right { - background: none; - background-image: none; -} - -#MSearchBox span.right { - padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); - position: absolute; - right: var(--spacing-small); -} - -.tabs #MSearchBox span.right { - top: calc(calc(var(--searchbar-height) / 2) - 12px); -} - -@keyframes slideInSearchResults { - from { - opacity: 0; - transform: translate(0, 15px); - } - - to { - opacity: 1; - transform: translate(0, 20px); - } -} - -#MSearchResultsWindow { - left: auto !important; - right: var(--spacing-medium); - border-radius: var(--border-radius-large); - border: 1px solid var(--separator-color); - transform: translate(0, 20px); - box-shadow: var(--box-shadow); - animation: ease-out 280ms slideInSearchResults; - background: var(--page-background-color); -} - -iframe#MSearchResults { - margin: 4px; -} - -iframe { - color-scheme: normal; -} - -@media (prefers-color-scheme: dark) { - html:not(.light-mode) iframe#MSearchResults { - filter: invert() hue-rotate(180deg); - } -} - -html.dark-mode iframe#MSearchResults { - filter: invert() hue-rotate(180deg); -} - -#MSearchResults .SRPage { - background-color: transparent; -} - -#MSearchResults .SRPage .SREntry { - font-size: 10pt; - padding: var(--spacing-small) var(--spacing-medium); -} - -#MSearchSelectWindow { - border: 1px solid var(--separator-color); - border-radius: var(--border-radius-medium); - box-shadow: var(--box-shadow); - background: var(--page-background-color); - padding-top: var(--spacing-small); - padding-bottom: var(--spacing-small); -} - -#MSearchSelectWindow a.SelectItem { - font-size: var(--navigation-font-size); - line-height: var(--content-line-height); - margin: 0 var(--spacing-small); - border-radius: var(--border-radius-small); - color: var(--page-foreground-color) !important; - font-weight: normal; -} - -#MSearchSelectWindow a.SelectItem:hover { - background: var(--menu-focus-background); - color: var(--menu-focus-foreground) !important; -} - -@media screen and (max-width: 767px) { - #MSearchBox { - margin-top: var(--spacing-medium); - margin-bottom: var(--spacing-medium); - width: calc(100vw - 30px); - } - - #main-menu > li:last-child { - float: none !important; - } - - #MSearchField { - width: calc(100vw - 110px); - } - - @keyframes slideInSearchResultsMobile { - from { - opacity: 0; - transform: translate(0, 15px); - } - - to { - opacity: 1; - transform: translate(0, 20px); - } - } - - #MSearchResultsWindow { - left: var(--spacing-medium) !important; - right: var(--spacing-medium); - overflow: auto; - transform: translate(0, 20px); - animation: ease-out 280ms slideInSearchResultsMobile; - width: auto !important; - } - - /* - * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 - */ - label.main-menu-btn ~ #searchBoxPos1 { - top: 3px !important; - right: 6px !important; - left: 45px; - display: flex; - } - - label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { - margin-top: 0; - margin-bottom: 0; - flex-grow: 2; - float: left; - } -} - -/* - Tree view - */ - -#side-nav { - padding: 0 !important; - background: var(--side-nav-background); -} - -@media screen and (max-width: 767px) { - #side-nav { - display: none; - } - - #doc-content { - margin-left: 0 !important; - } -} - -#nav-tree { - background: transparent; -} - -#nav-tree .label { - font-size: var(--navigation-font-size); -} - -#nav-tree .item { - height: var(--tree-item-height); - line-height: var(--tree-item-height); -} - -#nav-sync { - bottom: 12px; - right: 12px; - top: auto !important; - user-select: none; -} - -#nav-tree .selected { - text-shadow: none; - background-image: none; - background-color: transparent; - position: relative; -} - -#nav-tree .selected::after { - content: ""; - position: absolute; - top: 1px; - bottom: 1px; - left: 0; - width: 4px; - border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; - background: var(--primary-color); -} - - -#nav-tree a { - color: var(--side-nav-foreground) !important; - font-weight: normal; -} - -#nav-tree a:focus { - outline-style: auto; -} - -#nav-tree .arrow { - opacity: var(--side-nav-arrow-opacity); -} - -.arrow { - color: inherit; - cursor: pointer; - font-size: 45%; - vertical-align: middle; - margin-right: 2px; - font-family: serif; - height: auto; - text-align: right; -} - -#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { - opacity: var(--side-nav-arrow-hover-opacity); -} - -#nav-tree .selected a { - color: var(--primary-color) !important; - font-weight: bolder; - font-weight: 600; -} - -.ui-resizable-e { - background: var(--separator-color); - width: 1px; -} - -/* - Contents - */ - -div.header { - border-bottom: 1px solid var(--separator-color); - background-color: var(--page-background-color); - background-image: none; -} - -@media screen and (min-width: 1000px) { - #doc-content > div > div.contents, - .PageDoc > div.contents { - display: flex; - flex-direction: row-reverse; - flex-wrap: nowrap; - align-items: flex-start; - } - - div.contents .textblock { - min-width: 200px; - flex-grow: 1; - } -} - -div.contents, div.header .title, div.header .summary { - max-width: var(--content-maxwidth); -} - -div.contents, div.header .title { - line-height: initial; - margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; -} - -div.header .summary { - margin: var(--spacing-medium) auto 0 auto; -} - -div.headertitle { - padding: 0; -} - -div.header .title { - font-weight: 600; - font-size: 225%; - padding: var(--spacing-medium) var(--spacing-large); - word-break: break-word; -} - -div.header .summary { - width: auto; - display: block; - float: none; - padding: 0 var(--spacing-large); -} - -td.memSeparator { - border-color: var(--separator-color); -} - -span.mlabel { - background: var(--primary-color); - border: none; - padding: 4px 9px; - border-radius: 12px; - margin-right: var(--spacing-medium); -} - -span.mlabel:last-of-type { - margin-right: 2px; -} - -div.contents { - padding: 0 var(--spacing-large); -} - -div.contents p, div.contents li { - line-height: var(--content-line-height); -} - -div.contents div.dyncontent { - margin: var(--spacing-medium) 0; -} - -@media (prefers-color-scheme: dark) { - html:not(.light-mode) div.contents div.dyncontent img, - html:not(.light-mode) div.contents center img, - html:not(.light-mode) div.contents > table img, - html:not(.light-mode) div.contents div.dyncontent iframe, - html:not(.light-mode) div.contents center iframe, - html:not(.light-mode) div.contents table iframe { - filter: hue-rotate(180deg) invert(); - } -} - -html.dark-mode div.contents div.dyncontent img, -html.dark-mode div.contents center img, -html.dark-mode div.contents > table img, -html.dark-mode div.contents div.dyncontent iframe, -html.dark-mode div.contents center iframe, -html.dark-mode div.contents table iframe { - filter: hue-rotate(180deg) invert(); -} - -h2.groupheader { - border-bottom: 0px; - color: var(--page-foreground-color); - box-shadow: - 100px 0 var(--page-background-color), - -100px 0 var(--page-background-color), - 100px 0.75px var(--separator-color), - -100px 0.75px var(--separator-color), - 500px 0 var(--page-background-color), - -500px 0 var(--page-background-color), - 500px 0.75px var(--separator-color), - -500px 0.75px var(--separator-color), - 900px 0 var(--page-background-color), - -900px 0 var(--page-background-color), - 900px 0.75px var(--separator-color), - -900px 0.75px var(--separator-color), - 1400px 0 var(--page-background-color), - -1400px 0 var(--page-background-color), - 1400px 0.75px var(--separator-color), - -1400px 0.75px var(--separator-color), - 1900px 0 var(--page-background-color), - -1900px 0 var(--page-background-color), - 1900px 0.75px var(--separator-color), - -1900px 0.75px var(--separator-color); -} - -blockquote { - margin: 0 var(--spacing-medium) 0 var(--spacing-medium); - padding: var(--spacing-small) var(--spacing-large); - background: var(--blockquote-background); - color: var(--blockquote-foreground); - border-left: 0; - overflow: visible; - border-radius: var(--border-radius-medium); - overflow: visible; - position: relative; -} - -blockquote::before, blockquote::after { - font-weight: bold; - font-family: serif; - font-size: 360%; - opacity: .15; - position: absolute; -} - -blockquote::before { - content: "“"; - left: -10px; - top: 4px; -} - -blockquote::after { - content: "”"; - right: -8px; - bottom: -25px; -} - -blockquote p { - margin: var(--spacing-small) 0 var(--spacing-medium) 0; -} -.paramname { - font-weight: 600; - color: var(--primary-dark-color); -} - -.paramname > code { - border: 0; -} - -table.params .paramname { - font-weight: 600; - font-family: var(--font-family-monospace); - font-size: var(--code-font-size); - padding-right: var(--spacing-small); - line-height: var(--table-line-height); -} - -h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { - text-shadow: 0 0 15px var(--primary-light-color); -} - -.alphachar a { - color: var(--page-foreground-color); -} - -/* - Table of Contents - */ - -div.contents .toc { - max-height: var(--toc-max-height); - min-width: var(--toc-width); - border: 0; - border-left: 1px solid var(--separator-color); - border-radius: 0; - background-color: transparent; - box-shadow: none; - position: sticky; - top: var(--toc-sticky-top); - padding: 0 var(--spacing-large); - margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); -} - -div.toc h3 { - color: var(--toc-foreground); - font-size: var(--navigation-font-size); - margin: var(--spacing-large) 0 var(--spacing-medium) 0; -} - -div.toc li { - padding: 0; - background: none; - line-height: var(--toc-font-size); - margin: var(--toc-font-size) 0 0 0; -} - -div.toc li::before { - display: none; -} - -div.toc ul { - margin-top: 0 -} - -div.toc li a { - font-size: var(--toc-font-size); - color: var(--page-foreground-color) !important; - text-decoration: none; -} - -div.toc li a:hover, div.toc li a.active { - color: var(--primary-color) !important; -} - -div.toc li a.aboveActive { - color: var(--page-secondary-foreground-color) !important; -} - - -@media screen and (max-width: 999px) { - div.contents .toc { - max-height: 45vh; - float: none; - width: auto; - margin: 0 0 var(--spacing-medium) 0; - position: relative; - top: 0; - position: relative; - border: 1px solid var(--separator-color); - border-radius: var(--border-radius-medium); - background-color: var(--toc-background); - box-shadow: var(--box-shadow); - } - - div.contents .toc.interactive { - max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); - overflow: hidden; - } - - div.contents .toc > h3 { - -webkit-tap-highlight-color: transparent; - cursor: pointer; - position: sticky; - top: 0; - background-color: var(--toc-background); - margin: 0; - padding: var(--spacing-large) 0; - display: block; - } - - div.contents .toc.interactive > h3::before { - content: ""; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 5px solid var(--primary-color); - display: inline-block; - margin-right: var(--spacing-small); - margin-bottom: calc(var(--navigation-font-size) / 4); - transform: rotate(-90deg); - transition: transform 0.25s ease-out; - } - - div.contents .toc.interactive.open > h3::before { - transform: rotate(0deg); - } - - div.contents .toc.interactive.open { - max-height: 45vh; - overflow: auto; - transition: max-height 0.2s ease-in-out; - } - - div.contents .toc a, div.contents .toc a.active { - color: var(--primary-color) !important; - } - - div.contents .toc a:hover { - text-decoration: underline; - } -} - -/* - Code & Fragments - */ - -code, div.fragment, pre.fragment { - border-radius: var(--border-radius-small); - border: 1px solid var(--separator-color); - overflow: hidden; -} - -code { - display: inline; - background: var(--code-background); - color: var(--code-foreground); - padding: 2px 6px; -} - -div.fragment, pre.fragment { - margin: var(--spacing-medium) 0; - padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); - background: var(--fragment-background); - color: var(--fragment-foreground); - overflow-x: auto; -} - -@media screen and (max-width: 767px) { - div.fragment, pre.fragment { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right: 0; - } - - .contents > div.fragment, - .textblock > div.fragment, - .textblock > pre.fragment, - .contents > .doxygen-awesome-fragment-wrapper > div.fragment, - .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, - .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { - margin: var(--spacing-medium) calc(0px - var(--spacing-large)); - border-radius: 0; - border-left: 0; - } - - .textblock li > .fragment, - .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { - margin: var(--spacing-medium) calc(0px - var(--spacing-large)); - } - - .memdoc li > .fragment, - .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { - margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); - } - - .textblock ul, .memdoc ul { - overflow: initial; - } - - .memdoc > div.fragment, - .memdoc > pre.fragment, - dl dd > div.fragment, - dl dd pre.fragment, - .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, - .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, - dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, - dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { - margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); - border-radius: 0; - border-left: 0; - } -} - -code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { - font-family: var(--font-family-monospace); - font-size: var(--code-font-size) !important; -} - -div.line:after { - margin-right: var(--spacing-medium); -} - -div.fragment .line, pre.fragment { - white-space: pre; - word-wrap: initial; - line-height: var(--fragment-lineheight); -} - -div.fragment span.keyword { - color: var(--fragment-keyword); -} - -div.fragment span.keywordtype { - color: var(--fragment-keywordtype); -} - -div.fragment span.keywordflow { - color: var(--fragment-keywordflow); -} - -div.fragment span.stringliteral { - color: var(--fragment-token) -} - -div.fragment span.comment { - color: var(--fragment-comment); -} - -div.fragment a.code { - color: var(--fragment-link) !important; -} - -div.fragment span.preprocessor { - color: var(--fragment-preprocessor); -} - -div.fragment span.lineno { - display: inline-block; - width: 27px; - border-right: none; - background: var(--fragment-linenumber-background); - color: var(--fragment-linenumber-color); -} - -div.fragment span.lineno a { - background: none; - color: var(--fragment-link) !important; -} - -div.fragment .line:first-child .lineno { - box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); -} - -div.line { - border-radius: var(--border-radius-small); -} - -div.line.glow { - background-color: var(--primary-light-color); - box-shadow: none; -} - -/* - dl warning, attention, note, deprecated, bug, ... - */ - -dl.bug dt a, dl.deprecated dt a, dl.todo dt a { - font-weight: bold !important; -} - -dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.todo, dl.remark { - padding: var(--spacing-medium); - margin: var(--spacing-medium) 0; - color: var(--page-background-color); - overflow: hidden; - margin-left: 0; - border-radius: var(--border-radius-small); -} - -dl.section dd { - margin-bottom: 2px; -} - -dl.warning, dl.attention { - background: var(--warning-color); - border-left: 8px solid var(--warning-color-dark); - color: var(--warning-color-darker); -} - -dl.warning dt, dl.attention dt { - color: var(--warning-color-dark); -} - -dl.note, dl.remark { - background: var(--note-color); - border-left: 8px solid var(--note-color-dark); - color: var(--note-color-darker); -} - -dl.note dt, dl.remark dt { - color: var(--note-color-dark); -} - -dl.todo { - background: var(--todo-color); - border-left: 8px solid var(--todo-color-dark); - color: var(--todo-color-darker); -} - -dl.todo dt { - color: var(--todo-color-dark); -} - -dl.bug dt a { - color: var(--todo-color-dark) !important; -} - -dl.bug { - background: var(--bug-color); - border-left: 8px solid var(--bug-color-dark); - color: var(--bug-color-darker); -} - -dl.bug dt a { - color: var(--bug-color-dark) !important; -} - -dl.deprecated { - background: var(--deprecated-color); - border-left: 8px solid var(--deprecated-color-dark); - color: var(--deprecated-color-darker); -} - -dl.deprecated dt a { - color: var(--deprecated-color-dark) !important; -} - -dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { - margin-inline-start: 0px; -} - -dl.invariant, dl.pre { - background: var(--invariant-color); - border-left: 8px solid var(--invariant-color-dark); - color: var(--invariant-color-darker); -} - -dl.invariant dt, dl.pre dt { - color: var(--invariant-color-dark); -} - -/* - memitem - */ - -div.memdoc, div.memproto, h2.memtitle { - box-shadow: none; - background-image: none; - border: none; -} - -div.memdoc { - padding: 0 var(--spacing-medium); - background: var(--page-background-color); -} - -h2.memtitle, div.memitem { - border: 1px solid var(--separator-color); - box-shadow: var(--box-shadow); -} - -h2.memtitle { - box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); -} - -div.memitem { - transition: none; -} - -div.memproto, h2.memtitle { - background: var(--fragment-background); -} - -h2.memtitle { - font-weight: 500; - font-size: var(--memtitle-font-size); - font-family: var(--font-family-monospace); - border-bottom: none; - border-top-left-radius: var(--border-radius-medium); - border-top-right-radius: var(--border-radius-medium); - word-break: break-all; - position: relative; -} - -h2.memtitle:after { - content: ""; - display: block; - background: var(--fragment-background); - height: var(--spacing-medium); - bottom: calc(0px - var(--spacing-medium)); - left: 0; - right: -14px; - position: absolute; - border-top-right-radius: var(--border-radius-medium); -} - -h2.memtitle > span.permalink { - font-size: inherit; -} - -h2.memtitle > span.permalink > a { - text-decoration: none; - padding-left: 3px; - margin-right: -4px; - user-select: none; - display: inline-block; - margin-top: -6px; -} - -h2.memtitle > span.permalink > a:hover { - color: var(--primary-dark-color) !important; -} - -a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { - border-color: var(--primary-light-color); -} - -div.memitem { - border-top-right-radius: var(--border-radius-medium); - border-bottom-right-radius: var(--border-radius-medium); - border-bottom-left-radius: var(--border-radius-medium); - overflow: hidden; - display: block !important; -} - -div.memdoc { - border-radius: 0; -} - -div.memproto { - border-radius: 0 var(--border-radius-small) 0 0; - overflow: auto; - border-bottom: 1px solid var(--separator-color); - padding: var(--spacing-medium); - margin-bottom: -1px; -} - -div.memtitle { - border-top-right-radius: var(--border-radius-medium); - border-top-left-radius: var(--border-radius-medium); -} - -div.memproto table.memname { - font-family: var(--font-family-monospace); - color: var(--page-foreground-color); - font-size: var(--memname-font-size); - text-shadow: none; -} - -div.memproto div.memtemplate { - font-family: var(--font-family-monospace); - color: var(--primary-dark-color); - font-size: var(--memname-font-size); - margin-left: 2px; - text-shadow: none; -} - -table.mlabels, table.mlabels > tbody { - display: block; -} - -td.mlabels-left { - width: auto; -} - -td.mlabels-right { - margin-top: 3px; - position: sticky; - left: 0; -} - -table.mlabels > tbody > tr:first-child { - display: flex; - justify-content: space-between; - flex-wrap: wrap; -} - -.memname, .memitem span.mlabels { - margin: 0 -} - -/* - reflist - */ - -dl.reflist { - box-shadow: var(--box-shadow); - border-radius: var(--border-radius-medium); - border: 1px solid var(--separator-color); - overflow: hidden; - padding: 0; -} - - -dl.reflist dt, dl.reflist dd { - box-shadow: none; - text-shadow: none; - background-image: none; - border: none; - padding: 12px; -} - - -dl.reflist dt { - font-weight: 500; - border-radius: 0; - background: var(--code-background); - border-bottom: 1px solid var(--separator-color); - color: var(--page-foreground-color) -} - - -dl.reflist dd { - background: none; -} - -/* - Table - */ - -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { - display: inline-block; - max-width: 100%; -} - -.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { - margin-left: calc(0px - var(--spacing-large)); - margin-right: calc(0px - var(--spacing-large)); - max-width: calc(100% + 2 * var(--spacing-large)); -} - -table.fieldtable, -table.markdownTable tbody, -table.doxtable tbody { - border: none; - margin: var(--spacing-medium) 0; - box-shadow: 0 0 0 1px var(--separator-color); - border-radius: var(--border-radius-small); -} - -table.doxtable caption { - display: block; -} - -table.fieldtable { - border-collapse: collapse; - width: 100%; -} - -th.markdownTableHeadLeft, -th.markdownTableHeadRight, -th.markdownTableHeadCenter, -th.markdownTableHeadNone, -table.doxtable th { - background: var(--tablehead-background); - color: var(--tablehead-foreground); - font-weight: 600; - font-size: var(--page-font-size); -} - -th.markdownTableHeadLeft:first-child, -th.markdownTableHeadRight:first-child, -th.markdownTableHeadCenter:first-child, -th.markdownTableHeadNone:first-child, -table.doxtable tr th:first-child { - border-top-left-radius: var(--border-radius-small); -} - -th.markdownTableHeadLeft:last-child, -th.markdownTableHeadRight:last-child, -th.markdownTableHeadCenter:last-child, -th.markdownTableHeadNone:last-child, -table.doxtable tr th:last-child { - border-top-right-radius: var(--border-radius-small); -} - -table.markdownTable td, -table.markdownTable th, -table.fieldtable td, -table.fieldtable th, -table.doxtable td, -table.doxtable th { - border: 1px solid var(--separator-color); - padding: var(--spacing-small) var(--spacing-medium); -} - -table.markdownTable td:last-child, -table.markdownTable th:last-child, -table.fieldtable td:last-child, -table.fieldtable th:last-child, -table.doxtable td:last-child, -table.doxtable th:last-child { - border-right: none; -} - -table.markdownTable td:first-child, -table.markdownTable th:first-child, -table.fieldtable td:first-child, -table.fieldtable th:first-child, -table.doxtable td:first-child, -table.doxtable th:first-child { - border-left: none; -} - -table.markdownTable tr:first-child td, -table.markdownTable tr:first-child th, -table.fieldtable tr:first-child td, -table.fieldtable tr:first-child th, -table.doxtable tr:first-child td, -table.doxtable tr:first-child th { - border-top: none; -} - -table.markdownTable tr:last-child td, -table.markdownTable tr:last-child th, -table.fieldtable tr:last-child td, -table.fieldtable tr:last-child th, -table.doxtable tr:last-child td, -table.doxtable tr:last-child th { - border-bottom: none; -} - -table.markdownTable tr, table.doxtable tr { - border-bottom: 1px solid var(--separator-color); -} - -table.markdownTable tr:last-child, table.doxtable tr:last-child { - border-bottom: none; -} - -table.fieldtable th { - font-size: var(--page-font-size); - font-weight: 600; - background-image: none; - background-color: var(--tablehead-background); - color: var(--tablehead-foreground); -} - -table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fielddoc, .fieldtable th { - border-bottom: 1px solid var(--separator-color); - border-right: 1px solid var(--separator-color); -} - -table.fieldtable tr:last-child td:first-child { - border-bottom-left-radius: var(--border-radius-small); -} - -table.fieldtable tr:last-child td:last-child { - border-bottom-right-radius: var(--border-radius-small); -} - -.memberdecls td.glow, .fieldtable tr.glow { - background-color: var(--primary-light-color); - box-shadow: none; -} - -table.memberdecls { - display: block; - -webkit-tap-highlight-color: transparent; -} - -table.memberdecls tr[class^='memitem'] { - font-family: var(--font-family-monospace); - font-size: var(--code-font-size); -} - -table.memberdecls tr[class^='memitem'] .memTemplParams { - font-family: var(--font-family-monospace); - font-size: var(--code-font-size); - color: var(--primary-dark-color); - white-space: normal; -} - -table.memberdecls .memItemLeft, -table.memberdecls .memItemRight, -table.memberdecls .memTemplItemLeft, -table.memberdecls .memTemplItemRight, -table.memberdecls .memTemplParams { - transition: none; - padding-top: var(--spacing-small); - padding-bottom: var(--spacing-small); - border-top: 1px solid var(--separator-color); - border-bottom: 1px solid var(--separator-color); - background-color: var(--fragment-background); -} - -table.memberdecls .memTemplItemLeft, -table.memberdecls .memTemplItemRight { - padding-top: 2px; -} - -table.memberdecls .memTemplParams { - border-bottom: 0; - border-left: 1px solid var(--separator-color); - border-right: 1px solid var(--separator-color); - border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; - padding-bottom: var(--spacing-small); -} - -table.memberdecls .memTemplItemLeft { - border-radius: 0 0 0 var(--border-radius-small); - border-left: 1px solid var(--separator-color); - border-top: 0; -} - -table.memberdecls .memTemplItemRight { - border-radius: 0 0 var(--border-radius-small) 0; - border-right: 1px solid var(--separator-color); - padding-left: 0; - border-top: 0; -} - -table.memberdecls .memItemLeft { - border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); - border-left: 1px solid var(--separator-color); - padding-left: var(--spacing-medium); - padding-right: 0; -} - -table.memberdecls .memItemRight { - border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; - border-right: 1px solid var(--separator-color); - padding-right: var(--spacing-medium); - padding-left: 0; - -} - -table.memberdecls .mdescLeft, table.memberdecls .mdescRight { - background: none; - color: var(--page-foreground-color); - padding: var(--spacing-small) 0; -} - -table.memberdecls .memItemLeft, -table.memberdecls .memTemplItemLeft { - padding-right: var(--spacing-medium); -} - -table.memberdecls .memSeparator { - background: var(--page-background-color); - height: var(--spacing-large); - border: 0; - transition: none; -} - -table.memberdecls .groupheader { - margin-bottom: var(--spacing-large); -} - -table.memberdecls .inherit_header td { - padding: 0 0 var(--spacing-medium) 0; - text-indent: -12px; - color: var(--page-secondary-foreground-color); -} - -table.memberdecls img[src="closed.png"], -table.memberdecls img[src="open.png"], -div.dynheader img[src="open.png"], -div.dynheader img[src="closed.png"] { - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 5px solid var(--primary-color); - margin-top: 8px; - display: block; - float: left; - margin-left: -10px; - transition: transform 0.25s ease-out; -} - -table.memberdecls img { - margin-right: 10px; -} - -table.memberdecls img[src="closed.png"], -div.dynheader img[src="closed.png"] { - transform: rotate(-90deg); - -} - -.compoundTemplParams { - font-family: var(--font-family-monospace); - color: var(--primary-dark-color); - font-size: var(--code-font-size); -} - -@media screen and (max-width: 767px) { - - table.memberdecls .memItemLeft, - table.memberdecls .memItemRight, - table.memberdecls .mdescLeft, - table.memberdecls .mdescRight, - table.memberdecls .memTemplItemLeft, - table.memberdecls .memTemplItemRight, - table.memberdecls .memTemplParams { - display: block; - text-align: left; - padding-left: var(--spacing-large); - margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); - border-right: none; - border-left: none; - border-radius: 0; - white-space: normal; - } - - table.memberdecls .memItemLeft, - table.memberdecls .mdescLeft, - table.memberdecls .memTemplItemLeft { - border-bottom: 0; - padding-bottom: 0; - } - - table.memberdecls .memTemplItemLeft { - padding-top: 0; - } - - table.memberdecls .mdescLeft { - margin-bottom: calc(0px - var(--page-font-size)); - } - - table.memberdecls .memItemRight, - table.memberdecls .mdescRight, - table.memberdecls .memTemplItemRight { - border-top: 0; - padding-top: 0; - padding-right: var(--spacing-large); - overflow-x: auto; - } - - table.memberdecls tr[class^='memitem']:not(.inherit) { - display: block; - width: calc(100vw - 2 * var(--spacing-large)); - } - - table.memberdecls .mdescRight { - color: var(--page-foreground-color); - } - - table.memberdecls tr.inherit { - visibility: hidden; - } - - table.memberdecls tr[style="display: table-row;"] { - display: block !important; - visibility: visible; - width: calc(100vw - 2 * var(--spacing-large)); - animation: fade .5s; - } - - @keyframes fade { - 0% { - opacity: 0; - max-height: 0; - } - - 100% { - opacity: 1; - max-height: 200px; - } - } -} - - -/* - Horizontal Rule - */ - -hr { - margin-top: var(--spacing-large); - margin-bottom: var(--spacing-large); - height: 1px; - background-color: var(--separator-color); - border: 0; -} - -.contents hr { - box-shadow: 100px 0 0 var(--separator-color), - -100px 0 0 var(--separator-color), - 500px 0 0 var(--separator-color), - -500px 0 0 var(--separator-color), - 1500px 0 0 var(--separator-color), - -1500px 0 0 var(--separator-color), - 2000px 0 0 var(--separator-color), - -2000px 0 0 var(--separator-color); -} - -.contents img, .contents .center, .contents center, .contents div.image object { - max-width: 100%; - overflow: auto; -} - -@media screen and (max-width: 767px) { - .contents .dyncontent > .center, .contents > center { - margin-left: calc(0px - var(--spacing-large)); - margin-right: calc(0px - var(--spacing-large)); - max-width: calc(100% + 2 * var(--spacing-large)); - } -} - -/* - Directories - */ -div.directory { - border-top: 1px solid var(--separator-color); - border-bottom: 1px solid var(--separator-color); - width: auto; -} - -table.directory { - font-family: var(--font-family); - font-size: var(--page-font-size); - font-weight: normal; - width: 100%; -} - -table.directory td.entry, table.directory td.desc { - padding: calc(var(--spacing-small) / 2) var(--spacing-small); - line-height: var(--table-line-height); -} - -table.directory tr.even td:last-child { - border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; -} - -table.directory tr.even td:first-child { - border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); -} - -table.directory tr.even:last-child td:last-child { - border-radius: 0 var(--border-radius-small) 0 0; -} - -table.directory tr.even:last-child td:first-child { - border-radius: var(--border-radius-small) 0 0 0; -} - -table.directory td.desc { - min-width: 250px; -} - -table.directory tr.even { - background-color: var(--odd-color); -} - -table.directory tr.odd { - background-color: transparent; -} - -.icona { - width: auto; - height: auto; - margin: 0 var(--spacing-small); -} - -.icon { - background: var(--primary-color); - border-radius: var(--border-radius-small); - font-size: var(--page-font-size); - padding: calc(var(--page-font-size) / 5); - line-height: var(--page-font-size); - transform: scale(0.8); - height: auto; - width: var(--page-font-size); - user-select: none; -} - -.iconfopen, .icondoc, .iconfclosed { - background-position: center; - margin-bottom: 0; - height: var(--table-line-height); -} - -.icondoc { - filter: saturate(0.2); -} - -@media screen and (max-width: 767px) { - div.directory { - margin-left: calc(0px - var(--spacing-large)); - margin-right: calc(0px - var(--spacing-large)); - } -} - -@media (prefers-color-scheme: dark) { - html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { - filter: hue-rotate(180deg) invert(); - } -} - -html.dark-mode .iconfopen, html.dark-mode .iconfclosed { - filter: hue-rotate(180deg) invert(); -} - -/* - Class list - */ - -.classindex dl.odd { - background: var(--odd-color); - border-radius: var(--border-radius-small); -} - -.classindex dl.even { - background-color: transparent; -} - -/* - Class Index Doxygen 1.8 -*/ - -table.classindex { - margin-left: 0; - margin-right: 0; - width: 100%; -} - -table.classindex table div.ah { - background-image: none; - background-color: initial; - border-color: var(--separator-color); - color: var(--page-foreground-color); - box-shadow: var(--box-shadow); - border-radius: var(--border-radius-large); - padding: var(--spacing-small); -} - -div.qindex { - background-color: var(--odd-color); - border-radius: var(--border-radius-small); - border: 1px solid var(--separator-color); - padding: var(--spacing-small) 0; -} - -/* - Footer and nav-path - */ - -#nav-path { - width: 100%; -} - -#nav-path ul { - background-image: none; - background: var(--page-background-color); - border: none; - border-top: 1px solid var(--separator-color); - border-bottom: 1px solid var(--separator-color); - border-bottom: 0; - box-shadow: 0 0.75px 0 var(--separator-color); - font-size: var(--navigation-font-size); -} - -img.footer { - width: 60px; -} - -.navpath li.footer { - color: var(--page-secondary-foreground-color); -} - -address.footer { - color: var(--page-secondary-foreground-color); - margin-bottom: var(--spacing-large); -} - -#nav-path li.navelem { - background-image: none; - display: flex; - align-items: center; -} - -.navpath li.navelem a { - text-shadow: none; - display: inline-block; - color: var(--primary-color) !important; -} - -.navpath li.navelem b { - color: var(--primary-dark-color); - font-weight: 500; -} - -li.navelem { - padding: 0; - margin-left: -8px; -} - -li.navelem:first-child { - margin-left: var(--spacing-large); -} - -li.navelem:first-child:before { - display: none; -} - -#nav-path li.navelem:after { - content: ''; - border: 5px solid var(--page-background-color); - border-bottom-color: transparent; - border-right-color: transparent; - border-top-color: transparent; - transform: translateY(-1px) scaleY(4.2); - z-index: 10; - margin-left: 6px; -} - -#nav-path li.navelem:before { - content: ''; - border: 5px solid var(--separator-color); - border-bottom-color: transparent; - border-right-color: transparent; - border-top-color: transparent; - transform: translateY(-1px) scaleY(3.2); - margin-right: var(--spacing-small); -} - -.navpath li.navelem a:hover { - color: var(--primary-color); -} - -/* - Scrollbars for Webkit -*/ - -#nav-tree::-webkit-scrollbar, -div.fragment::-webkit-scrollbar, -pre.fragment::-webkit-scrollbar, -div.memproto::-webkit-scrollbar, -.contents center::-webkit-scrollbar, -.contents .center::-webkit-scrollbar, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, -div.contents .toc::-webkit-scrollbar { - background: transparent; - width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); - height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); -} - -#nav-tree::-webkit-scrollbar-thumb, -div.fragment::-webkit-scrollbar-thumb, -pre.fragment::-webkit-scrollbar-thumb, -div.memproto::-webkit-scrollbar-thumb, -.contents center::-webkit-scrollbar-thumb, -.contents .center::-webkit-scrollbar-thumb, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, -div.contents .toc::-webkit-scrollbar-thumb { - background-color: transparent; - border: var(--webkit-scrollbar-padding) solid transparent; - border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); - background-clip: padding-box; -} - -#nav-tree:hover::-webkit-scrollbar-thumb, -div.fragment:hover::-webkit-scrollbar-thumb, -pre.fragment:hover::-webkit-scrollbar-thumb, -div.memproto:hover::-webkit-scrollbar-thumb, -.contents center:hover::-webkit-scrollbar-thumb, -.contents .center:hover::-webkit-scrollbar-thumb, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, -div.contents .toc:hover::-webkit-scrollbar-thumb { - background-color: var(--webkit-scrollbar-color); -} - -#nav-tree::-webkit-scrollbar-track, -div.fragment::-webkit-scrollbar-track, -pre.fragment::-webkit-scrollbar-track, -div.memproto::-webkit-scrollbar-track, -.contents center::-webkit-scrollbar-track, -.contents .center::-webkit-scrollbar-track, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, -div.contents .toc::-webkit-scrollbar-track { - background: transparent; -} - -#nav-tree::-webkit-scrollbar-corner { - background-color: var(--side-nav-background); -} - -#nav-tree, -div.fragment, -pre.fragment, -div.memproto, -.contents center, -.contents .center, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, -div.contents .toc { - overflow-x: auto; - overflow-x: overlay; -} - -#nav-tree { - overflow-x: auto; - overflow-y: auto; - overflow-y: overlay; -} - -/* - Scrollbars for Firefox -*/ - -#nav-tree, -div.fragment, -pre.fragment, -div.memproto, -.contents center, -.contents .center, -.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, -div.contents .toc { - scrollbar-width: thin; -} - -/* - Optional Dark mode toggle button -*/ - -doxygen-awesome-dark-mode-toggle { - display: inline-block; - margin: 0 0 0 var(--spacing-small); - padding: 0; - width: var(--searchbar-height); - height: var(--searchbar-height); - background: none; - border: none; - border-radius: var(--searchbar-height); - vertical-align: middle; - text-align: center; - line-height: var(--searchbar-height); - font-size: 22px; - display: flex; - align-items: center; - justify-content: center; - user-select: none; - cursor: pointer; -} - -doxygen-awesome-dark-mode-toggle > svg { - transition: transform .1s ease-in-out; -} - -doxygen-awesome-dark-mode-toggle:active > svg { - transform: scale(.5); -} - -doxygen-awesome-dark-mode-toggle:hover { - background-color: rgba(0,0,0,.03); -} - -html.dark-mode doxygen-awesome-dark-mode-toggle:hover { - background-color: rgba(0,0,0,.18); -} - -/* - Optional fragment copy button -*/ -.doxygen-awesome-fragment-wrapper { - position: relative; -} - -doxygen-awesome-fragment-copy-button { - opacity: 0; - background: var(--fragment-background); - width: 28px; - height: 28px; - position: absolute; - right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); - top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); - border: 1px solid var(--fragment-foreground); - cursor: pointer; - border-radius: var(--border-radius-small); - display: flex; - justify-content: center; - align-items: center; -} - -.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { - opacity: .28; -} - -doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { - opacity: 1 !important; -} - -doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { - transform: scale(.91); -} - -doxygen-awesome-fragment-copy-button svg { - fill: var(--fragment-foreground); - width: 18px; - height: 18px; -} - -doxygen-awesome-fragment-copy-button.success svg { - fill: rgb(14, 168, 14); -} - -doxygen-awesome-fragment-copy-button.success { - border-color: rgb(14, 168, 14); -} - -@media screen and (max-width: 767px) { - .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, - .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, - .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, - .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, - dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { - right: 0; - } -} - -/* - Optional paragraph link button -*/ - -a.anchorlink { - font-size: 90%; - margin-left: var(--spacing-small); - color: var(--page-foreground-color) !important; - text-decoration: none; - opacity: .15; - display: none; - transition: opacity .1s ease-in-out, color .1s ease-in-out; -} - -a.anchorlink svg { - fill: var(--page-foreground-color); -} - -h3 a.anchorlink svg, h4 a.anchorlink svg { - margin-bottom: -3px; - margin-top: -4px; -} - -a.anchorlink:hover { - opacity: .45; -} - -h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { - display: inline-block; -} diff --git a/docs/doxygentheme/header.html b/docs/doxygentheme/header.html deleted file mode 100644 index cda3d32..0000000 --- a/docs/doxygentheme/header.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - $projectname: $title - - - $title - - - - - - - - - - - - $treeview - $search - $mathjax - - $extrastylesheet - - - - - - - - - - - - -
- - - -
- - - - - - - - - - - - - - - - - - - - - -
-
$projectname -  $projectnumber - -
- -
$projectbrief
- -
-
$projectbrief
-
$searchbox
-
- - \ No newline at end of file diff --git a/docs/doxygentheme/logo.drawio.svg b/docs/doxygentheme/logo.drawio.svg deleted file mode 100644 index a506ee0..0000000 --- a/docs/doxygentheme/logo.drawio.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/doxygentheme/toggle-alternative-theme.js b/docs/doxygentheme/toggle-alternative-theme.js deleted file mode 100644 index 72c3731..0000000 --- a/docs/doxygentheme/toggle-alternative-theme.js +++ /dev/null @@ -1,12 +0,0 @@ - -let original_theme_active = true; - -function toggle_alternative_theme() { - if(original_theme_active) { - document.documentElement.classList.add("alternative") - original_theme_active = false; - } else { - document.documentElement.classList.remove("alternative") - original_theme_active = true; - } -} \ No newline at end of file diff --git a/docs/dsysinfo.zh_CN.dox b/docs/dsysinfo.zh_CN.dox deleted file mode 100644 index 07912a6..0000000 --- a/docs/dsysinfo.zh_CN.dox +++ /dev/null @@ -1,221 +0,0 @@ -/*! -@~chinese -@file includes/global/dsysinfo.h - -dsysinfo.h是一组用于查询系统信息的静态类 - -@enum Dtk::Core::DSysInfo::ProductType dsysinfo.h -@brief 产品信息 -| 值 | 序号 | 含义 | -|-------------|----|-------| -| UnknownType | 0 | 未知类型 | -| deepin | 1 | 深度社区版 | -| ArchLinux | 2 | | -| CentOS | 3 | | -| Debian | 4 | | -| Fedora | 5 | | -| LinuxMint | 6 | | -| Manjaro | 7 | | -| openSUSE | 8 | | -| SailfishOS | 9 | | -| Ubuntu | 10 | | -| Uos | 11 | | -| Gentoo | 12 | | -| NixOS | 13 | | - - -@enum Dtk::Core::DSysInfo::DeepinType dsysinfo.h -@brief 深度操作系统版本 -| 值 | 序号 | 含义 | -|--------------------|----|-----------------------| -| UnknownDeepin | 0 | 未知版本 | -| DeepinDesktop | 1 | deepin桌面发行版 | -| DeepinProfessional | 2 | deepin专业版,现为uos专业版 | -| DeepinServer | 3 | deepin服务器版本,现为uos服务器版 | -| DeepinPersonal | 4 | deepin个人版,现为uos家庭版 | - -@enum Dtk::Core::DSysInfo::LogoType -@brief 系统的logo类型 -| 值 | 序号 | 含义 | -|--------------|----|----| -| Normal | 0 | 正常 | -| Light | 1 | 亮色 | -| Symbolic | 2 | 符号 | -| Transparent | 3 | 水印 | - -@enum Dtk::Core::DSysInfo::OrgType -@brief -| 值 | 序号 | 含义 | -|--------------|----|--------------| -| Distribution | 0 | 当前版本 | -| Distributor | 1 | 当前发行版 | -| Manufacturer | 2 | 当前发行版或设备的制造商 | - -@enum Dtk::Core::DSysInfo::UosType -@brief UOS版本类型 -| 值 | 序号 | 含义 | -|-----------------|----|-------------| -| UosTypeUnknown | 0 | 未知版本 | -| UosDesktop | 1 | UOS桌面版 | -| UosServer | 2 | UOS服务器版 | -| UosDevice | 3 | UOS设备版 | -| UosTypeCount | 4 | 记录枚举数量 | - -@enum Dtk::Core::DSysInfo::UosEdition -@brief 详细uos版本 -| 值 | 序号 | 含义 | -|-------------------|----|---------------------| -| UosEditionUnknown | 0 | 未知发行版 | -| UosProfessional | 1 | UOS专业版 | -| UosHome | 2 | UOS家庭版 | -| UosCommunity | 3 | 社区版 | -| UosMilitary | 4 | * | -| UosEnterprise | 5 | UOS企业版 | -| UosEnterpriseC | 6 | UOS行业版 | -| UosEuler | 7 | UOS服务器欧拉版 | -| UosMilitaryS | 8 | * | -| UosDeviceEdition | 9 | UOS专用设备版 | -| UosEducation | 10 | UOS教育版 | -| UosEditionCount | 11 | 记录枚举数量 | - -@enum Dtk::Core::DSysInfo::UosArch -@brief UOS使用的架构 -| 值 | 序号 | 含义 | -|----------------|----|--------| -| UosArchUnknown | 0 | 未知架构 | -| UosAMD64 | 1 | x86_64 | -| UosARM64 | 2 | arm64 | -| UosMIPS64 | 4 | mips64 | -| UosSW64 | 8 | sw_64 | - - - - -@fn static bool Dtk::Core::DSysInfo::isDeepin() //FIXME: 显示错乱 无法修复 -@brief 是否为deepin系统 -@return 0 不是deepin系统 -@return 1 是deepin系统 - -@fn static bool Dtk::Core::DSysInfo::isDDE() -@brief 是否使用dde桌面环境 -@note 此方法仅在linux平台下可用 - -@fn static DeepinType Dtk::Core::DSysInfo::deepinType() -@brief deepin系统类型 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::deepinTypeDisplayName (const QLocale &locale=QLocale::system()) -@brief 显示的deepin发行版类型名称 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::deepinVersion() -@brief deepin版本 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::deepinCopyright() -@brief deepin 开源许可协议 -@note 此方法仅在linux平台下可用 - -@fn static UosEdition Dtk::Core::DSysInfo::uosEditionType() -@brief DSysInfo::osEditionType 版本类型 显示版本类型 专业版/个人版/社区版.. -@note 根据 osBuild.B && osBuild.D -@note 此方法仅在linux平台下可用 - -@fn static UosArch Dtk::Core::DSysInfo::uosArch() -@brief DSysInfo::osArch 架构信息(使用一个字节的二进制位,从低位到高位) 【0x8 sw64】【0x4 mips64】【0x2 arm64】【0x1 amd64】 -@note 此处架构是从OsBuild获取的系统版本的Arch信息,并不是指硬件的Arch信息 -@note 此方法仅在linux平台下可用 - -@fn static QString uosProductTypeName(const QLocale &locale=QLocale::system()) -@brief DSysInfo::osProductTypeName 版本名称 ProductType[xx] 项对应的值, 如果找不到对应语言的默认使用 ProductType的值(Desktop/Server/Device) locale 当前系统语言 - -@fn static QString Dtk::Core::DSysInfo::uosSystemName(const QLocale &locale=QLocale::system()) -@brief SystemName[xx] 项对应的值, 如果找不到对应语言的默认使用 SystemName 的值 Uniontech OS locale 当前系统语言 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::function uosEditionName(const QLocale &locale=QLocale::system()) -@brief 版本名称 EditionName[xx] 项对应的值, 如果找不到对应语言的默认使用 EditionName 的值(Professional/Home/Community...) locale 当前系统语言 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::spVersion() -@brief 阶段版本名称 小版本号 A-BC-D 中 BC、 A.B.C 中的 B 返回 SP1-SPxx, 如果正式版返回空 X.Y.Z模式下暂不支持返回此版本号 -@note minVersion.BC == 00 正式版本, minVersion.BC | minVersion.B == 01-99 SP1….SP99 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::udpateVersion() -@brief 更新版本名称 小版本号 A-BC-D 中 D、A.B.C 模式中的 C 返回 update1… update9, 如果正式版返回空 X.Y.Z模式下暂不支持返回此版本号 -@note minVersion.D == 0;正式版本 minVersion.D | minVersion.C == 1-9;update1… update9,updateA...updateZ -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::majorVersion() -@brief 主版本号 主版本号 【20】【23】【25】【26】【29】【30】 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::minorVersion() -@brief 小版本号 【ABCD】 ·[0-9]{4} 【A.B.C】 或者【X.Y.Z】 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::buildVersion() -@brief 小版本号 系统镜像批次号,按时间顺序(不可回退)从100-999递增 -@note 此方法仅在linux平台下可用 - -@fn static QString Dtk::Core::DSysInfo::distributionInfoPath () -@brie 返回distribution文件地址 一般在`/usr/share/deepin/`目录下 - -@fn static QString Dtk::Core::DSysInfo::distributionInfoSectionName(OrgType type) -@brief 返回distribution.info 文件中SectionName字段的值 - -@fn static Dtk::Core::DSysInfo::distributionOrgName(OrgType type=Distribution, const QLocale &locale=QLocale::system()) -@brief 返回组织名称。使用类型为Distribution来获取当前deepin distribution本身的名称 - -@fn static QPairDtk::Core::DSysInfo::distributionOrgWebsite(OrgType type=Distribution) -@brief 发行版组织的网站名称和网址。使用 type 作为 Distribution 获取当前 deepin 发行版本身的名称。 - -@fn static QString Dtk::Core::DSysInfo::distributionOrgLogo(OrgType orgType=Distribution, LogoType type=Normal, const QString &fallback=QString()) -@brief 获得的组织logo路径,如果不存在,则返回给定的其他路径。 使用 type 作为 Distribution 获取当前 deepin 发行版本身的logo。 - -@fn static QString Dtk::Core::DSysInfo::operatingSystemName() -@brief 操作系统名 - -@fn static ProductType Dtk::Core::DSysInfo::productType() -@brief 产品类型 - -@fn static QString Dtk::Core::DSysInfo::productVersion() -@brief 产品版本 - -@fn static bool Dtk::Core::DSysInfo::isCommunityEdition() -@brief 检查当前版本是否是社区版 开发者可以使用这种方式来检查我们是否需要启用或禁用社区版或企业版的功能。 -目前的规则: - 专业版、服务器版、个人版(DeepinType)将被视为企业版。 - Uos(ProductType)将被视为企业版。 - -@fn static QString Dtk::Core::DSysInfo::computerName() -@brief 电脑名 - -@fn static QString Dtk::Core::DSysInfo::cpuModelName() -@brief cpu模式名 - -@fn static qint64 Dtk::Core::DSysInfo::memoryInstalledSize() -@brief 内存安装大小 - -@fn static qint64 Dtk::Core::DSysInfo::memoryTotalSize() -@brief 实际内存大小 - -@fn static qint64 Dtk::Core::DSysInfo::systemDiskSize() -@brief 系统磁盘大小 - -@fn static QDateTime Dtk::Core::DSysInfo::bootTime () -@brief 系统启动时间点 - -@fn static QDateTime Dtk::Core::DSysInfo::shutdownTime () -@brief 上一次正常关机时间点(重启也会被记录在内) - -@fn static qint64 Dtk::Core::DSysInfo::uptime() -@brief 系统启动到现在时长 -@note 参见`cat /proc/uptime`命令 - -@fn static Arch Dtk::Core::DSysInfo::arch -@brief cpu架构信息 -@note 此处架构是从gcc编译器获取的 - -*/ \ No newline at end of file diff --git a/docs/filesystem/dbasefilewatcher.zh_CN.dox b/docs/filesystem/dbasefilewatcher.zh_CN.dox new file mode 100644 index 0000000..06ed32b --- /dev/null +++ b/docs/filesystem/dbasefilewatcher.zh_CN.dox @@ -0,0 +1,68 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dbasefilewatcher.h + +@class Dtk::Core::DBaseFileWatcher +@brief DBaseFileWatcher 类提供了一系列接口可供监视文件和目录的变动。 +@note 建议使用 DFileWatcher 类,该类是 DBaseFileWatcher 的子类,提供了更多的功能。或者使用DFileWatcherManager类,该类提供了对文件和目录的监视功能。 +@warning 该类是一个虚类,不应该被直接使用,而应该使用 DFileWatcher 类或者 DFileWatcherManager 类。 + +@fn QUrl Dtk::Core::DBaseFileWatcher::fileUrl() +@brief 返回文件的统一资源定位符 +@sa [QUrl](https://doc.qt.io/qt-5/qurl.html) + +@fn bool Dtk::Core::DBaseFileWatcher::startWatcher() +@brief 开始监视文件变动 +@return true 成功 false 失败 +@sa DBaseFileWatcher::stopWatcher + +@fn bool Dtk::Core::DBaseFileWatcher::stopWatcher() +@brief 停止监视文件变动 +@return true 成功 false 失败 +@sa DBaseFileWatcher::startWatcher() + +@fn bool Dtk::Core::DBaseFileWatcher::restartWatcher() +@brief 重启监视文件变动 +@return true 成功 false 失败 +@sa DBaseFileWatcher::startWatcher() + +@fn virtual void Dtk::Core::DBaseFileWatcher::setEnabledSubfileWatcher(const QUrl &subfileUrl, bool enabled = true) +@brief 设置是否对`subfileUrl`目录启用文件监视 +@param[in] subfileUrl 设置所针对的 Url +@param[in] enabled 是否启用文件变动监视 + +@fn static bool Dtk::Core::DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, SignalType1 signal, const QUrl &arg1) +@brief 发送一个信号表示目标目录`targetUrl`得到了一个`signal`信号,包含参数`arg1`
+使用方式如下: +@code + DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileDeleted, QUrl("bookmark:///bookmarkFile1")); +@endcode +@return 成功发送返回 true,否则返回 false + +@fn static bool Dtk::Core::DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::SignalType2 signal, const QUrl &arg1, const QUrl &arg2) +@brief 发送一个信号表示目标目录`targetUrl`得到了一个`signal`信号,包含参数`arg1`和`arg2`
+@details 示例用法: +@code + DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileMoved, QUrl("bookmark:///bookmarkFile1"), QUrl("bookmark:///NewNameFile1")); +@endcode + +@var Dtk::Core::DBaseFileWatcher::fileDeleted(const QUrl &url) +@brief 文件被删除的信号 + +@var Dtk::Core::DBaseFileWatcher::fileMoved(const QUrl &fromUrl, const QUrl &toUrl) +@brief 文件被移动的信号 + +@var Dtk::Core::DBaseFileWatcher::fileAttributeChanged(const QUrl &url) +@brief 文件属性被改变的信号 + +@var Dtk::Core::DBaseFileWatcher::subfileCreated(const QUrl &url) +@brief 子文件被创建的信号 + +@var Dtk::Core::DBaseFileWatcher::fileClosed(const QUrl &url) +@brief 文件被关闭的信号 + +@var Dtk::Core::DBaseFileWatcher::fileModified(const QUrl &url) +@brief 文件被修改的信号 + +*/ diff --git a/docs/filesystem/dcapfile.zh_CN.dox b/docs/filesystem/dcapfile.zh_CN.dox new file mode 100644 index 0000000..8431335 --- /dev/null +++ b/docs/filesystem/dcapfile.zh_CN.dox @@ -0,0 +1,192 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dcapfile.h + +@class Dtk::Core::DCapFile +@brief 对于文件操作的安全封装, 提供了带有安全管控的文件读取, 相关漏洞见[CWE_22](https://cwe.mitre.org/data/definitions/22.html) + +@fn explicit Dtk::Core::DCapFile(QObject *parent = nullptr) +@brief 默认构造函数, 创建一个文件默认文件对象 + +@fn Dtk::Core::DCapFile::DCapFile(const QString &name, QObject *parent) +@brief 重载的构造函数, 接受传入一个文件名, 并创建一个文件对象 +@note 调用此构造函数相当于调用默认构造函数+`DCapFile::setFileName()` + +@fn void Dtk::Core::DCapFile::setFileName(const QString &name) +@brief 传入需要操作的文件名 + +@fn bool Dtk::Core::DCapFile::exists() const +@brief 文件是否存在 +@note 此处的存在指当前由setFileName() 指定的文件或者是在构造时指定的文件是否可读可写 +@note 需要在构造时或者手动指定了文件名才可以使用此函数, 否则请调用其重载的函数 + +@fn static bool Dtk::Core::DCapFile::exists(const QString &fileName) +@brief 文件是否存在 +@param[in] fileName 文件名 +@note 此处的存在指的是此函数的传入的文件名指向的文件是否可读可写 + +@fn QString Dtk::Core::DCapFile::readLink() const +@brief 读取软连接, 如果软连接指向的文件不允许读写, 则返回空字符串 +@note 此方法在Qt版本>=5.13后**废弃** +@return 返回软连接指向的文件或者目录的绝对路径 +@note 需要在构造时或者手动指定了文件名才可以使用此函数, 否则请调用其重载的函数 +@sa [readLink](https://doc.qt.io/qt-5/qfile-obsolete.html#readLink-1) + +@fn QString Dtk::Core::DCapFile::symLinkTarget() const +@brief 这是一个重载函数
+ 返回符号链接, 或Windows上的快捷方式指向的文件或目录的绝对路径, 如果该对象不是符号链接, 则返回一个空字符串。 + +@fn bool Dtk::Core::DCapFile::remove() +@brief 如果文件存在则删除文件 +@note 此处的存在指当前由setFileName() 指定的文件或者是在构造时指定的文件是否可读可写 +@note 需要在构造时或者手动指定了文件名才可以使用此函数, 否则请调用其重载的函数 +@note 文件需要在删除前被关闭 + +@fn static bool Dtk::Core::DCapFile::remove(const QString &fileName) +@brief 如果文件存在则删除文件 +@param[in] fileName 文件名 +@note 此处的存在指的是此函数的传入的文件名指向的文件是否可读可写 +@note 文件需要在删除前被关闭 +@sa DCapFile::remove() + +@fn bool Dtk::Core::DCapFile::moveToTrash() +@brief 如果文件存在则将文件移动至默认回收站(垃圾桶) +@note 此处的存在指当前由setFileName() 指定的文件或者是在构造时指定的文件是否可读可写 +@note 需要在构造时或者手动指定了文件名才可以使用此函数, 否则请调用其重载的函数 +@note 此方法仅在Qt版本>=5.15.0后可用 + +@fn bool Dtk::Core::DCapFile::moveToTrash(const QString &fileName, QString *pathInTrash) +@brief 如果传入文件名对应文件存在则将文件移动至指定回收站(垃圾桶) +@note 此处的存在指的是此函数的传入的文件名指向的文件是否可读可写 +@note 此方法仅在Qt版本>=5.15.0后可用 +@param[in] fileName 文件名 +@param[in] pathInTrash 回收站路径 + +@fn bool Dtk::Core::DCapFile::rename(const QString &newName) +@brief 如果文件名存在则重命名文件 +@param[in] newName 新文件名 +@note 需要在构造时或者手动指定了文件名才可以使用此函数, 否则请调用其重载的函数 + +@fn static bool Dtk::Core::DCapFile::rename(const QString &oldName, const QString &newName) +@brief 如果文件名存在则重命名文件 +@param[in] oldName 旧文件名 +@param[in] newName 新文件名 + +@fn bool Dtk::Core::DCapFile::link(const QString &newName) +@brief 创建一个名为newName的链接 +@details 该链接指向当前由`setFileName()`指定的文件或者是在构造时指定的文件。链接是什么取决于底层文件系统(无论是Windows上的快捷方式还是Unix上的符号链接)。如果成功, 则返回ture;否则返回false +@note 如果是windows系统的newName参数必须有`.lnk`合法后缀才可用 +@param[in] newName 新文件名 + +@fn static bool Dtk::Core::DCapFile::link(const QString &oldname, const QString &newName) +@brief 该函数是重载`DCapFile::link()`区别是需要手动传入原始文件名 +@sa DCapFile::link(const QString &newName) + +@fn bool Dtk::Core::DCapFile::copy(const QString &newName) +@brief `setFileName()`指定的文件或者是在构造时指定的文件复制一份, 名为newName
+ 如果成功, 则返回ture;否则返回false +@note 确保文件在复制之前是关闭的 +@note 如果复制的文件是一个符号链接(symlink), 它所指的文件被复制, 而不是链接本身。除了权限 + 会被复制外, 其他的文件元数据都不会被复制。 +@note 如果一个名称为 newName 的文件已经存在, `copy()`将会返回true但是并不会覆盖它 + +@fn static bool Dtk::Core::DCapFile::copy(const QString &fileName, const QString &newName) +@brief 该函数是重载`DCapFile::copy(const QString &newName)`区别是需要手动传入原始文件名 +@sa DCapFile::copy(const QString &newName) + +@fn bool Dtk::Core::DCapFile::open(OpenMode flags) +@brief 使用OpenMode模式打开文件, 如果成功返回true;否则返回false
+@details 模式如下:
+ NotOpen = 0x0000,
+ ReadOnly = 0x0001,
+ WriteOnly = 0x0002,
+ ReadWrite = ReadOnly | WriteOnly,
+ Append = 0x0004,
+ Truncate = 0x0008,
+ Text = 0x0010,
+ Unbuffered = 0x0020,
+ NewOnly = 0x0040,
+ ExistingOnly = 0x0080
+@note 在只写或读写模式下, 如果相关文件不存在, 该函数将在打开文件之前尝试创建一个新文件 + +@fn bool Dtk::Core::DCapFile::resize(qint64 sz) +@brief 设置文件大小sz(以字节为单位)。如果调整大小成功, 则返回true;否则为false。如果sz大于当前文件, 则新字节将设置为 0;如果sz较小, 则文件将被简单地截断 +@note 如果文件不存在, 此函数可能会无效 + +@fn static bool Dtk::Core::DCapFile::resize(const QString &filename, qint64 sz) +@brief 该函数是重载`DCapFile::resize(qint64 sz)`区别是手动指定文件名 +@sa DCapFile::resize(qint64 sz) + +*/ + +/*! +@class Dtk::Core::DCapFile +@brief 对于文件夹操作的封装 + +@fn Dtk::Core::DCapDir::DCapDir(const DCapDir &) +@brief 拷贝构造函数 构造一个DCapDir对象, 该对象是目录目录的DCapDir对象的副本 + +@fn Dtk::Core::DCapDir::DCapDir(const QString &path = QString()) +@brief 构造指向给定目录路径的DCapDir。如果 path 为空, 则使用程序的工作目录`.` + +@fn Dtk::Core::DCapDir::DCapDir(const QString &path, + const QString &nameFilter, SortFlags sort = SortFlags(Name | IgnoreCase), + Filters filter = AllEntries) +@brief 构造具有路径路径的DCapDir对象 +@details 该 DCapDir 使用nameFilter按名称筛选其条目, 并使用筛选器 按属性筛选其条目。它还使用排序对名称进行排序。
+ 默认名称筛选器是一个空字符串, 它不排除任何内容;默认筛选器是“所有条目”, 这也意味着不排除任何内容。默认排序为“名称|忽略大小写, 即按名称排序, 不区分大小写。 + 如果path为空字符串, DCapDir 将使用 “.”(当前目录)
+ 如果nameFilter为空字符串, DCapDir 将使用名称筛选器“*”(所有文件) +@note 路径不需要存在 + +@fn void Dtk::Core::DCapDir::setPath(const QString &path) +@brief 将目录的路径设置为path。该路径被清除了多余的"."、"... "和多个分隔符。没有检查这个路径的 + 目录是否真的存在;
+ 路径可以是绝对路径也可以是相对路径, 绝对路径以目录分隔符"/"开始(在Windows下可以选择在前面加一个驱动器号, 例如: C:\)
+ 相对路径以目录名开始, 并指定一个相对于当前目录的路径。一个绝对路径的例子是字符串"/etc/apt", 一个相对路径例子是 "src/1/"
+ +@fn bool Dtk::Core::DCapDir::cd(const QString &dirName) +@brief 将DCapDir的目录更改为dirName。 + 如果新目录存在, 则返回true;否则返回false + 请注意, 如果新目录不存在, 则不执行逻辑`cd()`操作 + +@fn QStringList Dtk::Core::DCapDir::entryList(Filters filters = NoFilter, SortFlags sort = NoSort) const +@brief 返回目录中所有文件和目录的名称列表 +@details 这些名称根据以前使用`setNameFilters()` 和`setFilter()` + 设置的名称和属性筛选器排序, 并根据使用`setSorting() 设置的标志进行排序。
+ 可以使用过滤器和排序参数覆盖属性过滤器和排序规范。 + 如果目录不可读、不存在或与规范不匹配, 则返回空列表。 + +@fn QString Dtk::Core::DCapDir::entryList(const QStringList &nameFilters, Filters filters = NoFilter, + SortFlags sort = NoSort) +@brief 重载函数, 返回目录中所有文件和目录的名称列表 +@sa entryList(Filters filters = NoFilter, SortFlags sort = NoSort) + +@fn bool Dtk::Core::DCapDir::mkdir(const QString &dirName) const +@brief 创建文件夹 + +@fn bool Dtk::Core::DCapDir::rmdir(const QString &dirName) const +@brief 移除文件夹 + +@fn bool Dtk::Core::DCapDir::mkpath(const QString &dirPath) +@brief 创建目录 + +@fn bool Dtk::Core::DCapDir::rmpath(const QString &dirPath) +@brief 移除目录 + +@fn bool Dtk::Core::DCapDir::exists() const +@brief 文件夹是否存在(如果找到同名文件, 此函数将返回 false) + +@fn bool Dtk::Core::DCapDir::exists(const QString &name) const +@brief 指定文件夹是否存在(如果找到同名文件, 此函数将返回 false) + +@fn bool Dtk::Core::DCapDir::remove(const QString &fileName) +@brief 移除文件夹 + +@fn bool Dtk::Core::DCapDir::rename(const QString &oldName, const QString &newName) +@brief 重命名文件夹 +@param[in] oldName 旧文件夹名 +@param[in] newName 新文件夹名 + +*/ diff --git a/docs/filesystem/dfilesystemwatcher.zh_CN.dox b/docs/filesystem/dfilesystemwatcher.zh_CN.dox new file mode 100644 index 0000000..b04c21c --- /dev/null +++ b/docs/filesystem/dfilesystemwatcher.zh_CN.dox @@ -0,0 +1,73 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dfilesystemwatcher.h + +@class DFileSystemWatcher +@brief 监听文件系统变化的类 +@details + DFileSystemWatcher监视文件系统对文件的更改和目录,通过观察指定的path列表。
+ 调用addPath()来监视特定的文件或目录。多个path可以使用addPaths()函数添加。现有path可以使用removePath()和removePaths()函数删除。
+ DFileSystemWatcher检查添加到其中的每个path。具有以下特性的文件添加到DFileSystemWatcher可以使用函数Files()和使用函数directories()创建的目录。
+ fileChanged()信号在文件被修改时发出,重命名或从磁盘中删除。类似地,directoryChanged()在目录或其内容被修改或移除。
+ 请注意,DFileSystemWatcher只停止监视一次文件,它们被重命名或从磁盘和目录中删除一次,它们已从磁盘中移除。 +@note 在运行不支持inotify的Linux内核的系统上,包含被监视路径的文件系统不能被卸载。
+ 默认情况下,Windows CE不支持目录监控,这取决于安装的文件系统驱动程序。
+ 监视文件和目录的行为修改操作会消耗系统资源。这意味着有一个限制进程可以使用的文件和目录的数量同时监控。 + +@fn DFileSystemWatcher::DFileSystemWatcher(QObject *parent) +@brief 构造函数,构造一个新的文件系统监视器对象。 + +@fn DFileSystemWatcher::DFileSystemWatcher(const QStringList &paths, QObject *parent = Q_NULLPTR) +@brief 构造函数,构造一个新的文件系统监视器对象,监控指定路径列表。 +@param paths 要监听的路径列表 + +@fn bool DFileSystemWatcher::addPath(const QString &file) +@brief 添加要监听的路径 +@details 如果path存在,则将path添加到文件系统监视器。如果path不存在或已经存在,则不添加它由文件系统监视程序监视。
+ 如果path指定了一个目录,则调用directoryChanged()信号将在path被修改或从磁盘中删除时发出。否则,当path被修改、重命名或删除。,就会触发fileChanged()信号
+ 如果监视成功,则返回true。
+ 监视故障的原因通常与系统有关,但是可能包括资源不存在、访问失败或总监视数量限制,如果平台有一个。 +@note 可能有一个系统依赖的数量限制可以同时监控的文件和目录。
+ 如果达到了这个限制,path将不会被监控,返回false。 +@param[in] file 要监听的路径 +@sa DFileSystemWatcher::addPaths() +@sa DFileSystemWatcher::removePath() + +@fn QStringList DFileSystemWatcher::addPaths(const QStringList &files) +@brief 添加要监听的路径列表 +@details 将path中的每个path添加到文件系统监视程序。path如果不存在,或者已经存在,则不添加由文件系统监视程序监视。
+ 如果path指定了一个目录,则调用directoryChanged()信号将在path被修改或从磁盘中删除时触发。否则,当path被修改、重命名或删除。,就会触发fileChanged()信号
+ 返回值是一个无法被监视的路径列表。
+ 监视故障的原因通常与系统有关,但是可能包括资源不存在、访问失败或总监视数量限制,如果平台有一个。
+@note 可能有一个系统依赖的数量限制可以同时监控的文件和目录。
+ 如果达到了这个限制,多余的path就不会达到,它们将被添加到返回的QStringList中。 +@param[in] files 要监听的路径列表 +@sa DFileSystemWatcher::addPath() +@sa DFileSystemWatcher::removePaths() + +@fn bool DFileSystemWatcher::removePath(const QString &file) +@brief 移除监听的路径 +@details 从文件系统监视程序中删除指定的path。
+ 如果监视成功删除,则返回true。
+ 监视删除失败的原因通常与系统有关,但可能是因为path已经被删除了。 +@sa DFileSystemWatcher::removePaths() +@sa DFileSystemWatcher::addPath() + +@fn QStringList DFileSystemWatcher::removePaths(const QStringList &files) +@brief 移除监听的路径列表 +@details 从文件系统监视程序中删除指定的path。
+ 返回值是一个无法被监视的路径列表。
+ 监视删除失败的原因通常与系统有关,但可能是因为path已经被删除了。 +@sa DFileSystemWatcher::removePath() +@sa DFileSystemWatcher::addPaths() + +@fn QStringList DFileSystemWatcher::directories() const +@brief 获取监听的目录列表 +@sa DFileSystemWatcher::files() + +@fn QStringList DFileSystemWatcher::files() const +@brief 获取监听的文件列表 +@sa DFileSystemWatcher::directories() + +*/ diff --git a/docs/filesystem/dfilewarcher.zh_CN.dox b/docs/filesystem/dfilewarcher.zh_CN.dox new file mode 100644 index 0000000..6ff1852 --- /dev/null +++ b/docs/filesystem/dfilewarcher.zh_CN.dox @@ -0,0 +1,44 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dfilewatcher.h +@class DFileWatcher +@brief DFileWatcher 类提供了对 DBaseFileWatcher 接口的实现,可供监视文件和目录的变动 + +@fn DFileWatcher::DFileWatcher(const QString &filepath, QObject *parent = 0) +@brief 构造函数 +@param filepath 要监视的文件或目录的路径 +@param parent 父对象 + +@fn void DFileWatcher::onFileDeleted(const QString &path, const QString &name) +@brief 当文件被删除时触发的信号 +@param[in] path 文件所在的目录路径 +@param[in] name 文件名 + +@fn void DFileWatcher::onFileAttributeChanged(const QString &path, const QString &name) +@brief 当文件属性发生变化时触发的信号 +@param[in] path 文件所在的目录路径 +@param[in] name 文件名 + +@fn void DFileWatcher::onFileMoved(const QString &fromPath, const QString &fromName, const QString &toPath, const QString &toName) +@brief 当文件被移动时触发的信号 +@param[in] fromPath 文件原来所在的目录路径 +@param[in] fromName 文件原来的文件名 +@param[in] toPath 文件现在所在的目录路径 +@param[in] toName 文件现在的文件名 + +@fn void DFileWatcher::onFileModified(const QString &path, const QString &name) +@brief 当文件被修改时触发的信号 +@param[in] path 文件所在的目录路径 +@param[in] name 文件名 + +@fn void DFileWatcher::onFileCreated(const QString &path, const QString &name) +@brief 当文件被创建时触发的信号 +@param[in] path 文件所在的目录路径 +@param[in] name 文件名 + +@fn void DFileWatcher::onFileClosed(const QString &path, const QString &name) +@brief 当文件被关闭时触发的信号 +@param[in] path 文件所在的目录路径 + +*/ diff --git a/docs/filesystem/dfilewatchermanager.zh_CN.dox b/docs/filesystem/dfilewatchermanager.zh_CN.dox new file mode 100644 index 0000000..d2a04fe --- /dev/null +++ b/docs/filesystem/dfilewatchermanager.zh_CN.dox @@ -0,0 +1,92 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dfilewatchermanager.h + +@class DFileWatcherManager +@brief DFileWatcherManager 类可以帮助管理一系列 DFileWatcher 文件监视器,并在文件变动时发送信号通知. +@details +示例代码: +```cpp + +#include "dfilewatchermanager" +#include +#include +#include +#include +DCORE_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + DFileWatcherManager manager; + QTemporaryFile tmpfile1; // 创建临时文件1 + tmpfile1.open(); + QFile file1( tmpfile1.fileName()); + QTemporaryFile tmpfile2; // 创建临时文件2 + tmpfile2.open(); + QFile file2( tmpfile2.fileName()); + + manager.add(tmpfile1.fileName());// 监控临时文件1 + manager.add(tmpfile2.fileName());// 监控临时文件2 + + QObject::connect(&manager, &Dtk::Core::DFileWatcherManager::fileModified, &app, [=](const QString value) { + qDebug() << "文件发生变动:" << value; + }); // 文件发生变动时打印文件路径 + + QObject::connect(&manager, &Dtk::Core::DFileWatcherManager::fileDeleted, &app, [=](const QString value) { + qDebug() << "文件被删除:" << value; + }); + + + file1.open(QIODevice::WriteOnly|QIODevice::Text);// 修改临时文件1 + file1.write("test"); + file1.close(); + + file2.open(QIODevice::WriteOnly|QIODevice::Text);// 修改临时文件2 + file2.write("test"); + file2.close(); + + qDebug() << manager.watchedFiles();// 打印所有被监控的文件路径 + qDebug() << "---------------------------"; + app.processEvents();// 处理事件 + manager.removeAll();// 移除所有的监控 + qDebug() << manager.watchedFiles();// 打印所有被监控的文件路径 + return app.exec(); +} +``` +上面代码演示了如何使用 DFileWatcherManager 类来监控文件变动和清除文件变动的监控. +具体可以参照源码中的example文件夹中的文件变动监控例子. + +@fn DFileWatcher* DFileWatcherManager::add(const QString &filePath) +@brief 为路径`filePath`创建 DFileWatcher 并将其添加到 DFileWatcherManager 中. +@return 被创建并添加到 DFileWatcherManager 的 DFileWatcher + +@fn void DFileWatcherManager::remove(const QString &filePath) +@brief 从 DFileWatcherManager 中移除路径`filePath`对应的 DFileWatcher. + +@fn void DFileWatcherManager::removeAll() +@brief 从 DFileWatcherManager 中移除所有的 DFileWatcher. + +@fn void DFileWatcherManager::watchedFiles() +@brief 获取 DFileWatcherManager 中所有的 DFileWatcher. + +@var void DFileWatcherManager::fileDeleted(const QString &filePath) +@brief 当路径`filePath`对应的文件被删除时发送此信号. + +@var void DFileWatcherManager::fileAttributeChanged(const QString &filePath) +@brief 当路径`filePath`对应的文件属性发生变化时发送此信号. + +@var void DFileWatcherManager::fileMoved(const QString &fromFilePath, const QString &toFilePath) +@brief 当路径`fromFilePath`对应的文件被移动到路径`toFilePath`时发送此信号. + +@var void DFileWatcherManager::fileClosed(const QString &filePath) +@brief 当路径`filePath`对应的文件被关闭时发送此信号. + +@var void DFileWatcherManager::fileModified(const QString &filePath) +@brief 当路径`filePath`对应的文件被修改时发送此信号. + +@var void DFileWatcherManager::subfileCreated(const QString &filePath) +@brief 当路径`filePath`对应的文件夹中有新的子文件被创建时发送此信号. + +*/ diff --git a/docs/filesystem/dstandardpaths.zh_CN.dox b/docs/filesystem/dstandardpaths.zh_CN.dox new file mode 100644 index 0000000..b504389 --- /dev/null +++ b/docs/filesystem/dstandardpaths.zh_CN.dox @@ -0,0 +1,47 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dstandardpaths.h + +@class DStandardPaths +@brief DStandardPaths 类描述了一些标准的文件路径,包括XDG文件路径,locate等 + +@fn static QString DStandardPaths::writableLocation(QStandardPaths::StandardLocation type) +@brief DStandardPaths提供兼容Snap/Dtk标准的路径模式。DStandardPaths实现了Qt的QStandardPaths主要接口。此处返回可写路径 + +@fn static QStringList DStandardPaths::standardLocations (QStandardPaths::StandardLocation type) +@brief DStandardPaths提供兼容Snap/Dtk标准的路径模式。DStandardPaths实现了Qt的QStandardPaths主要接口。此处返回所有Standardpath + +@fn static QString DStandardPaths::locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile) +@brief 在 type 的标准位置查找名为 fileName 的文件或目录。选项标志允许您指定是否查找文件或目录。默认情况下,此标志设置为 LocateFile。返回找到的第一个文件或目录的绝对路径,否则返回空字符串。 + +@fn static QStringList DStandardPaths::locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile) +@brief 在类型的标准位置中按名称 fileName 查找所有文件或目录。选项标志允许您指定是否查找文件或目录。默认情况下,此标志设置为 LocateFile。返回找到的所有文件的列表。 + +@fn static QString DStandardPaths::findExecutable(const QString &executableName, const QStringList &paths = QStringList()) +@brief 同QStandardPaths::findExecutable, 查找可执行文件 + +@fn static void DStandardPaths::setMode(DStandardPaths::Mode mode) +@brief 同QStandardPaths::setTestModeEnabled, 设置是否是测试模式 + +@fn static QString DStandardPaths::homePath() +@brief 返回家目录 + +@fn static QString DStandardPaths::homePath(const uint uid) +@brief 用uid返回家目录 + +@fn static QString DStandardPaths::path(DStandardPaths::XDG type) +@brief 返回对应的xdg目录 + +@fn static QString DStandardPaths::path(DStandardPaths::DSG type) +@brief 返回对应Dsg目录 + +@fn static QStringList DStandardPaths::paths(DStandardPaths::DSG type) +@brief 返回所有DSG下所有目录 + +@fn static QString DStandardPaths::filePath(DStandardPaths::XDG type, QString fileName) +@brief 用xdg和文件名称拼接,返回文件绝对路径 + +@fn static QString DStandardPaths::filePath(DStandardPaths::DSG type, QString fileName) +@brief 用dsg和文件名称拼接,返回文件绝对路径 +*/ diff --git a/docs/filesystem/dtrashmanager.zh_CN.dox b/docs/filesystem/dtrashmanager.zh_CN.dox new file mode 100644 index 0000000..27bfd50 --- /dev/null +++ b/docs/filesystem/dtrashmanager.zh_CN.dox @@ -0,0 +1,21 @@ +/*! +@~chinese +@ingroup dfilesystem +@file include/filesystem/dtrashmanager.h +@class DTrashManager +@brief dtk垃圾管理器提供管理文件回收站的功能。 +@details 非常简单的一个类 + +@fn ststic DTrashManager *DTrashManager::instance() +@brief 获取DTrashManager的实例 + +@fn bool DTrashManager::trashIsEmpty() const +@brief 判断回收站是否为空 + +@fn bool DTrashManager::cleanTrash() +@brief 清空回收站 + +@fn bool DTrashManager::moveToTrash(const QString &filePath, bool followSymlink = false) +@brief 将文件移动到回收站 + +*/ diff --git a/docs/filesystem/index.zh_CN.md b/docs/filesystem/index.zh_CN.md new file mode 100644 index 0000000..82f6918 --- /dev/null +++ b/docs/filesystem/index.zh_CN.md @@ -0,0 +1,8 @@ +@page dfilesystem dfilesystem--dtk文件系统操作的封装 + + +# Dlog:dtk日志组件 + +TODO:添加filesystem组件使用说明 +@defgroup dfilesystem +@brief dtk文件系统操作的封装 diff --git a/docs/global/dconfig.zh_CN.dox b/docs/global/dconfig.zh_CN.dox new file mode 100644 index 0000000..853d3d0 --- /dev/null +++ b/docs/global/dconfig.zh_CN.dox @@ -0,0 +1,388 @@ +/*! +@~chinese +@file include/global/dconfig.h +@ingroup dglobal +@class Dtk::Core::DConfigBackend dconfig.h +@brief 配置后端的抽象接口。 +@details 所有DConfig使用的配置后端都继承此类,用户可以继承此类实现自己的配置后端。 + +@sa FileBackend +@sa DBusBackend +@sa QSettingBackend + +@fn Dtk::Core::DConfigBackend::~DConfigBackend() +@brief DConfigBackend析构函数 +@sa FileBackend::~FileBackend() +@sa DBusBackend::~DBusBackend() +@sa QSettingBackend::~QSettingBackend() + +@fn bool Dtk::Core::DConfigBackend::isValid() const = 0 +@brief 判断此后端是否可用 +@sa DConfig::isValid() +@sa FileBackend::isValid() +@sa DBusBackend::isValid() +@sa QSettingBackend::isValid() + +@fn bool Dtk::Core::DConfigBackend::load(const QString &) = 0 +@brief 初始化后端 +@details appId 管理的配置信息key值,默认为应用程序名称。 +@sa FileBackend::load() +@sa DBusBackend::load() +@sa QSettingBackend::load() + +@fn QStringList Dtk::Core::DConfigBackend::keyList() = 0 +@brief 获得所有可用的配置项名称 +@sa DConfig::keyList() +@sa FileBackend::keyList() +@sa DBusBackend::keyList() +@sa QSettingBackend::keyList() + +@fn QVariant Dtk::Core::DConfigBackend::value(const QString &key, const QVariant &fallback = QVariant()) const = 0 +@brief 根据配置项名称获得对应值 +@param[in] key 配置项名称 +@param[in] fallback 没有获取到配置项值后提供的默认值 +@sa DConfig::value() +@sa FileBackend::value() +@sa DBusBackend::value() +@sa QSettingBackend::value() + +@fn void Dtk::Core::DConfigBackend::setValue(const QString &key, const QVariant &value) = 0 +@brief 根据配置项名称设置其值 +@param[in] key 配置项名称 +@param[in] value 需要更新的值 +@sa DConfig::setValue() +@sa FileBackend::setValue() +@sa DBusBackend::setValue() +@sa QSettingBackend::setValue() + +@fn void Dtk::Core::DConfigBackend::reset(const QString &key) +@brief 设置其配置项对应的默认值,此值为经过override机制覆盖后的值,不一定为此配置文件中meta中定义的值。 +@param[in] key 配置项名称 +@sa DConfig::reset() +@sa FileBackend::reset() +@sa DBusBackend::reset() +@sa QSettingBackend::reset() + +@fn QString Dtk::Core::DConfigBackend::name() const = 0 +@brief 后端配置的唯一标识 +@sa FileBackend::name() +@sa DBusBackend::name() +@sa QSettingBackend::name() + +@fn bool Dtk::Core::DConfigBackend::isDefaultValue(const QString &key) +@brief 检测指定配置项名称对应的值是否为默认值。 +@param[in] key 配置项名称 +@sa DConfig::isDefaultValue() +@sa FileBackend::isDefaultValue() +@sa DBusBackend::isDefaultValue() +@sa QSettingBackend::isDefaultValue() + +@class Dtk::Core::QSettingBackend dconfig.h +@brief QSetting后端,继承自DConfigBackend抽象接口,并实现了虚函数。 +@sa DConfigBackend + +@fn QSettingBackend Dtk::Core::QSettingBackend::QSettingBackend(DConfigPrivate* o) +@brief QSettingBackend构造函数 + +@class Dtk::Core::DConfigPrivate dconfig.h +@brief DConfig的私有实现 + +@fn DConfigPrivate Dtk::Core::DConfigPrivate::DConfigPrivate() +@brief DConfigPrivate构造函数 + +@fn bool Dtk::Core::DConfigPrivate::invalid() +@brief 判断此后端是否可用 + +@fn DConfigBackend* Dtk::Core::DConfigPrivate::getOrCreateBackend() +@brief 创建一个配置后端 +@details 默认使用的配置后端会优先根据环境变量来选择配置中心的D-Bus接口还是文件配置后端接口。若没有配置此环境变量,则根据是否有配置中心提供D-Bus服务来选择配置中心服务还是文件配置后端接口。 + +@fn DConfigBackend* Dtk::Core::DConfigPrivate::createBackendByEnv() +@brief 创建一个配置后端 +@details 尝试根据环境变量来选择配置中心的D-Bus接口还是文件配置后端接口。 + +@var QString Dtk::Core::DConfigPrivate::appId +@brief 配置文件所属的应用Id,为空时默认为本应用Id。 + +@var QString Dtk::Core::DConfigPrivate::name +@brief 配置文件名 + +@var QString Dtk::Core::DConfigPrivate::subpath +@brief 配置文件对应的子目录 + +@var QScopedPointer Dtk::Core::DConfigPrivate::backend +@brief 配置策略后端 + +@class Dtk::Core::DConfig dconfig.h +@brief 配置策略提供的接口类 +@details +## 概述 + +此接口规范定义了开发库所提供的关于配置文件读写的相关接口,如果应用程序所使用的开发库实现了此规范,则程序应当优先使用开发库提供的接口。 + +项目目录结构如下: +```bash +├── CMakeLists.txt +├── config +│ └── example.json +└── main.cpp +``` + +## CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.1.0) # 指定cmake最低版本 + +project(dconfig-example VERSION 1.0.0 LANGUAGES CXX) # 指定项目名称, 版本, 语言 cxx就是c++ + +set(CMAKE_CXX_STANDARD 11) # 指定c++标准 +set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定c++标准要求,至少为11以上 + +set(CMAKE_AUTOMOC ON) # 支持qt moc +set(CMAKE_AUTORCC ON) # support qt resource file # 支持qt资源文件 + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 支持 clangd + +if (CMAKE_VERSION VERSION_LESS "3.7.0") # 如果cmake版本小于3.7.0 + set(CMAKE_INCLUDE_CURRENT_DIR ON) # 设置包含当前目录 +endif() + +find_package(Qt5 REQUIRED COMPONENTS Core) # 寻找Qt5组件Core +find_package(Dtk REQUIRED COMPONENTS Core) # 寻找Dtk组件Core + +add_executable(${PROJECT_NAME} # 生成可执行文件 + main.cpp +) + +target_link_libraries(${PROJECT_NAME} PRIVATE # 添加需要链接的共享库 + Qt5::Core + dtkcore +) + +# dtk_add_config_meta_files函数,部署一些"meta"的配置。 +# 函数定义在dtkcore的cmake目录下 +# APPID 应用的ID +# FILES 需要部署的文件。 +dtk_add_config_meta_files( + APPID ${PROJECT_NAME} + FILES ./config/example.json +) +``` + +## example.json +```json +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "canExit": { + "value": true, + "serial": 0, + "flags": ["global"], + "name": "I am name", + "name[zh_CN]": "我是名字", + "description": "I am description", + "permissions": "readwrite", + "visibility": "private" + }, + "key1": { + "value": "125", + "serial": 0, + "flags": ["nooverride"], + "name": "I am name", + "name[zh_CN]": "我是名字", + "description": "I am description", + "permissions": "readwrite", + "visibility": "public" + }, + "number": { + "value": 1, + "serial": 0, + "flags": ["global"], + "name": "array value type", + "permissions": "readwrite", + "visibility": "public" + }, + "array": { + "value": ["value1", "value2"], + "serial": 0, + "flags": ["global"], + "name": "array", + "permissions": "readwrite", + "visibility": "public" + }, + "map": { + "value": {"key1": "value1", "key2": "value2"}, + "serial": 0, + "flags": ["global"], + "name": "map", + "permissions": "readwrite", + "visibility": "public" + } + } +} +``` + +## main.cpp +```cpp +#include +#include +#include + +DCORE_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + // 构造DConfig,元数据文件名example,与元数据安装目录的/usr/share/dsg/configs/APPID名(可执行文件名)对应目录/example.json, + DConfig config("example"); + + // 判断是否有效 + if (!config.isValid()) { + qWarning() << QString("DConfig无效, name:[%1]."). + arg(config.name()); + return 0; + } + + // 获取所有配置项的key + qDebug() << "所有的所有配置项的key:" << config.keyList(); + + // 获取指定配置项的值,配置项可以是字符串,数组,map容器,布尔值,整型,详见example.json + qDebug() << "canExit对应的值:" << config.value("canExit").toBool(); + + QVariantMap map; + for (int i = 0; i < 1; i++) { + QVariantMap nestItem; + for (int j = 0; j < 1; j++) { + nestItem[QString::number(j)] = QString::number(j); + } + map[QString::number(i)] = nestItem; + } + + QScopedPointer heapConfig; + heapConfig.reset(new DConfig("example")); + + if (!heapConfig->isValid()) { + qWarning() << QString("DConfig无效, name:[%1]."). + arg(heapConfig->name()); + return 0; + } + + // 监听值改变的信号 + const bool &oldValue = heapConfig->value("canExit").toBool(); + QObject::connect(heapConfig.get(), &DConfig::valueChanged, [oldValue,&heapConfig](const QString &key){ + qDebug() << "canExit原来的值:" << oldValue << ", canExit新的值:" << heapConfig->value(key).toBool(); + }); + + // 重置canExit的值 + heapConfig->setValue("canExit", !oldValue); + + return a.exec(); +} +``` + +## 从源码构建 +```bash +mkdir build && cd build +# 修改路径前缀为/usr,GNU标准的默认值为/usr/local +cmake .. -DCMAKE_INSTALL_PREFIX=/usr +make +sudo make install +``` +结果如下图 + +![example](/docs/src/dconfig_example1.png) + +@fn DConfig Dtk::Core::DConfig(const QString &name, const QString &subpath, QObject *parent) +@brief 构造配置策略提供的对象 +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 + +@fn DConfig Dtk::Core::DConfig(DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent) +@brief 使用自定义的配置策略后端构造对象 +@param[in] backend 调用者继承于DConfigBackend的配置策略后端 +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 + +@fn static DConfig* Dtk::Core::DConfig::create(const QString &appId, const QString &name, const QString &subpath, QObject *parent) +@brief 构造配置策略提供的对象,指定配置所属的应用Id,管理某一特定应用的配置。 +@param[in] appId 配置文件所属的应用Id,为空时默认为本应用Id +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 +@return 构造的配置策略对象,由调用者释放 + +@fn static DConfig* Dtk::Core::DConfig::create(DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent) +@brief 构造配置策略提供的对象,指定配置所属的应用Id。 +@param[in] backend 调用者继承于DConfigBackend的配置策略后端 +@param[in] appId 配置文件所属的应用Id,为空时默认为本应用Id +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 +@return 构造的配置策略对象,由调用者释放 + +@fn static DConfig* Dtk::Core::DConfig::createGeneric(const QString &name, const QString &subpath, QObject *parent) +@brief 构造配置策略提供的对象,用来管理与应用无关的配置。 +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 +@return 构造的配置策略对象,由调用者释放 +@note 如果我们管理针对某一特定应用的配置,应该使用 Dtk::Core::DConfig::create(),或 Dtk::Core::DConfig(),来指定所属应用的appId。 + +@fn static DConfig* Dtk::Core::DConfig::createGeneric(DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent) +@sa Dtk::Core::DConfig::createGeneric() + +@fn DConfig Dtk::Core::DConfig(DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent) +@brief 使用自定义的配置策略后端构造对象 +@param[in] backend 调用者继承于DConfigBackend的配置策略后端 +@param[in] appId 配置文件所属的应用Id,为空时默认为本应用Id +@param[in] name 配置文件名 +@param[in] subpath 配置文件对应的子目录 +@param[in] parent 父对象 +@note 调用者只构造backend,由DConfig释放。 + +@fn static void DConfig::setAppId(const QString &appId) +@brief 显示指定应用Id,不采用DSGApplication::id()作为应用Id +@param[in] appId 配置文件所属的应用Id +@note 需要在QCoreApplication构造前设置。 + +@fn QString Dtk::Core::DConfig::backendName() +@brief 配置策略后端名称 +@return 配置策略后端名称 +@note 调用者只能用DConfig访问DConfigBackend对象,所以不返回DConfigBackend对象。 + +@fn QStringList Dtk::Core::DConfig::keyList() +@brief 获得所有可用的配置项名称 +@return 配置项名称集合 + +@fn bool Dtk::Core::DConfig::isValid() +@brief 判断此后端是否可用 + +@fn bool Dtk::Core::DConfig::isDefaultValue(const QString &key) +@brief 检测指定配置项名称对应的值是否为默认值。 +@param[in] key 配置项名称 + +@fn QVariant Dtk::Core::DConfig::value(const QString &key, const QVariant &fallback) +@brief 根据配置项名称获得对应值 +@param[in] key 配置项名称 +@param[in] fallback 没有获取到配置项值后提供的默认值 + +@fn void Dtk::Core::DConfig::setValue(const QString &key, const QVariant &value); +@brief 根据配置项名称设置其值 +@param[in] key 配置项名称 +@param[in] value 需要更新的值 + +@fn void Dtk::Core::DConfig::reset(const QString &key) +@brief 设置其配置项对应的默认值,此值为经过override机制覆盖后的值,不一定为此配置文件中meta中定义的值 +@param[in] key 配置项名称 + +@fn QString Dtk::Core::DConfig::name() +@brief 返回配置文件名称 + +@fn QString Dtk::Core::DConfig::subpath() +@brief 返回配置文件对应的子目录 + +*/ diff --git a/docs/global/dconfigfile.zh_CN.dox b/docs/global/dconfigfile.zh_CN.dox new file mode 100644 index 0000000..87ae4c7 --- /dev/null +++ b/docs/global/dconfigfile.zh_CN.dox @@ -0,0 +1,448 @@ +/*! +@~chinese +@file include/global/dconfigfile.h +@ingroup dglobal + +@class Dtk::Core::DConfigFile dconfigfile.h +@brief 规范配置文件读写的相关接口的配置文件实现 +@details +## 概述 + +规范配置文件读写的相关接口的配置文件实现 + +项目目录结构如下: +```bash +├── CMakeLists.txt +├── config +│ └── example.json +└── main.cpp +``` + +## CMakeLists.txt +```cmake +cmake_minimum_required(VERSION 3.1.0) # 指定cmake最低版本 + +project(dconfigfile-example VERSION 1.0.0 LANGUAGES CXX) # 指定项目名称, 版本, 语言 cxx就是c++ + +set(CMAKE_CXX_STANDARD 11) # 指定c++标准 +set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定c++标准要求,至少为11以上 + +set(CMAKE_AUTOMOC ON) # 支持qt moc +set(CMAKE_AUTORCC ON) # 支持qt资源文件 +set(CMAKE_AUTOUIC ON) # 支持qt ui文件(非必须) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 支持 clangd + +if (CMAKE_VERSION VERSION_LESS "3.7.0") # 如果cmake版本小于3.7.0 + set(CMAKE_INCLUDE_CURRENT_DIR ON) # 设置包含当前目录 +endif() + +find_package(Qt5 REQUIRED COMPONENTS Core) # 寻找Qt5组件Core +find_package(Dtk REQUIRED COMPONENTS Core) # 寻找Dtk组件Core + +add_executable(${PROJECT_NAME} # 生成可执行文件 + main.cpp +) + +target_link_libraries(${PROJECT_NAME} PRIVATE # 添加需要链接的共享库 + Qt5::Core + dtkcore +) + +# dtk_add_config_meta_files函数,部署一些"meta"的配置。 +# 函数定义在dtkcore的cmake目录下 +# APPID 应用的ID +# FILES 需要部署的文件。 +dtk_add_config_meta_files( + APPID ${PROJECT_NAME} + FILES ./config/example.json +) +``` + +## example.json +```json +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "canExit": { + "value": true, + "serial": 0, + "flags": ["global"], + "name": "I am name", + "name[zh_CN]": "我是名字", + "description": "I am description", + "permissions": "readwrite", + "visibility": "private" + }, + "key1": { + "value": "125", + "serial": 0, + "flags": ["nooverride"], + "name": "I am name", + "name[zh_CN]": "我是名字", + "description": "I am description", + "permissions": "readwrite", + "visibility": "public" + }, + "number": { + "value": 1, + "serial": 0, + "flags": ["global"], + "name": "array value type", + "permissions": "readwrite", + "visibility": "public" + }, + "array": { + "value": ["value1", "value2"], + "serial": 0, + "flags": ["global"], + "name": "array", + "permissions": "readwrite", + "visibility": "public" + }, + "map": { + "value": {"key1": "value1", "key2": "value2"}, + "serial": 0, + "flags": ["nooverride"], + "name": "map", + "permissions": "readwrite", + "visibility": "public" + }, + "publicConfig": { + "value": true, + "serial": 0, + "flags": ["user-public"], + "name": "public configure", + "name[zh_CN]": "我是公开的配置", + "description": "I am public configure", + "permissions": "readwrite", + "visibility": "private" + } + } +} +``` + +## main.cpp +```cpp +#include +#include +#include +#include + +DCORE_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + // 构造DConfigFile,元数据文件名example,与元数据安装目录的/usr/share/dsg/configs/APPID名(可执行文件名)对应目录/example.json, + DConfigFile configFile("dconfigfile-example","example"); + // 解析配置文件 + configFile.load(); + + // 创建用户缓存 + QScopedPointer userCache(configFile.createUserCache(getuid())); + // 解析配置文件 + userCache->load(); + + // 判断是否有效 + if (!configFile.isValid()) { + qWarning() << QString("DConfig无效."); + return 0; + } + + // meta 返回原型对象, keyList获取所有配置项的key + qDebug() << "所有的所有配置项的key:" << configFile.meta()->keyList(); + + // 获取指定配置项的值,配置项可以是字符串,数组,map容器,布尔值,整型,详见example.json + qDebug() << "canExit对应的值:" << configFile.value("canExit").toBool(); + + // 配置项的可见性,其余配置项标记、配置项的权限可查看文档 + qDebug() << "配置项的可见性" << configFile.meta()->visibility("canExit"); + + QVariantMap map; + map.insert("k1","v1"); + map.insert("k2","v2"); + // 设置map的值 + configFile.setValue("map", map, "dconfigfile-example", userCache.get()); + + configFile.save(); + + // root用户运行,save的数据会保存到/root/.config/dsg/configs-fake-global/dconfigfile-example/example.json + // map数据对应的flags标记为NoOverride,配置项允许被覆盖,如果flags为global泽忽略用户身份,详见文档。 + userCache->save(); + + return a.exec(); +} +``` + +## 从源码构建 +```bash +mkdir build && cd build +# 修改路径前缀为/usr,GNU标准的默认值为/usr/local +cmake .. -DCMAKE_INSTALL_PREFIX=/usr +sudo make install +sudo ./dconfigfile-example +``` + +结果如下图 + +![一些简单的输出](/docs/src/dconfigfile_example1.png) + +![用户保存的数据](/docs/src/dconfigfile_example2.png) + +@enum Dtk::Core::DConfigFile::Flag +@brief 配置项名称 +@var Dtk::Core::DConfigFile::Flag Dtk::Core::DConfigFile::NoOverride +@brief 存在此标记时,将表明则此配置项不可被覆盖(详见下述 override 机制)。反之,不存在此标记时表明此配置项允许被覆盖,对于此类配置项,如若其有界面设置入口,则当此项不可写时,应当隐藏或禁用界面的设置入口. +@var Dtk::Core::DConfigFile::Flag Dtk::Core::DConfigFile::Global +@brief 当读写此类配置时,将忽略用户身份,无论程序使用哪个用户身份执行,读操作都将获取到同样的数据,写操作将对所有用户都生效。但是,如果对应的配置存储目录不存在或无权限写入,则忽略此标志 +@var Dtk::Core::DConfigFile::Flag Dtk::Core::DConfigFile::UserPublic +@brief 该类配置项允许被其他用户访问 + + +@enum Dtk::Core::DConfigFile::Permissions +@brief 配置项的权限 +@var Dtk::Core::DConfigFile::Permissions Dtk::Core::DConfigFile::ReadOnly +@brief 将配置项覆盖为只读 +@var Dtk::Core::DConfigFile::Permissions Dtk::Core::DConfigFile::ReadWrite +@brief 将配置项覆盖为可读可写 + + +@enum Dtk::Core::DConfigFile::Visibility +@brief 配置项的可见性 +@var Dtk::Core::DConfigFile::Visibility Dtk::Core::DConfigFile::Private +@brief 仅限程序内部使用,对外不可见。此类配置项完全由程序自己读写,可随意增删改写其含义,无需做兼容性考虑 +@var Dtk::Core::DConfigFile::Visibility Dtk::Core::DConfigFile::Public +@brief 外部程序可使用。 此类配置项一旦发布,在兼容性版本的升级中,要保障此配置项向下兼容,简而言之,只允许在程序/库的大版本升级时才允许删除或修改此类配置项,当配置项的 permissions、visibility、flags 任意一个属性被修改则认为此配置项被修改,除此之外修改 value、name、description 属性时则不需要考虑兼容性。 + +@struct Dtk::Core::DConfigFile::Version +@brief 版本信息 +@details +此文件的内容格式的版本。版本号使用两位数字描述, +首位数字不同的描述文件相互之间不兼容,第二位数字不同的描述文件需满足向下兼容。 +读取此描述文件的程序要根据版本进行内容分析,当遇到不兼容的版本时,需要立即终止解析,忽略此文件, +并在程序日志中写入警告信息,如 “1.0” 和 “2.0” 版本之间不兼容, +如果解析程序最高只支持 1.0 版本,则遇到 2.0 版本的描述文件时应该终止解析, +但是如果遇到 1.1 版本,则可以继续执行。 +写入此描述文件时,遇到不兼容的版本时,需要先清空当前内容再写入,每次写入皆需更新此字段。 + +@fn static constexpr DConfigFile::Version Dtk::Core::DConfigFile::supportedVersion() +@brief 支持的版本 +@return + +@fn Dtk::Core::DConfigFile::DConfigFile(const QString &appId, const QString &name, const QString &subpath = QString()) +@brief DConfigFile构造函数,构造配置文件管理对象。 +@param[in] appId 应用程序唯一标识 +@param[in] name 配置文件名 +@param[in] subpath 子目录 + +@fn Dtk::Core::DConfigFile::DConfigFile(const DConfigFile &other); +@brief DConfigFile构造函数,构造配置文件管理对象。 +@param[in] appId 应用程序唯一标识 +@param[in] name 配置文件名 +@param[in] subpath 子目录 + +@fn bool Dtk::Core::DConfigFile::load(const QString &localPrefix = QString()) +@brief 解析配置文件 +@param[in] localPrefix 为目录前缀 +@return + +@fn bool Dtk::Core::DConfigFile::load(QIODevice *meta, const QList &overrides) +@brief 解析配置文件流 +@param[in] meta 为原型流 +@param[in] overrides 为覆盖机制查找的文件流 +@return + +@fn bool Dtk::Core::DConfigFile::save(const QString &localPrefix = QString(), QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool sync = false) const +@brief 保存缓存的值到磁盘中 +@param[in] format 保存格式 +@param[in] sync 是否立即刷新 +@return + +@fn bool Dtk::Core::DConfigFile::isValid() const +@brief 检测配置文件是否有效 +@return + +@fn QVariant Dtk::Core::DConfigFile::value(const QString &key, DConfigCache *userCache = nullptr) const +@brief DConfigFile::value +@param[in] key 配置项名称 +@param[in] userCache 用户缓存,当key为全局项时, \a userCache 不会被使用 +@return + +@fn QVariant Dtk::Core::DConfigFile::cacheValue(DConfigCache *userCache, const QString &key) const +@brief DConfigFile::cacheValue 获取指定用户缓存的配置项值,若无此配置项的用户缓存值,返回无效值 +@param[in] key 配置项名称 +@param[in] userCache 用户缓存,当key为全局配置项时, \a userCache 不会被使用 +@return + +@fn bool Dtk::Core::DConfigFile::setValue(const QString &key, const QVariant &value, const QString &callerAppid, DConfigCache *userCache = nullptr) +@brief 设置缓存中的值 +@param[in] key 配置项名称 +@param[in] value 需要设置的值 +@param[in] uid 设置时的用户id +@param[in] appid 设置时的应用id +@return 为true时表示重新设置了新值,false表示没有设置 + +@fn DConfigCache* Dtk::Core::DConfigFile::createUserCache(const uint uid) +@brief 创建用户缓存 + +@fn DConfigCache* Dtk::Core::DConfigFile::globalCache() const +@brief 返回全局缓存 +@return + +@fn DConfigMeta* Dtk::Core::DConfigFile::meta() +@brief 返回原型对象 +@return + +*/ + +/*! +@class Dtk::Core::DConfigMeta dconfigfile.h +@brief 提供配置文件的原型和覆盖机制的访问接口 + +@fn virtual DConfigFile::Version Dtk::Core::DConfigMeta::version() const = 0 +@brief 返回配置版本信息 +@return + +@fn virtual void Dtk::Core::DConfigMeta::setVersion(quint16 major, quint16 minor) = 0 +@brief 设置配置版本信息 +@param[in] major 主板本号 +@param[in] minor 次版本号 + +@fn virtual bool Dtk::Core::DConfigMeta::load(const QString &localPrefix = QString()) = 0 +@brief 解析配置文件 +@param[in] localPrefix 为目录前缀 +@return + +@fn virtual bool Dtk::Core::DConfigMeta::load(QIODevice *meta, const QList &overrides) = 0 +@brief 解析配置文件流 +@param[in] meta 为原型流 +@param[in] overrides 为覆盖机制查找的文件流 +@return + +@fn virtual QStringList Dtk::Core::DConfigMeta::keyList() const = 0 +@brief 返回配置内容的所有配置项 +@return + +@fn virtual DConfigFile::Flags Dtk::Core::DConfigMeta::flags(const QString &key) const = 0 +@brief 返回指定配置项的特性 +@param[in] key 配置项名称, NoOverride为此配置项不可被覆盖, Global为忽略用户身份 +@return + +@fn virtual DConfigFile::Permissions Dtk::Core::DConfigMeta::permissions(const QString &key) const = 0 +@brief 返回指定配置项的权限 +@param[in] key 配置项名称 +@return + +@fn virtual DConfigFile::Visibility Dtk::Core::DConfigMeta::visibility(const QString &key) const = 0 +@brief 返回指定配置项的可见性 +@param[in] key 配置项名称 +@return + +@fn virtual int Dtk::Core::DConfigMeta::serial(const QString &key) const = 0 +@brief 返回配置项的单调递增值 +@param[in] key 配置项名称 +@return -1为无效值,表明没有配置此项 + +@fn virtual QString Dtk::Core::DConfigMeta::displayName(const QString &key, const QLocale &locale) = 0 +@brief 返回指定配置项的显示名 +@param[in] key 配置项名称 +@param[in] locale 为语言版本 +@return + +@fn virtual QString Dtk::Core::DConfigMeta::description(const QString &key, const QLocale &locale) = 0 +@brief 返回指定配置项的描述信息 +@param[in] key 配置项名称 +@param[in] locale 为语言版本 +@return + +@fn virtual QString Dtk::Core::DConfigMeta::metaPath(const QString &localPrefix = QString(), bool *useAppId = nullptr) const = 0 +@brief 返回描述文件的路径 +@param[in] localPrefix 目录的所有需要查找的覆盖机制目录 +@param[in] useAppId 是否不使用通用目录 +@return + +@fn virtual QStringList Dtk::Core::DConfigMeta::allOverrideDirs(const bool useAppId, const QString &prefix = QString()) const = 0 +@brief 获得前缀为 `prefix` 目录的所有需要查找的覆盖机制目录 +@param[in] useAppId 是否不使用通用目录 +@param[in] prefix 目录的应用或公共库的所有覆盖机制目录 +@return + +@fn virtual QVariant DConfigMeta::value(const QString &key) const = 0 +@brief meta初始值经过覆盖机制覆盖后的原始值 +@param[in] key 配置项名称 +@return + +@fn static QStringList genericMetaDirs(const QString &localPrefix = QString()) +@brief 获取应用无关配置存储的目录 +@param[in] localPrefix 配置的目录前缀 +@return 返回应用无关配置存储的目录列表 + +@fn static QStringList applicationMetaDirs(const QString &localPrefix, const QString &appId) +@brief 获取应用配置存储的目录 +@param[in] localPrefix 配置的目录前缀 +@param[in] appId 应用唯一标识 +@return 返回存储应用配置的目录列表 +*/ + +/*! +@class Dtk::Core::DConfigCache dconfigfile.h +@brief 提供配置文件的用户和全局运行缓存访问接口 + +@fn virtual bool Dtk::Core::DConfigCache::load(const QString &localPrefix = QString()) = 0 +@brief 解析缓存配置文件 +@return + +@fn virtual bool Dtk::Core::DConfigCache::load(const QString &localPrefix = QString()) = 0 +@brief 解析缓存配置文件 +@return + +@fn virtual bool Dtk::Core::DConfigCache::save(const QString &localPrefix = QString(), QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool sync = false) = 0 +@brief 保存缓存的值到磁盘中 +@param[in] localPrefix 为目录前缀 +@param[in] format 保存格式 +@param[in] sync 是否立即刷新 +@return + +@fn virtual bool Dtk::Core::DConfigCache::isGlobal() const = 0 +@brief 是否是全局缓存 +@return + +@fn virtual void Dtk::Core::DConfigCache::remove(const QString &key) = 0 +@brief 删除缓存中的配置项 +@param[in] key 配置项名称 +@return + +@fn virtual QStringList Dtk::Core::DConfigCache::keyList() const = 0 +@brief 返回配置内容的所有配置项 +@return + +@fn virtual bool Dtk::Core::DConfigCache::setValue(const QString &key, const QVariant &value, const int serial, const uint uid, const QString &callerAppid) = 0 +@brief 设置缓存中的值 +@param[in] key 配置项名称 +@param[in] value 需要设置的值 +@param[in] uid 设置时的用户id +@param[in] callerAppid 设置时的应用id +@return 为true时表示重新设置了新值,false表示没有设置。 + +@fn virtual QVariant Dtk::Core::DConfigCache::value(const QString &key) const = 0 +@brief 获取缓存中的值 +@param[in] key 配置项名称 +@return + +@fn virtual int Dtk::Core::DConfigCache::serial(const QString &key) const = 0 +@brief 返回配置项的单调递增值 +@param[in] key 配置项名称 +@return -1为无效值,表明没有配置此项 + +@fn virtual uint Dtk::Core::DConfigCache::uid() const = 0 +@brief 用户标识,为全局缓存时,uid为非用户标识的特定值 +@return + +@fn virtual void setCachePathPrefix(const QString &prefix) = 0 +@brief 指定缓存位置前缀,缓存访问所需的权限及区分不同缓存的位置由调用者考虑,其默认值参考配置策略规范 +@param[in] prefix 缓存位置的前缀 + +*/ diff --git a/docs/global/ddesktopentry.zh_CN.dox b/docs/global/ddesktopentry.zh_CN.dox new file mode 100644 index 0000000..48496cd --- /dev/null +++ b/docs/global/ddesktopentry.zh_CN.dox @@ -0,0 +1,361 @@ +/*! +@~chinese +@file include/global/ddesktopentry.h +@ingroup dglobal + +@class Dtk::Core::DDesktopEntry ddesktopentry.h +@brief 处理desktop文件的接口 +@details +## 概述 + +DDesktopEntry提供了处理XDG desktop读写的方法的接口,这个Class类似于QSettings。 + +有关该规范本身的更多详细信息,请参阅: +https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html + + +项目目录结构在同一目录下 + +## CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.1.0) # 指定cmake最低版本 + +project(example1 VERSION 1.0.0 LANGUAGES CXX) # 指定项目名称, 版本, 语言 cxx就是c++ + +set(CMAKE_CXX_STANDARD 11) # 指定c++标准 +set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定c++标准要求,至少为11以上 +set(target example1) # 指定目标名称 + +set(CMAKE_AUTOMOC ON) # support qt moc # 支持qt moc +set(CMAKE_AUTORCC ON) # support qt resource file # 支持qt资源文件 +set(CMAKE_AUTOUIC ON) # support qt ui file # 支持qt ui文件(非必须) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # support clangd # 支持 clangd + +if (CMAKE_VERSION VERSION_LESS "3.7.0") # 如果cmake版本小于3.7.0 + set(CMAKE_INCLUDE_CURRENT_DIR ON) # 设置包含当前目录 +endif() +find_package(Qt5 COMPONENTS Core REQUIRED) # 寻找Qt5组件Core +find_package(Dtk COMPONENTS Core REQUIRED) # 寻找Dtk组件Core + +add_executable(${target} # 生成可执行文件 + main.cpp +) + +target_link_libraries(${target} PRIVATE # 添加需要链接的共享库 + Qt5::Core + dtkcore +) +``` + +## main.cpp + +```cpp +#include +#include +#include +#include + +DCORE_USE_NAMESPACE // 使用Dtk Core命名空间 + +const QString fileContent = { QStringLiteral(R"desktop(# A. Example Desktop Entry File +[Desktop Entry] +Version=1.0 +Type=Application +Name=Foo Viewer +Name[zh_CN]=福查看器 +Comment=The best viewer for Foo objects available! +# Next line have an extra " character +Comment[zh_CN]=最棒的 "福 查看器! +TryExec=fooview +Exec=fooview %F +Icon=fooview +MimeType=image/x-foo; +Actions=Gallery;Create; + +[Desktop Action Gallery] +Exec=fooview --gallery +Name=Browse Gallery + +[Desktop Action Create] +Exec=fooview --create-new +Name=Create a new Foo! +Icon=fooview-new +)desktop") }; + +int main(int argc, char *argv[]) +{ + QFile file("example1.desktop"); + // 尝试打开文件 + if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){ + qDebug()<<"文件打开失败"; + } + const QString fileName = file.fileName(); + QTextStream ts(&file); + ts << fileContent; + file.close(); + QFile::exists(fileName); + + // 打开一个fileName为example1.desktop的文件 + QScopedPointer desktopFile(new DDesktopEntry(fileName)); + + // 获取desktop中所有组并返回列表,对应"Desktop Entry"、"Desktop Action Gallery"、"Desktop Action Create"三组 + QStringList allGroups = desktopFile->allGroups(); + + qDebug() << QString("Desktop 文件共有%1组").arg(allGroups.count()); + + // 调用allGroups函数,传入true,保持读取desktop文件时的顺序不变,获取第0组 + qDebug() << QString("Desktop 文件第0组为: %1").arg(desktopFile->allGroups(true)[0]); + + // 获取key=Name,localeKey=zh_CN的值,即Name[zh_CN]=福查看器 + qDebug() << QString("Name[zh_CN]=%1") \ + .arg(desktopFile->localizedValue("Name", "zh_CN")); + + // 获取key为Nam,,localeKey为empty的值,empty表示没有localeKey,即Name=Foo Viewer + qDebug() << QString("Name=%1") \ + .arg(desktopFile->localizedValue("Name", "empty")); + + // 获取Desktop Entry组下的所有key,即"Actions", "Comment", "Comment[zh_CN]", "Exec", "Icon", "MimeType", "Name", "Name[zh_CN]", "TryExec", "Type", "Version" + qDebug() << QString("Desktop Entry组下的所有key: ") \ + << desktopFile->keys("Desktop Entry"); + + // 设置 key 为 Name的值为"Bar Viewer",默认组是"Desktop Entry" + desktopFile->setRawValue("Bar Viewer", "Name"); + + // 设置 key 为 Name,localeKey为zh_CN的值为霸查看器,默认组是"Desktop Entry" + desktopFile->setLocalizedValue("霸查看器", "zh_CN", "Name"); + + // 检查 section 中是否包 key 为 Semicolon 的值,包含 key 返回true; 否则返回false,默认组是Desktop Entry + qDebug() << QString("Desktop Entry组是否包key是Semicolon: ") \ + << desktopFile->contains("Semicolon", "Desktop Entry"); + + // 设置key为Semicolon的值为";grp\\;2;grp3;",默认组是"Desktop Entry" + desktopFile->setRawValue(";grp\\;2;grp3;", "Semicolon"); + + // 返回给定 section 中与给定 key 关联的字符串的列表。如果destkop不包含为该键的项,则函数返回一个空字符串列表。 默认组是Desktop Entry + qDebug() << QString("Desktop Entry组中Semicolon对应值的字符串列表: ") \ + << desktopFile->stringListValue("Semicolon"); + + // 再次检查 section 中是否包 key 为 Semicolon 的值,此时为true + qDebug() << QString("Desktop Entry组是否包key是Semicolon: ") \ + << desktopFile->contains("Semicolon", "Desktop Entry"); + + // 删除desktop中 section 中 key 对应的值,默认组是"Desktop Entry" + desktopFile->removeEntry("Semicolon", "Desktop Entry"); + + // 再次检查 section 中是否包 key 为 Semicolon 的值,此时为false + qDebug() << QString("Desktop Entry组是否包key是Semicolon: ") \ + << desktopFile->contains("Semicolon", "Desktop Entry"); + + // 将数据回写到desktop文件。 true表示写成功; 否则返回false + if (desktopFile->save()) + { + qDebug() << "文件保存成功"; + } else { + qDebug() << "文件保存失败"; + } + + return 0; +} +``` + +结果如下图 + +![example](/docs/src/ddesktopentry_example1.png) + +@enum Dtk::Core::DDesktopEntry::EntryType +@brief 桌面入口文件的类型 +@var Dtk::Core::DDesktopEntry::Unknown +@brief 未知的桌面文件类型。可能是无效的 +@var Dtk::Core::DDesktopEntry::Application +@brief 该文件描述应用程序 +@var Dtk::Core::DDesktopEntry::Link +@brief 该文件描述URL +@var Dtk::Core::DDesktopEntry::Directory +@brief 该文件描述目录设置 +@var Dtk::Core::DDesktopEntry::ServiceType +@brief KDE特定类型。规范中提到过, 所以这里也列出了 +@var Dtk::Core::DDesktopEntry::Service +@brief KDE特定类型。规范中提到过, 所以这里也列出了 +@var Dtk::Core::DDesktopEntry::FSDevice +@brief KDE特定类型。规范中提到过, 所以这里也列出了 + +@enum Dtk::Core::DDesktopEntry::ValueType +@brief 值的类型 +@var Dtk::Core::DDesktopEntry::Unparsed +@brief 未解析的值 +@var Dtk::Core::DDesktopEntry::String +@brief 字符串 +@var Dtk::Core::DDesktopEntry::Strings +@brief 字符串数组 +@var Dtk::Core::DDesktopEntry::Boolean +@brief 布尔值 +@var Dtk::Core::DDesktopEntry::Numeric +@brief 数字 +@var Dtk::Core::DDesktopEntry::NotExisted +@brief 不存在 + +@enum Dtk::Core::DDesktopEntry::Status +@brief desktop文件的解析状态 +@var Dtk::Core::DDesktopEntry::NoError +@brief 没有错误发生 +@var Dtk::Core::DDesktopEntry::AccessError +@brief 发生访问错误(例如, 试图写入只读文件) +@var Dtk::Core::DDesktopEntry::FormatError +@brief 发生格式错误(例如, 加载格式错误的desktop文件) + +@fn Dtk::Core::DDesktopEntry::DDesktopEntry(const QString &filePath) noexcept +@brief DDesktopEntry构造函数 + +@fn bool Dtk::Core::DDesktopEntry::save() const +@brief 将数据回写到desktop文件。 +@return true表示写成功; 否则返回false + +@fn Status Dtk::Core::DDesktopEntry::status() const +@brief Get data parse status +@return 返回一个状态码, 表示DDesktopEntry遇到的第一个错误, 如果没有错误发生, 则返回QSettings::NoError。请注意, DDesktopEntry会延迟执行某些操作。 + +@fn QStringList Dtk::Core::DDesktopEntry::keys(const QString §ion = "Desktop Entry") const +@brief 根据 `section` 返回全部键值 +@return 返回所有的键值 + +@fn QStringList Dtk::Core::DDesktopEntry::allGroups(bool sorted = false) const +@brief 获取desktop中所有组的列表。如果 `sorted` 设置为true, 则返回结果将保持读取desktop文件时的顺序不变。 +@return 返回所有的组. + +@fn bool Dtk::Core::DDesktopEntry::contains(const QString &key, const QString §ion = "Desktop Entry") const +@brief 检查desktop文件是否有给定的 `section` 包含给定的 `key` +@return 如果desktop在 `section` 包含 `key` 返回true; 否则返回false。 + +@fn QString Dtk::Core::DDesktopEntry::name() const +@brief 返回“Desktop Entry”部分下的“Name”键的本地化字符串值。这等价于调用localizedValue("Name")。 +@return 返回“Desktop Entry”部分下的“Name”键的本地化字符串值。 +@sa localizedValue(), genericName(), ddeDisplayName() + +@fn QString Dtk::Core::DDesktopEntry::genericName() const +@brief 返回"Desktop Entry"部分下的"GenericName"键的本地化字符串值。它等价于调用localizedValue("GenericName")。如果是“GenericName”不存在。则不会回退到“Name”。 +@return 返回"Desktop Entry"部分下的"GenericName"键的本地化字符串值。 +@sa localizedValue(), name(), ddeDisplayName() + +@fn QString Dtk::Core::DDesktopEntry::ddeDisplayName() const +@brief 为DDE应用程序专门显示名称 +@details 这将检查“X-Deepin-Vendor”,并将返回本地化的字符串值“GenericName” +"X-Deepin-Vendor"是"deepin",否则它将返回"Name"的本地化字符串值。 +@return 返回专门用于DDE应用程序的显示名称 +@sa localizedValue(), name(), genericName() + +@fn QString Dtk::Core::DDesktopEntry::comment() const +@brief 返回“Desktop Entry”部分下的“Comment”键的本地化字符串值。这等价于调用localizedValue("Comment")。 +@return 返回“Desktop Entry”部分下的“Comment”键的本地化字符串值。 +@sa localizedValue() + +@fn QString Dtk::Core::DDesktopEntry::rawValue(const QString &key, const QString §ion = "Desktop Entry", const QString &defaultValue = QString()) const +@brief 返回 `section` 中与给定 `key` 关联的原始字符串值。如果desktop不包含具有该键的项, 则函数返回一个构造好的 `defaultValue`。 +@return 返回 `section` 中与给定 `key` 相关联的原始字符串值。 +@sa stringValue() localizedValue() stringListValue() + +@fn QString Dtk::Core::DDesktopEntry::stringValue(const QString &key, const QString §ion = "Desktop Entry", const QString &defaultValue = QString()) const +@brief 返回 `section` 与给定 `key` 关联的未转义字符串值。如果desktop不包含键值为0的项, 则函数返回一个构造好的 `defaultValue`。 +@return 返回 `section` 中与给定 `key` 相关联的未转义字符串值。 +@sa rawValue() localizedValue() stringListValue() + +@fn QString Dtk::Core::DDesktopEntry::localizedValue(const QString &key, const QString &localeKey = "default", const QString §ion = "Desktop Entry", const QString& defaultValue = QString()) const +@brief 返回与 `section` 中给定的 `key` 和 `localeKey` 相关联的本地化字符串值。 +@details +如果找不到给定的 `localeKey` ,它将回退到"C",如果仍然找不到,将回退 `key` 没有`localeKey`部分。。 +如果destkop不包含 `key` 值为0的项,则函数返回一个构造好的 `defaultValue`。 +@return 返回 `section` 中与给定的 `key` 和 `localeKey` 关联的本地化字符串值。 +@sa rawValue() stringValue() stringListValue() + +@fn QString Dtk::Core::DDesktopEntry::localizedValue(const QString &key, const QLocale &locale, const QString §ion = "Desktop Entry", const QString& defaultValue = QString()) const +@brief 返回与给定的 `key` 和 `section` 中的区域设置相关联的本地化字符串值。 +@details +如果找不到给定的 `localeKey` ,它将回退到"C",如果仍然找不到,将回退 `key` 没有`localeKey`部分。 +如果destkop不包含 `key` 值为0的项,则函数返回一个构造好的 `defaultValue`。 +@return 返回 `section`中 与给定的 `key` 和 `locale` 设置相关联的本地化字符串值。 +@sa rawValue() stringValue() stringListValue() + +@fn QStringList Dtk::Core::DDesktopEntry::stringListValue(const QString &key, const QString §ion = "Desktop Entry") const +@brief 返回给定 `section` 中与给定 `key` 关联的字符串的列表。如果destkop不包含为该键的项,则函数返回一个空字符串列表。 +@return 返回给定 `section` 中与给定 `key` 关联的字符串的列表。 +@sa rawValue() stringValue() localizedValue() + +@fn bool Dtk::Core::DDesktopEntry::setRawValue(const QString &value, const QString &key, const QString& section = "Desktop Entry") +@brief 设置给定 `section` 中与给定 `key` 关联的原始字符串值。 + +@fn bool Dtk::Core::DDesktopEntry::setStringValue(const QString &value, const QString &key, const QString& section = "Desktop Entry") +@brief 设置给定 `section` 中与给定 `key` 关联的字符串 + +@fn bool Dtk::Core::DDesktopEntry::setLocalizedValue(const QString &value, const QString& localeKey, const QString &key, const QString& section = "Desktop Entry") +@brief 设置给定的 `key` 和 `section` 中的区域设置相关联的本地化字符串值。 + +@fn bool Dtk::Core::DDesktopEntry::removeEntry(const QString &key, const QString §ion = "Desktop Entry"); +@brief 删除desktop中 `section` 与 `key` 对应的值 + +@fn static QString& Dtk::Core::DDesktopEntry::escape(QString &str) +@brief 支持转义序列`\s`、`\n`、`\t`、`\r`和`\\`表示值 +@details string和localestring类型的值支持转义序列`\s`、`\n`、`\t`、`\r`和`\\`,分别表示ASCII空格、换行符、制表符、回车和反斜杠。 + +@fn static QString& Dtk::Core::DDesktopEntry::escapeExec(QString &str) +@brief 必须将参数括在双引号之间,并对双引号字符进行转义。 +@details +| 原字符 | 转义后 | +|------|---------| +| \` | "`" | +| $ | "$" | +| \ | "\" | +在它前面加上一个额外的反斜杠字符。实现必须在扩展字段代码之前和之前撤销引用,将参数传递给可执行程序。 +@note 类型为string的值的通用转义规则规定,反斜杠字符也可以转义为("\\")和这个转义规则应用在引用规则之前。
+因此,要明确地表示在desktop文件中,引号参数中的文字反斜杠字符
+要求使用四个连续的反斜杠字符("\\\\")。同样,在桌面入口文件中引用参数中的美元符号表示为("\\$")。 + +@fn static QString& Dtk::Core::DDesktopEntry::unescape(QString &str, bool unescapeSemicolons = false) +@brief 对于类型为string和localestring的值,支持转义序列`\s`、`\n`、`\t`、`\r`和`\\`,分别表示ASCII空格、换行符、制表符、回车符和反斜杠。 +@details 有些键可以有多个值。这种情况下,`key` 的值被指定为复数形式: +例如,字符串。多个值应该用分号分隔,`key` 的值可以选择以分号结尾。空字符串必须以分号结尾。 +这些值中的分号需要使用`\;`转义。 + +有关该规范本身的更多详细信息,请参阅: +https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#value-types + +@fn static QString& Dtk::Core::DDesktopEntry::unescapeExec(QString &str) +@brief 必须将参数括在双引号之间,并对双引号字符进行转义, +@details +| 原字符 | 转义后 | +|------|---------| +| \` | "`" | +| $ | "$" | +| \ | "\" | +在它前面加上一个额外的反斜杠字符。实现必须在扩展字段代码之前和之前撤销引用,将参数传递给可执行程序。 + +保留字符: +| 功能 | 字符 | +|---------------------|---------| +| space | " " | +| tab | | +| newline | | +| double quote | | +| single quote | "'" | +| backslash character | "\" | +| greater-than sign | ">" | +| less-than sign | "<" | +| tilde | "~" | +| vertical bar | \| | +| ampersand | "&" | +| semicolon | ";" | +| dollar sign | "$" | +| asterisk | "*" | +| question mark | "?" | +| hash mark | "#" | +| parenthesis | "(" 和 ")" | +| backtick character | "`" | +@note 类型为string的值的通用转义规则规定
+反斜杠字符也可以转义为("\\"),而且转义规则在引号规则之前应用。
+因此,要在desktop文件的引号参数中明确表示字面上的反斜杠字符,需要使用四个连续的反斜杠字符(“\\\\”)。
+同样,在desktop文件中,引号参数中的美元符号可以明确地表示为("\\$")。 + +@fn bool Dtk::Core::DDesktopEntry::setStatus(const Status &status) +@brief 设置desktop文件解析状态 + +*/ diff --git a/docs/global/dlicenseinfo.zh_CN.dox b/docs/global/dlicenseinfo.zh_CN.dox new file mode 100644 index 0000000..8f22ab9 --- /dev/null +++ b/docs/global/dlicenseinfo.zh_CN.dox @@ -0,0 +1,51 @@ +/*! +@~chinese +@ingroup dglobal +@file include/global/dlicenseinfo.h + +@class Dtk::Core::DLicenseInfo::DComponentInfo +@brief dcomponentinfo 是一组用于查询组件所用开源协议信息的类 + +@fn Dtk::Core::DLicenseInfo::DComponentInfo::DComponentInfo(DObject *parent) +@brief 组件信息类的构造函数 +@param[in] parent 组件信息类的父对象 + +@fn QString Dtk::Core::DLicenseInfo::DComponentInfo::name() +@brief 获取组件的名称 + +@fn QString Dtk::Core::DLicenseInfo::DComponentInfo::version() +@brief 获取组件的版本号 + +@fn QString Dtk::Core::DLicenseInfo::DComponentInfo::copyRight() +@brief 获取组件的授权信息 + +@fn QString Dtk::Core::DLicenseInfo::DComponentInfo::licenseName() +@brief 获取组件的所用开源许可协议名称 + +@class Dtk::Core::DLicenseInfo +@brief dlicenseinfo是一组用于查询应用所用开源许可协议相关信息的类 + +@fn Dtk::Core::DLicenseInfo::DLicenseInfo(DObject *parent) +@brief 开源许可协议信息类的构造函数 +@param[in] parent 开源许可协议信息类的父对象 + +@fn bool Dtk::Core::DLicenseInfo::loadContent(const QByteArray &content) +@brief 通过内容content加载协议 +@return 0 加载失败 +@return 1 加载成功 + +@fn bool Dtk::Core::DLicenseInfo::loadFile(const QString &file) +@brief 通过文件file加载协议 +@return 0 加载失败 +@return 1 加载成功 + +@fn void Dtk::Core::DLicenseInfo::setLicenseSearchPath(const QString &path) +@brief 设置协议内容路径path + +@fn QByteArray Dtk::Core::DLicenseInfo::licenseContent(const QString &licenseName) +@brief 获取协议名为licenseName的内容 + +@fn DLicenseInfo::DComponentInfos Dtk::Core::DLicenseInfo::componentInfos() +@brief 获取组件的相关信息 + +*/ diff --git a/docs/global/dsysinfo.zh_CN.dox b/docs/global/dsysinfo.zh_CN.dox new file mode 100644 index 0000000..7b78e87 --- /dev/null +++ b/docs/global/dsysinfo.zh_CN.dox @@ -0,0 +1,307 @@ +/*! +@~chinese +@ingroup dglobal +@file include/global/dsysinfo.h + +@class Dtk::Core::DSysInfo +@brief dsysinfo 是一组用于查询系统信息的静态类 +@details +## 概述 + +dsysinfo是一组用于查询系统信息的静态类 + +项目目录结构如下: + +```bash +├── CMakeLists.txt +└── main.cpp +``` + +## CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.13) # cmake版本要求 +set (VERSION "1.0.0" CACHE STRING "define project version") # 定义项目版本 +set(BIN_NAME test) # 定义项目名称 +project(test) # 定义项目名称 +file(GLOB_RECURSE SRCS "*.h" "*.cpp") # 定义项目源文件 +find_package(Qt5 REQUIRED COMPONENTS Core) # 寻找Qt5 +find_package(DtkCore REQUIRED) # 寻找DtkCore + +add_executable(test + main.cpp # 源文件 +) + +target_link_libraries(test PRIVATE + ${DtkCore_LIBRARIES} # 链接DtkCore + Qt5::Core # 链接Qt5 +) + +``` + +## main.cpp + +```cpp +#include // 引入DSysInfo +#include // 引入qdebug.h +DCORE_USE_NAMESPACE // 使用dtkcore命名空间 + +int main(int argc, char **argv) { + + qDebug() << DSysInfo::deepinType(); // 打印deepin类型 + qDebug() << DSysInfo::ProductType(); // 打印产品类型 + return 0; +} +``` + +@enum Dtk::Core::DSysInfo::ProductType +@brief 产品信息 +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Deepin +@brief 深度操作系统 +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::ArchLinux +@brief ArchLinux +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::CentOS +@brief CentOS +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Debian +@brief Debian +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Fedora +@brief Fedora +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::LinuxMint +@brief LinuxMint +@var Dtj::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Manjaro +@brief Manjaro +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::openSUSE +@brief openSUSE +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::SailfishOS +@brief SailfishOS +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Ubuntu +@brief Ubuntu +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Uos +@brief UOS +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::Gentoo +@brief Gentoo +@var Dtk::Core::DSysInfo::ProductType Dtk::Core::DSysInfo::NixOS +@brief NixOS + +@enum Dtk::Core::DSysInfo::DeepinType +@brief 深度操作系统版本 +@var Dtk::Core::DSysInfo::DeepinType Dtk::Core::DSysInfo::UnknownDeepin +@brief 未知版本 +@var Dtk::Core::DSysInfo::DeepinType Dtk::Core::DSysInfo::DeepinDesktop +@brief 桌面版 +@var Dtk::Core::DSysInfo::DeepinType Dtk::Core::DSysInfo::DeepinProfessional +@brief deepin专业版, 现为uos专业版 +@var Dtk::Core::DSysInfo::DeepinType Dtk::Core::DSysInfo::DeepinServer +@brief deepin服务器版本, 现为uos服务器版 +@var Dtk::Core::DSysInfo::DeepinType Dtk::Core::DSysInfo::DeepinPersonal +@brief deepin个人版, 现为uos家庭版 + +@enum Dtk::Core::DSysInfo::LogoType +@brief 系统的logo类型 +@var Dtk::Core::DSysInfo::LogoType Dtk::Core::DSysInfo::Normal +@brief 正常 +@var Dtk::Core::DSysInfo::LogoType Dtk::Core::DSysInfo::Light +@brief 亮色 +@var Dtk::Core::DSysInfo::LogoType Dtk::Core::DSysInfo::Symbolic +@brief 符号 +@var Dtk::Core::DSysInfo::LogoType Dtk::Core::DSysInfo::Transparent +@brief 水印 + +@enum Dtk::Core::DSysInfo::OrgType +@brief 组织类型 +@var Dtk::Core::DSysInfo::OrgType Dtk::Core::DSysInfo::Distribution +@brief 当前版本 +@var Dtk::Core::DSysInfo::OrgType Dtk::Core::DSysInfo::Distributor +@brief 当前发行版 +@var Dtk::Core::DSysInfo::OrgType Dtk::Core::DSysInfo::Manufacturer +@brief 当前发行版或设备的制造商 + +@enum Dtk::Core::DSysInfo::UosType +@brief UOS版本类型 +@var Dtk::Core::DSysInfo::UosType Dtk::Core::DSysInfo::UosTypeUnknown +@brief 未知版本 +@var Dtk::Core::DSysInfo::UosType Dtk::Core::DSysInfo::UosDesktop +@brief UOS桌面版 +@var Dtk::Core::DSysInfo::UosType Dtk::Core::DSysInfo::UosServer +@brief UOS服务器版 +@var Dtk::Core::DSysInfo::UosType Dtk::Core::DSysInfo::UosDevice +@brief UOS设备版 +@var Dtk::Core::DSysInfo::UosType Dtk::Core::DSysInfo::UosTypeCount +@brief 记录枚举数量 + +@enum Dtk::Core::DSysInfo::UosEdition +@brief 详细uos版本 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEditionUnknown +@brief 未知版本 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosProfessional +@brief UOS专业版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosHome +@brief UOS家庭版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosCommunity +@brief 社区版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosMilitary +@brief * +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEnterprise +@brief UOS企业版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEnterpriseC +@brief UOS行业版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEuler +@brief UOS服务器欧拉版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosMilitaryS +@brief * +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosDeviceEdition +@brief UOS专用设备版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEducation +@brief UOS教育版 +@var Dtk::Core::DSysInfo::UosEdition Dtk::Core::DSysInfo::UosEditionCount +@brief 记录枚举数量 + +@enum Dtk::Core::DSysInfo::UosArch +@brief UOS使用的架构 +@var Dtk::Core::DSysInfo::UosArch Dtk::Core::DSysInfo::UosArchUnknown +@brief 未知架构 +@var Dtk::Core::DSysInfo::UosArch Dtk::Core::DSysInfo::UosAMD64 +@brief x86_64 +@var Dtk::Core::DSysInfo::UosArch Dtk::Core::DSysInfo::UosARM64 +@brief arm64 +@var Dtk::Core::DSysInfo::UosArch Dtk::Core::DSysInfo::UosMIPS64 +@brief mips64 +@var Dtk::Core::DSysInfo::UosArch Dtk::Core::DSysInfo::UosSW64 +@brief sw_64 + + +@fn static bool Dtk::Core::DSysInfo::isDeepin() //FIXME: 显示错乱 无法修复 +@brief 是否为 deepin 或 uos 系统 +@return 0 不是 deepin 或 uos 系统 +@return 1 是 deepin 或 uos 系统 + +@fn static bool Dtk::Core::DSysInfo::isDDE() +@brief 是否使用 dde 桌面环境 +@note 此方法仅在 linux 平台下可用 + +@fn static DeepinType Dtk::Core::DSysInfo::deepinType() +@brief deepin 系统类型 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::deepinTypeDisplayName (const QLocale &locale=QLocale::system()) +@brief 显示的 deepin 发行版类型名称 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::deepinVersion() +@brief deepin 版本 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::deepinCopyright() +@brief deepin 开源许可协议 +@note 此方法仅在 linux 平台下可用 + +@fn static UosEdition Dtk::Core::DSysInfo::uosEditionType() +@brief DSysInfo::osEditionType 版本类型 显示版本类型 专业版/个人版/社区版.. +@note 根据 osBuild.B && osBuild.D +@note 此方法仅在 linux 平台下可用 + +@fn static UosArch Dtk::Core::DSysInfo::uosArch() +@brief DSysInfo::osArch 架构信息 +@details(使用一个字节的二进制位, 从低位到高位) 【0x8 sw64】【0x4 mips64】【0x2 arm64】【0x1 amd64】 +@note 此处架构是从 OsBuild 获取的系统版本的 Arch 信息, 并不是指硬件的 Arch 信息 +@note 此方法仅在 linux 平台下可用 + +@fn static QString uosProductTypeName(const QLocale &locale=QLocale::system()) +@brief DSysInfo::osProductTypeName 版本名称 +@details ProductType[xx] 项对应的值, 如果找不到对应语言的默认使用 ProductType 的值(Desktop/Server/Device) locale 当前系统语言 + +@fn static QString Dtk::Core::DSysInfo::uosSystemName(const QLocale &locale=QLocale::system()) +@brief SystemName[xx] 项对应的值 +@details 如果找不到对应语言的默认使用 SystemName 的值 Uniontech OS locale 当前系统语言 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::function uosEditionName(const QLocale &locale=QLocale::system()) +@brief 版本名称 EditionName[xx] 项对应的值 +@details 如果找不到对应语言的默认使用 EditionName 的值(Professional/Home/Community...) locale 当前系统语言 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::spVersion() +@brief 阶段版本名称 +@details 小版本号 A-BC-D 中 BC、 A.B.C 中的 B 返回 SP1-SPxx, 如果正式版返回空 X.Y.Z模式下暂不支持返回此版本号 +@note minVersion.BC == 00 正式版本, minVersion.BC | minVersion.B == 01-99 SP1….SP99 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::udpateVersion() +@brief 更新版本名称 小版本号 A-BC-D 中 D、A.B.C 模式中的 C 返回 update1… update9, 如果正式版返回空 X.Y.Z 模式下暂不支持返回此版本号 +@note minVersion.D == 0;正式版本 minVersion.D | minVersion.C == 1-9;update1… update9, updateA...updateZ +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::majorVersion() +@brief 主版本号 主版本号 【20】【23】【25】【26】【29】【30】 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::minorVersion() +@brief 小版本号 【ABCD】 ·[0-9]{4} 【A.B.C】 或者【X.Y.Z】 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::buildVersion() +@brief 小版本号 系统镜像批次号, 按时间顺序(不可回退)从100-999递增 +@note 此方法仅在 linux 平台下可用 + +@fn static QString Dtk::Core::DSysInfo::distributionInfoPath () +@brief 返回 distribution 文件地址 一般在`/usr/share/deepin/`目录下 + +@fn static QString Dtk::Core::DSysInfo::distributionInfoSectionName(OrgType type) +@brief 返回 distribution.info 文件中 SectionName 字段的值 + +@fn static Dtk::Core::DSysInfo::distributionOrgName(OrgType type=Distribution, const QLocale &locale=QLocale::system()) +@brief 返回组织名称 +@details 使用类型为Distribution来获取当前deepin distribution本身的名称 + +@fn static QPairDtk::Core::DSysInfo::distributionOrgWebsite(OrgType type=Distribution) +@brief 发行版组织的网站名称和网址。使用 type 作为 Distribution 获取当前 deepin 发行版本身的名称。 + +@fn static QString Dtk::Core::DSysInfo::distributionOrgLogo(OrgType orgType=Distribution, LogoType type=Normal, const QString &fallback=QString()) +@brief 获得的组织logo路径, 如果不存在, 则返回给定的其他路径 +@details 使用 type 作为 Distribution 获取当前 deepin 发行版本身的logo。 + +@fn static QString Dtk::Core::DSysInfo::operatingSystemName() +@brief 操作系统名 + +@fn static ProductType Dtk::Core::DSysInfo::productType() +@brief 产品类型 + +@fn static QString Dtk::Core::DSysInfo::productVersion() +@brief 产品版本 + +@fn static bool Dtk::Core::DSysInfo::isCommunityEdition() +@brief 检查当前版本是否是社区版 开发者可以使用这种方式来检查我们是否需要启用或禁用社区版或企业版的功能。 +@details 目前的规则: + 专业版、服务器版、个人版(DeepinType)将被视为企业版。
+ Uos(ProductType)将被视为企业版。 + +@fn static QString Dtk::Core::DSysInfo::computerName() +@brief 电脑名 + +@fn static QString Dtk::Core::DSysInfo::cpuModelName() +@brief cpu模式名 + +@fn static qint64 Dtk::Core::DSysInfo::memoryInstalledSize() +@brief 内存安装大小 + +@fn static qint64 Dtk::Core::DSysInfo::memoryTotalSize() +@brief 实际内存大小 + +@fn static qint64 Dtk::Core::DSysInfo::systemDiskSize() +@brief 系统磁盘大小 + +@fn static QDateTime Dtk::Core::DSysInfo::bootTime () +@brief 系统启动时间点 + +@fn static QDateTime Dtk::Core::DSysInfo::shutdownTime () +@brief 上一次正常关机时间点(重启也会被记录在内) + +@fn static qint64 Dtk::Core::DSysInfo::uptime() +@brief 系统启动到现在时长 +@note 参见`cat /proc/uptime`命令 + +@fn static Arch Dtk::Core::DSysInfo::arch +@brief cpu架构信息 +@note 此处架构是从gcc编译器获取的 + +*/ diff --git a/docs/global/index.zh_CN.md b/docs/global/index.zh_CN.md new file mode 100644 index 0000000..f175983 --- /dev/null +++ b/docs/global/index.zh_CN.md @@ -0,0 +1,50 @@ +@page global global--dtk全局工具组件 + +# DTk global:dtk全局工具类 +## dsysinfo:dtk系统信息工具类 + +[dsysinfo.h 详细文档](dsysinfo_8h.html)
+这里放一个最小化使用dsysinfo的例子:
+cmake: + +```cmake +cmake_minimum_required(VERSION 3.13) # cmake版本要求 +set (VERSION "1.0.0" CACHE STRING "define project version") # 定义项目版本 +set(BIN_NAME test) # 定义项目名称 +project(test) # 定义项目名称 +file(GLOB_RECURSE SRCS "*.h" "*.cpp") # 定义项目源文件 +find_package(Qt5 REQUIRED COMPONENTS Core) # 寻找Qt5 +find_package(DtkCore REQUIRED) # 寻找DtkCore + +add_executable(test + main.cpp # 源文件 +) + +target_link_libraries(test PRIVATE + ${DtkCore_LIBRARIES} # 链接DtkCore + Qt5::Core # 链接Qt5 +) + +``` +cpp: +```cpp +#include // 引入DSysInfo +#include // 引入qdebug.h +DCORE_USE_NAMESPACE // 使用dtkcore命名空间 + +int main(int argc, char **argv) { + + qDebug() << DSysInfo::deepinType(); // 打印deepin类型 + qDebug() << DSysInfo::ProductType(); // 打印产品类型 + return 0; +} +``` +其余的组件使用方法类似,这里就不一一列举了 + +@defgroup dglobal +@brief dtk设置全局工具组件 +@details + dtk全局工具组件,提供了设置全局工具的功能。
+ 包含以下功能: + * dsysinfo:dtk系统信息工具类 + * dconfig:dtk配置文件工具类 diff --git a/docs/log/AbstractAppender.zh_CN.dox b/docs/log/AbstractAppender.zh_CN.dox new file mode 100644 index 0000000..fa31731 --- /dev/null +++ b/docs/log/AbstractAppender.zh_CN.dox @@ -0,0 +1,70 @@ +/*! +@~chinese +@ingroup dlog +@file include/log/AbstractAppender.h + +AbstractAppender类是所有可以与Logger一起使用的日志appender的基础接口类。 +@class Dtk::Core::AbstractAppender +@brief AbstractAppender为应用消息的线程安全、互斥保护的日志提供了一个通用的实现 +@details AbstractAppender为应用消息的线程安全、互斥保护的日志提供了一个通用的实现,例如ConsoleAppender、FileAppender或其他的东西。
+ AbstractAppender是抽象的,不能被实例化,但是你可以使用它的任何一个子类,或者根据你的选择创建一个自定义的日志appender。
+ Appenders是逻辑设备,旨在通过调用`Logger::registerAppender()`附加到Logger对象。在每个来自应用程序的日志记录调用中,Logger对象都会依次调用所有在它身上注册的appender的`write()`函数。
+ 你可以子类化AbstractAppender来实现你喜欢的任何类型的日志目标。它可以是外部日志子系统(例如,*nix中的syslog)、XML文件、SQL数据库条目、D-Bus消息或任何你能想到的其他东西。
+ 对于简单的非结构化的纯文本日志(例如,到一个纯文本文件或到控制台输出),请子类化AbstractStringAppender而不是AbstractAppender,这将给你一个更方便的方法来控制日志输出的格式。 + +@fn AbstractAppender Dtk::Core::AbstractAppender::AbstractAppender() +@brief AbstractAppender构造函数 + +@fn AbstractAppender Dtk::Core::AbstractAppender::~AbstractAppender() +@brief AbstractAppender析构函数 + +@fn Logger::LogLevel Dtk::Core::AbstractAppender::detailsLevel() +@brief 返回appender的当前日志级别 +@details 返回appender的当前日志级别.日志级别低于当前`detailsLevel()`的日志记录将被appender默认忽略, + 并且不会被发送到其append()函数。 + 它提供了额外的日志灵活性,允许你为不同类型的日志设置不同的记录等级 +@note 该函数是线程安全的 +@sa setDetailsLevel() +@sa Logger::LogLevel +@return 日志记录等级 + +@fn void Dtk::Core::AbstractAppender::setDetailsLevel(Logger::LogLevel level) +@brief 设置当前appender的记录级别,默认记录级别为Logger::Debug +@note 该函数是线程安全的 +@sa setDetailsLevel() +@sa Logger::LogLevel + +@fn void Dtk::Core::AbstractAppender::setDetailsLevel(const QString &level) +@brief 设置当前appender的记录级别,这个函数是为了简化输入而提供的,它的行为与同名函数类似。 +@sa AbstractAppender::setDetailsLevel(Logger::LogLevel level) +@sa setDetailsLevel() +@sa Logger::LogLevel + +@fn void Dtk::Core::AbstractAppender::write(const QDateTime &time, Logger::LogLevel level, const char *file, int line, const char *func, const QString &category, const QString &msg) +@brief 尝试写入日志,这是由Logger对象调用的函数,用于向appender写入日志信息 +@param[in] time 时间戳 +@param[in] level 日志记录等级 +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] func 输出的函数名称 +@param[in] category 日志类别 +@param[in] msg 输出信息 +@note 该函数是线程安全的 +@sa Logger::write() +@sa detailsLevel() + +@fn void Dtk::Core::AbstractAppender::AbstractAppender::append(const QDateTime &timeStamp, Logger::LogLevel level, const char *file, int line, + const char *function, const QString &category, const QString &message) = 0 +@brief 将日志记录写到logger实例中 +@details 每次当用户试图使用`write()`函数向这个AbstractAppender实例写入消息时,都会调用这个函数。`write()`函数作为代理工作,只输出日志级别大于或等于当前`logLevel()`的消息 +@note 当你实现一个自定义的appender时,需要重载这个函数。 +@note 该函数不需要是线程安全的,因为它不会被Logger对象直接调用。`write()`函数作为代理,保护该函数不被并发调用。 +@param[in] timeStamp 时间戳 +@param[in] level 日志记录等级 +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] function 输出的函数名称 +@param[in] category 日志类别 +@param[in] message 输出信息 + +*/ diff --git a/docs/log/AbstractStringAppender.zh_CN.dox b/docs/log/AbstractStringAppender.zh_CN.dox new file mode 100644 index 0000000..e31ea79 --- /dev/null +++ b/docs/log/AbstractStringAppender.zh_CN.dox @@ -0,0 +1,60 @@ +/*! +@~chinese +@ingroup dlog +@file include/log/AbstractStringAppender.h + +@class Dtk::Core::AbstractStringAppender +@brief AbstractStringAppender类为处理纯文本格式的Appender提供了一个方便的基础日志 +@details AbstractStringAppender是AbstractAppender类的简单扩展, + 它提供了一种方便的方式来创建自定义日志应用程序, 该程序使用纯文本格式的日志. + 它有`formattedString()`保护类型(不可直接被调用)函数, 可以根据`setFormat()`设置的格式来格式化日志参数。 +@note 这个类不能直接实例化, 因为它包含从AbstractAppender类继承的纯虚函数。 +@brief 关于自定义日志输出格式的更详细描述, 请参见setFormat()函数的文档 +@sa AbstractStringAppender::setFormat() + +@fn AbstractStringAppender Dtk::Core::AbstractStringAppender::AbstractStringAppender() +@brief 构建一个新的字符串appender对象 + +@fn QString Dtk::Core::AbstractStringAppender::format() +@brief 返回当前使用的format字符串 +@details 默认记录格式为:`"%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n"` + 你可以使用setFormat()函数来设置不同的日志记录格式。 +@sa AbstractStringAppender::setFormat() +@return 返回当前使用的format字符串 + +@fn void Dtk::Core::AbstractStringAppender::setFormat(const QString &format) +@brief 设置日志格式, 以便用这个appender向日志目标写入字符串。 +@details + 对于那些使用过标准sprintf函数的开发者来说, 字符串格式非常常见。 + 日志输出格式是一个简单的QString, 带有特殊的标记(以%符号开始), 在写日志记录时将被替换成它的内部含义。 + 控制标记以百分号(%)开始, 后面是{}括号内的命令(该命令描述了将被放入日志记录而不是标记的内容)。 + 可选的字段宽度参数可以在命令后直接指定(通过括号内的冒号), 有些命令需要一个额外的格式化参数(在第二个{}括号内) + 字段宽度参数的工作原理与`QString::arg()`fieldWidth参数几乎相同(并在内部使用它), + 例如, "%{type:-7}"将被替换为消息的左边填充的调试级别("Debug")或其他东西。更详细的描述请参考Qt文档。 +@details 支持的标记: +| **标记** | **含义** | **备注** | +|:-----------:|:-----------------------------------------------------:|:-------------------------------------------------------------------:| +| %{time} | 时间戳。你可以使用标记后的第二个{}括号来指定你的自定义时间戳格式。默认格式:"HH:mm:ss.zzz" | "%{time}{dd-MM-yyyy, HH:mm}"可能被替换为 "20-9-2022, 21:24", 这取决于当前的日期和时间。 | +| %{type} | 日志级别。可能的日志级别在Logger::LogLevel枚举中显示。 | | +| %{Type} | 大写的日志级别 | | +| %{typeOne} | 一个字母的日志级别 | | +| %{TypeOne} | 一个大写字母的日志级别 | | +| %{File} | 记录日志的文件的完整源文件名(含路径), 使用 `__FILE__`预处理程序宏 | | +| %{file} | 简短的文件名(去除路径后的文件名) | | +| %{line} | 源文件中的行数。使用`__LINE__`预处理程序宏。 | | +| %{Function} | 调用`LOG_*`宏的函数的名称。使用Qt提供的`Q_FUNC_INFO`宏。 | | +| %{function} | 类似于%{Function}, 但使用 stripFunctionName 剥离了函数名。 | | +| %{message} | 日志内容 | | +| %{category} | 日志类别 | | +| %{appname} | 应用程序名称(由`QCoreApplication::applicationName()`函数返回) | | +| %{pid} | 应用程序的pid(由`QCoreApplication::applicationPid()`函数返回) | | +| %{threadid} | 线程ID | | +| %% | 转译为单`%`标记 | | + +@fn static QString Dtk::Core::AbstractStringAppender::stripFunctionName(const char *name) +@brief 剥离长函数签名(由Q_FUNC_INFO宏添加) +@details 字符串处理掉了函数的返回类型、参数和模板参数, 这对于提高日志输出的可读性是非常有用的 +@param[in] name 函数名称 +@return 剥离的函数名称 + +*/ diff --git a/docs/log/ConsoleAppender.zh_CN.dox b/docs/log/ConsoleAppender.zh_CN.dox new file mode 100644 index 0000000..49541ee --- /dev/null +++ b/docs/log/ConsoleAppender.zh_CN.dox @@ -0,0 +1,23 @@ +/*! +@~chinese +@ingroup dlog +@file include/log/ConsoleAppender.h + +@class Dtk::Core::ConsoleAppender +@brief ConsoleAppender是简单的控制台appender,将日志记录写入`std::cerr`输出流
+@details ConsoleAppender使用`[%{type:-7}] <%{function}> %{message}\n`作为默认输出格式。它类似于AbstractStringAppender,但不显示时间
+ 你可以通过使用`QT_MESSAGE_PATTERN`环境变量来修改ConsoleAppender的输出格式,而不用修改你的代码。 + 变量。如果你需要你的应用程序忽略这个环境变量,你可以调用`ConsoleAppender::ignoreEnvironmentPattern(true)` + +@fn ConsoleAppender Dtk::Core::ConsoleAppender::ConsoleAppender() +@brief 构造函数,设置默认的日志格式为`[%{type:-7}] <%{function}> %{message}\n` + +@fn virtual QString Dtk::Core::ConsoleAppender::format() +@brief 返回当前默认输出格式,可以调用父类的`setFormat()`来更改日志输出格式 +@sa AbstractStringAppender::setFormat() + +@fn void Dtk::Core::ConsoleAppender::ignoreEnvironmentPattern(bool ignore) +@brief 设置应用程序忽略环境变量来修改ConsoleAppender的输出格式,使用默认输出格式 +@sa [QT_MESSAGE_PATTERN](https://doc.qt.io/qt-5/debug.html#warning-and-debugging-messages) + +*/ diff --git a/docs/log/FileAppender.zh_CN.dox b/docs/log/FileAppender.zh_CN.dox new file mode 100644 index 0000000..a48376b --- /dev/null +++ b/docs/log/FileAppender.zh_CN.dox @@ -0,0 +1,29 @@ +/*! +@~chinese +@ingroup dlog +@file include/log/FileAppender.h + +@class Dtk::Core::FileAppender +@brief 简单的文件appender,将日志记录写到纯文本文件中 + +@fn FileAppender Dtk::Core::FileAppender::FileAppender(const QString &fileName = QString()) +@brief 构造函数,指定日志记录文件的文件名。 + +@fn QString Dtk::Core::FileAppender::fileName() const +@brief 返回由setFileName()设置的名称,或返回FileAppender构造函数传入的fileName +@sa FileAppender::setFileName() + +@fn void Dtk::Core::FileAppender::setFileName(const QString &s) +@brief 设置文件的名称。该名称可以没有路径,可以是相对路径,也可以是绝对路径 +@sa FileAppender::fileName() + +@fn qint64 Dtk::Core::FileAppender::size() +@brief 返回日志文件大小 + +@fn bool FileAppender::openFile() +@brief 打开日志记录文件 + +@fn void FileAppender::closeFile() +@brief 关闭日志记录文件 + +*/ diff --git a/docs/log/Logger.zh_CN.dox b/docs/log/Logger.zh_CN.dox new file mode 100644 index 0000000..e83a849 --- /dev/null +++ b/docs/log/Logger.zh_CN.dox @@ -0,0 +1,176 @@ +/*! +@~chinese + +@ingroup dlog +@file include/log/Logger.h + +@class Dtk::Core::Logger Logger.h +@brief 非常简单但相当强大的组件,可用于记录你的应用程序活动。 + +@enum Dtk::Core::Logger::LogLevel +@brief 日志等级 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Trace +追踪级别,可用于大部分不需要的记录,用于内部代码追踪 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Debug +调试级别,用于软件的调试。 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Info +信息级别,可用于信息记录,这可能不仅对开发者有意义 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Warning +警告,可以用来记录你的应用程序检测到的一些非致命的警告 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Error +错误,可能是一个较大问题,导致你的程序工作出错,但不至于崩溃 +@var Dtk::Core::Logger::LogLevel Dtk::Core::Logger::Fatal +致命错误,用于不可恢复的错误,在写入日志记录后立即崩溃应用程序(终止) + +@fn Logger Dtk::Core::Logger::Logger() +@brief 构建Logger的实例。 +@note 如果你只使用一个全局的logger实例,不需要手动使用这个构造函数,可以考虑使用logger宏来代替访问记录器实例 + +@fn Logger Dtk::Core::Logger::Logger(const QString &defaultCategory) +@brief 构建Logger的实例并设置Logger的默认类别 +@note 如果你只使用一个全局的logger实例,不需要手动使用这个构造函数, + 可以考虑使用logger宏来访问logger实例并调用setDefaultCategory方法 +@sa Logger::Logger() +@sa Logger::setDefaultCategory() + +@fn Logger Dtk::Core::Logger::~Logger() +@brief 析构函数 +@note 你可能不需要直接使用这个函数。记录器的全局实例将在你的QCoreApplication执行结束后自动销毁 + +@fn static Logger* Dtk::Core::Logger::globalInstance() +@brief 返回Logger的全局对象 +@note 在大多数情况下,你不应该直接使用这个函数。可以考虑使用 [logger](@ref logger) 宏来代替 +@return Logger指针 + +@fn static QString Dtk::Core::Logger::levelToString(Logger::LogLevel level) +@brief 将LogLevel枚举值转换为其字符串表示 +@sa Logger::LogLevel + +@fn static LogLevel Dtk::Core::Logger::levelFromString(const QString &str) +@brief 将LogLevel字符串表示转换为枚举值 +@note 字符串的比较是不分大小写的。如果提供的日志级别字符串不合法,则返回`Logger::Debug`的枚举值 +@sa Logger::LogLevel +@sa Logger::levelToString() + +@fn void Dtk::Core::Logger::registerAppender(AbstractAppender *appender) +@brief 注册appender来写入日志记录
+ 在写入日志的调用中(使用其中一个宏或`write()`函数),Logger遍历appender列表,并向每个appender写入日志记录。请查阅AbstractAppender文档以了解appenders的概念。 + 如果没有appender被添加到Logger中,它就会退回到记录到`std::cerr`流中。 +@param[in] appender 要在Logger中注册的Appender +@note Logger对appender拥有所有权,它将在应用程序退出时删除它。因此,appender必须在堆上创建,以防止appender被重复销毁。 +@sa Logger::registerCategoryAppender() +@sa Dtk::Core::AbstractAppender + +@fn void Dtk::Core::Logger::registerCategoryAppender(const QString &category, AbstractAppender *appender) +@brief 注册appender,将日志记录写到特定的类别中
+@details 调用这个方法,你可以将一些appender与命名的类别联系起来。 + 在调用特定类别的日志写入时(直接调用带有类别参数的`write()`,写入默认类别,或使用特殊的`dCDebug()`、`dCWarning()`等宏), + Logger只将日志信息写入注册的类别appender列表中。
+ 你可以调用`logToGlobalInstance()`将所有类别的日志信息传递给全局的Logger实例Appender(使用`registerAppender()`注册)。 + 如果没有特定名称的类别应用程序被注册到记录器上,它就会退回到记录到`std::cerr` STL流中,这两种方法都有简单的警告信息。 +@param[in] category 类别名称 +@param[in] appender 要在Logger中注册的Appender +@note Logger对appender拥有所有权,它将在应用程序退出时删除它。根据这一点,appender必须在堆上创建,以防止appender被重复销毁。 +@sa Logger::registerAppender() +@sa Logger::logToGlobalInstance() +@sa Logger::setDefaultCategory() + +@fn void Dtk::Core::Logger::logToGlobalInstance(const QString &category, bool logToGlobal = false) +@brief 将一些日志类别与全局日志实例应用者联系起来。 + 如果logToGlobal设置为 "true",所有到指定类别的Logger的日志消息也将被写入全局日志实例appenders(使用`registerAppender()`注册)
+ 默认情况下,所有到特定类别的消息都只写到特定的类别应用者 + (使用 `registerCategoryAppender()` 注册) +@param[in] category 类别名称 +@param[in] logToGlobal 是否将日志写入全局日志appenders +@sa Logger::registerAppender() +@sa Logger::globalInstance() +@sa Logger::registerCategoryAppender() + +@fn void Dtk::Core::Logger::setDefaultCategory(const QString &category); + QString defaultCategory() +@brief 设置默认的日志类别 + 所有到这个类别应用的日志信息也将被写入一般的日志实例应用(使用[registerAppender](@ref registerAppender)方法注册),反之亦然 + 特别是,任何对dDebug()宏的调用都将被视为类别日志 + 所以你不需要用dCDebug()宏来指定类别名称 + 要取消默认的类别,传递一个空字符串作为参数 +@param[in] category 类别名称 +@note "category "格式标记将被设置为所有这些消息的类别名称 +@sa Dtk::Core::AbstractStringAppender::setFormat() +@sa Logger::defaultCategory() +@sa Logger::registerCategoryAppender() +@sa Logger::logToGlobalInstance() + +@fn QString Dtk::Core::Logger::defaultCategory() +@brief 返回默认的日志类别名称 +@sa Logger::setDefaultCategory() + +@fn void Dtk::Core::Logger::write(const QDateTime &time, LogLevel level, + const char *file, int line,const char *func, + const char *category, const QString &msg) +@brief 写入日志记录。 + 将带有所提供参数的日志记录写给所有注册的应用 +@param[in] time 时间戳 +@param[in] level 日志记录等级 +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] func 输出的函数名称 +@param[in] category 日志类别 +@param[in] msg 输出信息 +@note 使用`Logger::Fatal`日志级别记录日志记录将导致调用STL `abort()`函数, + 这将中断你的软件的运行并Core dump +@sa Logger::LogLevel +@sa Dtk::Core::AbstractAppender + +@fn void Dtk::Core::Logger::write(LogLevel level, const char *file, int line, + const char *func, const char *category, const QString &msg) +@brief 这是为方便而提供的重载函数。它的行为与同名函数类似,此函数无需传入time参数 +@note 这个函数使用了`QDateTime::currentDateTime()`用获得的当前时间戳 +@sa Logger::write(const QDateTime &time, LogLevel level, + const char *file, int line,const char *func, + const char *category, const QString &msg) +@param[in] level 日志记录等级 +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] func 输出的函数名称 +@param[in] category 日志类别 +@param[in] msg 输出信息 + +@fn QDebug Dtk::Core::Logger::write(LogLevel level, const char *file, + int line,const char *func, const char *category) +@brief 这是为方便而提供的重载函数。它的行为与同名函数类似,此函数无需传入message参数 +@details 这个函数不接受任何日志信息作为参数。它返回的是可以使用流函数写入的`QDebug`对象
+ 例如,你可能想写: + @code + dDebug() << "This is the size" << size << "of the element" << elementName; + @endcode + 而不是写为: + @code + dDebug(QString(QLatin1String("This is the size %1x%2 of the element %3")).arg(size.x()).arg(size.y()).arg(elementName)); + @endcode + 这样会更优雅一些
+ 请考虑阅读Qt参考文档,了解QDebug类的使用语法 +@note 这个重载肯定是最好用的一个重载,但是代价是它会比其他的重载更为慢 +@sa Logger::write(const QDateTime &time, LogLevel level, + const char *file, int line,const char *func, + const char *category, const QString &msg) +@param[in] level 日志记录等级 +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] func 输出的函数名称 +@param[in] category 日志类别 + +@fn void Dtk::Core::Logger:: writeAssert(const char *file, int line, + const char *func, const char *condition) +@brief 写入断言 +@details 这个函数使用write()函数来写断言记录
+ 断言记录总是使用`Logger::Fatal`日志级别来写,这将导致程序的中止和核心转储(core dump)的生成(如果支持) + 写入appenders的信息与传入参数相同,前缀为 `ASSERT:` +@param[in] file 目标文件名 +@param[in] line 要输出的行数 +@param[in] func 输出的函数名称 +@note 不建议直接调用这个函数,你可以直接调用`LOG_ASSERT`宏,它将为这个函数提供所有需要的信息 +@sa Logger::write(const QDateTime &time, LogLevel level, + const char *file, int line,const char *func, + const char *category, const QString &msg) + +*/ diff --git a/docs/log/RollingFileAppender.zh_CN.dox b/docs/log/RollingFileAppender.zh_CN.dox new file mode 100644 index 0000000..8393715 --- /dev/null +++ b/docs/log/RollingFileAppender.zh_CN.dox @@ -0,0 +1,64 @@ +/*! +@~chinese +@ingroup dlog +@file include/log/RollingFileAppender.h + +@class Dtk::Core::RollingFileAppender +@brief RollingFileAppender类扩展了FileAppender,使日志文件在按照用户指定的频率进行滚动 +@details + 该类是基于`Log4Qt.DailyRollingFileAppender`类[Log4Qt](http://log4qt.sourceforge.net/) + 并具有相同的日期模式格式
+ 例如,如果fileName设置为`/foo/bar`,DatePattern设置为每日滚动('.yyy-MM-dd'.log'),在2022-05-28的午夜。 + 日志文件`/foo/bar.log`将被复制到`/foo/bar.2022-05-28.log`,2022-05-29的日志将在`/foo/bar`中继续,直到第二天滚动
+ logFilesLimit参数用于在滚动期间自动删除目录中最旧的日志文件。 + (所以在任何时候,目录中都不会有超过logFilesLimit的最新日志文件存在) + +@enum Dtk::Core::RollingFileAppender::DatePattern +@brief 日志频率 +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::MinutelyRollover +@brief 每分钟的日期模式字符串是`.yyyy-MM-dd-hh-mm` +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::HourlyRollover +@brief 每小时的日期模式字符串是 `.yyyy-MM-dd-hh` +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::HalfDailyRollover +@brief 每半天的日期模式字符串是`.yyyy-MM-dd-a` +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::DailyRollover +@brief 每天的日期模式字符串是`.yyyy-MM-dd` +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::WeeklyRollover +@brief 每周的日期模式字符串是`.'yyyy-ww` +@var Dtk::Core::RollingFileAppender::DatePattern Dtk::Core::RollingFileAppender::MonthlyRollover +@brief 每月的日期模式字符串是`.yyyy-MM` + +@fn RollingFileAppender Dtk::Core::RollingFileAppender::RollingFileAppender() +@brief 构造函数,默认限制日志文件个数是0,默认日志文件大小是1024*1024*20=20m + +@fn DatePattern Dtk::Core::RollingFileAppender::datePattern() +@brief 返回当前的滚动更新频率 +@sa RollingFileAppender::DatePattern + +@fn void Dtk::Core::RollingFileAppender::setDatePattern(DatePattern datePattern) +@brief 设置日志滚动频率 +@sa RollingFileAppender::DatePattern + +@fn void Dtk::Core::RollingFileAppender::setDatePattern(const QString &datePattern) +@brief 此重载是为了方便使用,可以传入一个滚动频率字符串 +@sa RollingFileAppender::DatePattern +@sa RollingFileAppender::setDatePattern(DatePattern datePattern) + +@fn QString Dtk::Core::RollingFileAppender::datePatternString() +@brief 以字符串形式,返回当前滚动频率 + +@fn void Dtk::Core::RollingFileAppender::setLogFilesLimit(int limit) +@brief 设置日志文件数量上限,最旧的文件会被滚动覆盖 + +@fn int Dtk::Core::RollingFileAppender::logFilesLimit() +@brief 返回设置的日志文件数量上限 +@sa RollingFileAppender::setLogFilesLimit() + +@fn int Dtk::Core::RollingFileAppender::setLogSizeLimit(int qint64) +@brief 设置日志文件单个文件大小上限 + +@fn qint64 Dtk::Core::RollingFileAppender::logSizeLimit() +@brief 返回设置的日志文件单个文件大小上限 +@sa RollingFileAppender::setLogSizeLimit(int qint64) + +*/ diff --git a/docs/log/dlogmanager.zh_CN.dox b/docs/log/dlogmanager.zh_CN.dox new file mode 100644 index 0000000..eba84cb --- /dev/null +++ b/docs/log/dlogmanager.zh_CN.dox @@ -0,0 +1,41 @@ +/*! +@~chinese + +@ingroup dlog +@file include/log/LogManager.h +@class Dtk::Core::DLogManager +@brief DLogManager是dtk日志管理类,提供对日志的基础设置 +@details 使用此类可以很方便的为自己的dtk程序加上日志,一般情况下应用如果需要写入日志只需要调用此类 +调用相应的注册方法设置存储路径相关信息即可 + +@fn static void Dtk::Core::DLogManager::registerConsoleAppender() +@brief 注册默认的控制台记录器 + +@fn static void Dtk::Core::DLogManager::registerFileAppender() +@brief 注册默认的文件记录器,默认的文件记录器类型为RollingFileAppender. +@note 输出日志默认文件位置为`~/.cache//.log`如果获取 $HOME 环境变量失败将不写日志. +如果在创建程序的时候没有指定这两个name,如果未设置organizationName,则是 `~/.cache//.log` +如果applicationName没有设置, 会fallback到进程二进制文件名 +@sa DLogManager::setlogFilePath() + +@fn static void Dtk::Core::DLogManager::registerJournaldAppender() +@brief 注册默认的journald记录器 +@note 此方法只在linux下有效 +@detials 默认输出文件位置为`/var/log/journal/.journal`,前提是此目录存在且有写权限, +如果目录不存在,systemd将不会自动创建此目录,并将日志写入到`/run/log/journal/.journal`中,此目录不支持持久化存储, +将在下次重启后丢失。 +@note 查看日志可用`journalctl`命令,查看详细信息可用`journalctl -o verbose`命令,也可以使用deepin 日志查看器查看 + +@fn static QString Dtk::Core::DLogManager::getlogFilePath() +@brief 获取当前的日志存储路径,包括文件名 + +@fn static void Dtk::Core::DLogManager::setlogFilePath(const QString &logFilePath) +@brief 设置log文件路径。如果文件存在且不是log文件类型(比如文件夹)会导致设置无效并输出一条警告。 +@note 注意,此文件路径为包括具体文件名的绝对路径。需要此文件不存在或者存在且为有效类型(xxx.log),一般情况下无需手动指定路径。 + +@fn static void Dtk::Core::DLogManager::setLogFormat(const QString &format) +@brief 设置日志的格式,如果没有设置格式 +@details 默认的格式为:`"%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n"` +@sa Dtk::Core::AbstractStringAppender::format() + +*/ diff --git a/docs/log/index.zh_CN.md b/docs/log/index.zh_CN.md new file mode 100644 index 0000000..b0123f2 --- /dev/null +++ b/docs/log/index.zh_CN.md @@ -0,0 +1,84 @@ +@page DLog dlog--DTK日志组件 + +# Dlog:DTK日志组件 + +## 简介 + +DTK日志组件,提供了日志的输出、日志级别的设置、日志文件的设置等功能。为了简化日志的使用,我们提供了两种使用方式,一种是使用宏,另一种是使用类。 +但是更为建议使用宏的方式进行使用。因为使用宏可以输出更多的信息,比如文件名、函数名、行号等。 + +## 使用 + +### 宏 + +DTK日志组件提供了一系列的宏,用于输出日志。这些宏的定义在dloggerdefs.h中 +如果需要使用宏,则需要在你的代码中包含`DLog`文件。 +@note DTK更推荐使用CPP标准引入头文件的方式,即使用`#include `的方式引入头文件,而不是使用`#include "xxxxx.h"`的方式引入头文件。 + +示例代码如下: + +```cpp +#include +#include +DCORE_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); +#ifdef Q_OS_LINUX + DLogManager::registerJournalAppender(); +#endif + DLogManager::registerConsoleAppender(); + dDebug() << "this is a debug message"; + return app.exec(); +} +``` + +上述代码中,我们使用了dDebug()宏,用于输出一条debug级别的日志。在输出日志时,我们可以使用`<<`运算符,将多个变量输出到日志中。 +注意,registerJournalAppender()仅在Linux平台下有效,因为journal仅在Linux平台下有效。而registerConsoleAppender()则是在所有平台下都有效。 + +### 类 + +使用类的方式需要先创建一个logger对象,然后使用logger对象的方法来输出日志,具体请参见logger文档 + +## 注意事项 + +### 日志级别 + +DTK使用的日志级别与Qt的日志级别一致,分别为:Trace、Debug、Info、Warning、Error、Fatal。其中Trace是最低级别,Fatal是最高级别。 +与之不同的是journal的日志级别和DTK的日志级别不一致,journal的日志级别分别为:emergency、alert、critical、error、warning、notice、info、debug。 +这是因为journal的日志级别是从syslog中继承过来的,而syslog的日志级别是从BSD的syslog中继承过来的。而DTK的日志级别是从Qt的日志级别中继承过来的。 +下表是DTK日志级别和journal日志级别的对应关系 +| DTK值 | 序号 | 含义 | syslog值 | syslog序号 | +|---------|----|-------------------------------------|-------------|----------| +| dTrace | 0 | 追踪级别,可用于大部分不需要的记录,用于内部代码追踪 | 无 | | +| dDebug | 1 | 调试级别,用于软件的调试。 | LOG_DEBUG | 7 | +| dInfo | 2 | 信息级别,可用于信息记录,这可能不仅对开发者有意义 | LOG_INFO | 6 | +| dWarning | 3 | 警告,可以用来记录你的应用程序检测到的一些非致命的警告 | LOG_WARNING | 4 | +| dError | 4 | 错误,可能是一个较大问题,导致你的程序工作出错,但不至于崩溃 | LOG_ERR | 3 | +| dFatal | 5 | 致命错误,用于不可恢复的错误,在写入日志记录后立即崩溃应用程序(终止) | LOG_EMERG | 0 | +| | | | LOG_ALERT | 1 | +| | | | LOG_CRIT | 2 | +| | | | LOG_NOTICE | 6 | + +### 日志文件 + +如果你选择使用journal作为日志输出,那么你需要在系统中安装systemd(一般的linux发行版都会自带systemd)。并且需要确保`/var/log/journal/` +目录的存在,否则journal会将日志写入到`/run/log/journal/`目录中。 + +如果你选择使用控制台作为日志输出,那么不会生成日志文件。 + +如果你选择使用文件作为日志输出,那么你需要确保你的日志文件所在的目录存在,否则会导致日志文件无法创建。 + +### 日志格式 + +如果你选择使用journal作为日志输出,且使用宏的方式进行日志输出,那么日志的格式为: +`[时间] [进程ID] [线程ID] [日志级别] [文件名:行号] [函数名] [日志内容]`,你仅需要关注日志内容即可。其他的信息都是journal自动添加的。 + + +@defgroup dlog +@brief DTK日志组件 +@details + DTK日志组件,提供了日志的输出、日志级别的设置、日志文件的设置等功能。 + 对于DTK日志组件,我们提供了两种使用方式,一种是使用宏,另一种是使用类。 + 但是更为建议使用宏的方式进行使用 diff --git a/docs/settings/backend/dsettingsdconfigbackend.zh_CN.dox b/docs/settings/backend/dsettingsdconfigbackend.zh_CN.dox new file mode 100644 index 0000000..7939602 --- /dev/null +++ b/docs/settings/backend/dsettingsdconfigbackend.zh_CN.dox @@ -0,0 +1,32 @@ +/*! +@~chinese +@file include/settings/backend/dsettingsdconfigbackend.h +@ingroup dsettings + +@class Dtk::Core::DSettingsDConfigBackend dsettingsdconfigbackend.h +@brief 配置存储到DConfig + +@fn Dtk::Core::DSettingsDConfigBackend::DSettingsDConfigBackend(const QString &name, const QString &subpath = QString(), QObject *parent = nullptr) +@brief DSettingsDConfigBackend构造函数,使用DConfig为配置文件名,保存数据到配置文件。 +@param[in] name 配置文件名 +@param[in] subpath 配置文件名的子目录 +@param[in] parent 父对象 + +@fn virtual QStringList Dtk::Core::DSettingsDConfigBackend::keys() const +@brief 返回Dconfig的全部键值 +@return + +@fn virtual QVariant Dtk::Core::DSettingsDConfigBackend::getOption(const QString &key) const +@brief 从DConfig获取键值 +@param[in] key +@return + +@fn virtual void QVariant Dtk::Core::DSettingsDConfigBackend::doSetOption(const QString &key, const QVariant &value) +@brief 给DConfig设置键值 +@param[in] key +@param[in] value + +@fn virtual void Dtk::Core::DSettingsDConfigBackend::doSync() +@brief 触发DSettings将选项值保存到DConfig + +*/ \ No newline at end of file diff --git a/docs/settings/backend/gsettingsbackend.zh_CN.dox b/docs/settings/backend/gsettingsbackend.zh_CN.dox new file mode 100644 index 0000000..0e78bfc --- /dev/null +++ b/docs/settings/backend/gsettingsbackend.zh_CN.dox @@ -0,0 +1,27 @@ +/*! +@~chinese +@file include/settings/backend/gsettingsbackend.h +@ingroup dsettings + +@class Dtk::Core::GSettingsBackend gsettingsbackend.h +@brief DSettings的存储后端使用gsettings +@details 你可以从libdtkcore-bin中找到此工具, 使用/usr/lib/x86_64-linux-gnu/libdtk-/DCore/bin/dtk-settings -h 获取帮助 + +@fn Dtk::Core::GSettingsBackend::GSettingsBackend(DSettings *settings, QObject *parent = nullptr) +@brief GSettingsBackend构造函数 + +@fn virtual QStringList Dtk::Core::GSettingsBackend::keys() const +@brief gsettings的全部键值 +@return 返回gsettings的全部键值 + +@fn virtual QVariant Dtk::Core::GSettingsBackend::getOption(const QString &key) const +@brief 根据`key`获取值 +@return 返回键对应的值 + +@fn virtual void Dtk::Core::GSettingsBackend::doSetOption(const QString &key, const QVariant &value) +@brief 设置`key`对应的值 + +@fn virtual void Dtk::Core::GSettingsBackend::doSync() +@brief 触发DSettings将选项同步到存储 + +*/ \ No newline at end of file diff --git a/docs/settings/backend/qsettingbackend.zh_CN.dox b/docs/settings/backend/qsettingbackend.zh_CN.dox new file mode 100644 index 0000000..6c26f22 --- /dev/null +++ b/docs/settings/backend/qsettingbackend.zh_CN.dox @@ -0,0 +1,31 @@ +/*! +@~chinese +@file include/settings/backend/qsettingbackend.h +@ingroup dsettings + +@class Dtk::Core::QSettingBackend qsettingbackend.h +@brief 存储DSettings到QSettings + +@fn Dtk::Core::QSettingBackend::QSettingBackend(const QString &filepath, QObject *parent = 0) +@brief QSettingBackend构造函数,使用QSettings::NativeFormat将数据保存到指定路径。 +@param[in] filepath 存储数据的路径 +@param[in] parent 父对象 + +@fn virtual QStringList Dtk::Core::QSettingBackend::keys() const +@brief QSettings的全部键值 +@return 返回QSettings的全部键值 + +@fn virtual QVariant Dtk::Core::QSettingBackend::getOption(const QString &key) const +@brief 根据`key`获取值 +@param[in] key 配置项名称 +@return 返回键对应的值 + +@fn virtual void Dtk::Core::QSettingBackend::doSetOption(const QString &key, const QVariant &value) +@brief 设置`key`对应的值 +@param[in] key 配置项名称 +@param[in] value 需要设置的值 + +@fn virtual void Dtk::Core::QSettingBackend::doSync() +@brief 触发DSettings选项值保存到QSettings + +*/ \ No newline at end of file diff --git a/docs/settings/dsettings.zh_CN.dox b/docs/settings/dsettings.zh_CN.dox new file mode 100644 index 0000000..c7a3b04 --- /dev/null +++ b/docs/settings/dsettings.zh_CN.dox @@ -0,0 +1,230 @@ +/*! +@~chinese +@file include/settings/dsettings.h +@ingroup dsettings +@class Dtk::Core::DSettingsBackend dsettings.h +@brief DSettingsBackend是一个配置存储类的接口 +@details 简单的例子: +@code +{ + "groups": [{ + "key": "base", + "name": "Basic settings", + "groups": [{ + "key": "open_action", + "name": "Open Action", + "options": [{ + "key": "alway_open_on_new", + "type": "checkbox", + "text": "Always Open On New Windows", + "default": true + }, + { + "key": "open_file_action", + "name": "Open File:", + "type": "combobox", + "default": "" + } + ] + }, + { + "key": "new_tab_windows", + "name": "New Tab & Window", + "options": [{ + "key": "new_window_path", + "name": "New Window Open:", + "type": "combobox", + "default": "" + }, + { + "key": "new_tab_path", + "name": "New Tab Open:", + "type": "combobox", + "default": "" + } + ] + } + ] + }] +} +@endcode + +读取/设置其值的示例如下: +@code + // 初始化一个存储后端 + QTemporaryFile tmpFile; + tmpFile.open(); + auto backend = new Dtk::Core::QSettingBackend(tmpFile.fileName()); + + // 从json中初始化配置 + auto settings = Dtk::Core::DSettings::fromJsonFile(":/resources/data/dfm-settings.json"); + settings->setBackend(backend); + + // 读取配置 + auto opt = settings->option("base.new_tab_windows.new_window_path"); + qDebug() << opt->value(); + + // 修改配置 + opt->setValue("Test") + qDebug() << opt->value(); +@endcode +@sa Dtk::Core::DSettingsOption +@sa Dtk::Core::DSettingsGroup +@sa Dtk::Core::DSettingsBackend +@sa Dtk::Widget::DSettingsWidgetFactory +@sa Dtk::Widget::DSettingsDialog + +@fn Dtk::Core::DSettingsBackend::DSettingsBackend(QObject *parent = Q_NULLPTR) +@brief DSettingsBackend构造函数 + +@fn virtual QStringList DSettingsBackend::keys() const = 0; +@brief 返回全部键值 + +@fn virtual QVariant DSettingsBackend::getOption(const QString &key) const = 0; +@brief 获取 `key` 对应的值 + +@fn virtual void DSettingsBackend::doSync() = 0; +@brief 开始进行同步 + +@fn virtual void DSettingsBackend::doSetOption(const QString &key, const QVariant &value) = 0; +@brief 设置`key`对应的值,并使用存储后端进行存储。 + +@fn void DSettingsBackend::optionChanged(const QString &key, const QVariant &value); +@brief DSettingsOption的值发生变化时发出的信号。 +@details `key` 发生改变的 option 键,`value`对应键的值。 + +@fn void DSettingsBackend::sync(); +@brief 私有信号,请勿使用。 + +@fn void DSettingsBackend::setOption(const QString &key, const QVariant &value); +@brief 私有信号,请勿使用。 + +@class Dtk::Core::DSettings dsettings.h +@brief DSettings是设计上为Dtk的应用程序提供统一的配置存储以及界面生成工具的基础库。 +@details DSetting使用json作为应用配置程序的描述文件。简单来说,应用查询的配置分为组/键值二个基础层级, +对于一个标准的Dtk配置控件,一般只包含组/子组/键值三个层级,对于超过三个层级的键值,可以通过 +DSettings的API接口进行读取和写入,但是不能在标准的DSettingsDialogs上显示出来。 + +一个简单的配置文件如下: +@code +{ + "groups": [{ + "key": "base", + "name": "Basic settings", + "groups": [{ + "key": "open_action", + "name": "Open Action", + "options": [{ + "key": "alway_open_on_new", + "type": "checkbox", + "text": "Always Open On New Windows", + "default": true + }, + { + "key": "open_file_action", + "name": "Open File:", + "type": "combobox", + "default": "" + } + ] + }, + { + "key": "new_tab_windows", + "name": "New Tab & Window", + "options": [{ + "key": "new_window_path", + "name": "New Window Open:", + "type": "combobox", + "default": "" + }, + { + "key": "new_tab_path", + "name": "New Tab Open:", + "type": "combobox", + "default": "" + } + ] + } + ] + }] +} +@endcode + +该组中包含一个base的root组,两个子组: open_action/new_tab_windows,每个子组有包含若干选项。 +对于"New Window Open:"这个配置,其完整的访问id为base.new_tab_windows.new_window_path。 + +读取/设置其值的示例如下: +@code + // 初始化一个存储后端 + QTemporaryFile tmpFile; + tmpFile.open(); + auto backend = new Dtk::Core::QSettingBackend(tmpFile.fileName()); + + // 从json中初始化配置 + auto settings = Dtk::Core::DSettings::fromJsonFile(":/resources/data/dfm-settings.json"); + settings->setBackend(backend); + + // 读取配置 + auto opt = settings->option("base.new_tab_windows.new_window_path"); + qDebug() << opt->value(); + + // 修改配置 + opt->setValue("Test") + qDebug() << opt->value(); +@endcode +@sa Dtk::Core::DSettingsOption +@sa Dtk::Core::DSettingsGroup +@sa Dtk::Core::DSettingsBackend +@sa Dtk::Widget::DSettingsWidgetFactory +@sa Dtk::Widget::DSettingsDialog + +@fn Dtk::Core::DSettings::DSettings(QObject *parent = Q_NULLPTR) +@brief DSettings构造函数 + +@fn void Dtk::Core::DSettings::setBackend(DSettingsBackend *backend = nullptr) +@brief 设置存储后端 + +@fn static QPointer Dtk::Core::DSettings::fromJson(const QByteArray &json) +@brief 从 json 中获取 DSettings,返回的数据使用之后需要自己手动释放。 + +@fn static QPointer Dtk::Core::DSettings::fromJsonFile(const QString &filepath) +@brief 从 json 文件中获取 DSetting。 + +@fn QJsonObject Dtk::Core::DSettings::meta() const +@brief 返回JSON对象 + +@fn QStringList Dtk::Core::DSettings::keys() const +@brief 返回全部键值 + +@fn QList > Dtk::Core::DSettings::options() const +@brief 返回全部 `key` 的值 + +@fn QPointer Dtk::Core::DSettings::option(const QString &key) const +@brief 获取 `key` 对应的值 + +@fn QVariant Dtk::Core::DSettings::value(const QString &key) const +@brief 获取 `key` 对应的值 + +@fn QStringList Dtk::Core::DSettings::groupKeys() const +@brief 返回子组全部键值 + +@fn QList > Dtk::Core::DSettings::groups() const +@brief 返回子组全部 `key` 的值 + +@fn QPointer Dtk::Core::DSettings::group(const QString &key) const +@brief DSettings::group将递归找到子组 +@return + +@fn QVariant Dtk::Core::DSettings::getOption(const QString &key) const +@brief 获取 `key` 对应的值 + +@fn void Dtk::Core::DSettings::sync() +@brief 开始进行同步 + +@fn void Dtk::Core::DSettings::setOption(const QString &key, const QVariant &value) +@brief 设置键值 + +@fn void Dtk::Core::DSettings::reset() +@brief 重置键值 + +*/ diff --git a/docs/settings/dsettingsgroup.zh_CN.dox b/docs/settings/dsettingsgroup.zh_CN.dox new file mode 100644 index 0000000..ef72e45 --- /dev/null +++ b/docs/settings/dsettingsgroup.zh_CN.dox @@ -0,0 +1,60 @@ +/*! +@~chinese +@file include/settings/dsettingsgroup.h +@ingroup dsettings + +@class Dtk::Core::DSettingsGroup dsettingsgroup.h +@brief 一组DSettings选项的集合,也可以包含子组。 + +@fn Dtk::Core::DSettingsGroup::DSettingsGroup(QObject *parent = Q_NULLPTR) +@brief DSettingsGroup构造函数 + +@fn QPointer Dtk::Core::DSettingsGroup::parentGroup() const +@brief 获取当前组的父组 +@return + +@fn void Dtk::Core::DSettingsGroup::setParentGroup(QPointer< DSettingsGroup > parentGroup) +@brief 设置当前组的父组为 `parentGroup` + +@fn QString Dtk::Core::DSettingsGroup::key() const +@brief 返回这个组的键,会包含全部的父组的键 +@return 返回这个组的键,会包含全部的父组的键 + +@fn QString Dtk::Core::DSettingsGroup::name() const +@brief 返回这个组名称,它可能被翻译。 +@return 返回这个组名称 + +@fn bool Dtk::Core::DSettingsGroup::isHidden() const +@brief 检查这个选项组是否会在界面上显示 +@return true 表示则这个选项组会显示出来 + +@fn QPointer Dtk::Core::DSettingsGroup::childGroup(const QString &groupKey) const +@brief 返回给定键在选项组中对应的子组。`groupKey`子组的键 +@return 返回子组的指针 + +@fn QPointer Dtk::Core::DSettingsGroup::option(const QString &key) const +@brief 根据键值获取选项。`key`选项的完整键 +@return 返回对应键值选项指针 + +@fn QList > Dtk::Core::DSettingsGroup::childGroups() const +@brief 列出组下面所有的直接子组。 +@return 返回所有子组指针列表 + +@fn QList > Dtk::Core::DSettingsGroup::childOptions() const +@brief 列出组下面所有的直接选项。 +@return 返回所有子选项指针列表 + +@fn QList > Dtk::Core::DSettingsGroup::options() const +@brief 列出组下面所有的选项。 +@return 返回所有选项指针列表 + +@fn QPointer Dtk::Core::DSettingsGroup::fromJson(const QString &prefixKey, const QJsonObject &group) +@brief 将json对象转化为DSettingsGroup。`prefixKey` 组键值前缀 `group` 待反序列化的json对象 +@return 返回解析json后的组指针 +@sa QPointer Dtk::Core::DSettingsOption + +@fn void Dtk::Core::DSettingsGroup::parseJson(const QString &prefixKey, const QJsonObject &group) +@brief 将json对象转化为DSettingsGroup。`prefixKey` 组键值前缀 `group` 待反序列化的json对象 +@sa QPointer Dtk::Core::DSettingsGroup::fromJson(const QString &prefixKey, const QJsonObject &json) + +*/ diff --git a/docs/settings/dsettingsoption.zh_CN.dox b/docs/settings/dsettingsoption.zh_CN.dox new file mode 100644 index 0000000..3fcbbc1 --- /dev/null +++ b/docs/settings/dsettingsoption.zh_CN.dox @@ -0,0 +1,87 @@ +/*! +@~chinese +@file include/settings/dsettingsoption.h +@ingroup dsettings + +@class Dtk::Core::DSettingsOption dsettingsoption.h +@brief DSettingsOption是DSettings的基本单元,用于存放一对键-值数据。 + +@fn Dtk::Core::DSettingsOption::DSettingsOption(QObject *parent = Q_NULLPTR) +@brief DSettingsOption构造函数 + +@fn QPointer Dtk::Core::DSettingsOption::parentGroup() const +@brief 当前选项的直接上级组 +@return 返回当前选项的直接上级组 + +@fn void Dtk::Core::DSettingsOption::setParentGroup(QPointer parentGroup) +@brief 修改当前选项的上级组 +@param[in] parentGroup 上级组 + +@fn QString Dtk::Core::DSettingsOption::key() const +@brief 当前选项的键值 +@return 返回当前选项的键值 + +@fn QString Dtk::Core::DSettingsOption::name() const +@brief 当前选项的名称 +@return 返回当前选项的名称 + +@fn bool Dtk::Core::DSettingsOption::canReset() const +@brief 选项是否可以重置,如果可以重置,在调用reset方法后,选项的值会变成初始值。 +@return 如果可以重置则为true + +@fn QVariant Dtk::Core::DSettingsOption::defaultValue() const +@brief 选项的默认值 +@return 返回选项的默认值 + +@fn QVariant Dtk::Core::DSettingsOption::value() const +@brief 选项的当前值 +@return 返回选项的当前值 + +@fn QVariant Dtk::Core::DSettingsOption::data(const QString &dataType) const +@param[in] dataType 数据类型 +@brief 选项的附件data,用于未选项设置一些额外的辅助属性。 +@return 数据类型对应的数据. +@sa QObject::property +@sa Dtk::Core::DSettingsOption::setData + +@fn QString Dtk::Core::DSettingsOption::viewType() const +@brief 选项的控件类型 +@return 返回选项的控件类型 +@sa Dtk::Widget::DSettingsWidgetFactory + +@fn bool Dtk::Core::DSettingsOption::isHidden() const +@brief 检查选项是否会在界面上显示 +@return 如果显示则返回true,否则返回false。 + +@fn static QPointer Dtk::Core::DSettingsOption::fromJson(const QString &prefixKey, const QJsonObject &json) +@brief 从json对象中反序列化出一个选项对象 +@param[in] prefixKey 选项的前缀 +@param[in] json 待反序列化的json对象 +@return 返回解析完成后的 `option` 数据 + +@fn void Dtk::Core::DSettingsOption::setValue(QVariant value) +@brief 设置选项的当前值. +@param[in] value 选项的当前值 + +@fn void Dtk::Core::DSettingsOption::setData(const QString &dataType, QVariant value) +@brief 为选项添加自定义属性 +@param[in] dataType 选项的扎属性数据id,对每个选项必须唯一 +@param[in] value 选项id对应的值 +@sa Dtk::Core::DSettingsOption::data + +@fn void Dtk::Core::DSettingsOption::parseJson(const QString &prefixKey, const QJsonObject &option) +@brief 从json对象中反序列化,并设置自身的值。 +@param[in] prefixKey 选项的前缀 +@param[in] option 待反序列化的json对象 +@sa QPointer Dtk::Core::DSettingsOption::fromJson(const QString &prefixKey, const QJsonObject &json) + +@fn void Dtk::Core::DSettingsOption::valueChanged(QVariant value) +@brief 选项的数据变化时发出改信息 +@param[in] value 发生改变的数据 + +@fn void Dtk::Core::DSettingsOption::dataChanged(const QString &dataType, QVariant value); +@brief 选项的附件的额外数据变化时发出改信息,可以看作这个值的属性发生变化。 +@param[in] dataType 改变的数据类型 +@param[in] value 发生改变的数据 + +*/ \ No newline at end of file diff --git a/docs/settings/index.zh_CN.md b/docs/settings/index.zh_CN.md new file mode 100644 index 0000000..39695b6 --- /dev/null +++ b/docs/settings/index.zh_CN.md @@ -0,0 +1,166 @@ +@page dsettings dsettings--dtk设置工具组件 + +# DSettings + +## DSettings:dtk设置组件 + +[dsettings.h 详细文档](dsettings_8h.html) + +项目目录结构如下: + +```bash +├── CMakeLists.txt +├── data +│ └── settings.json +├── data.qrc +└── main.cpp +``` + +CMakeLists.txt: + +```cmake +cmake_minimum_required(VERSION 3.1.0) # 指定cmake最低版本 + +project(dsetting-example VERSION 1.0.0 LANGUAGES CXX)# 指定项目名称, 版本, 语言 cxx就是c++ + +set(CMAKE_CXX_STANDARD 11) # 指定c++标准 +set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定c++标准要求,至少为11以上 + +set(CMAKE_AUTORCC ON) # support qt resource file # 支持qt资源文件 + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 支持 clangd + +if (CMAKE_VERSION VERSION_LESS "3.7.0") # 如果cmake版本小于3.7.0 + set(CMAKE_INCLUDE_CURRENT_DIR ON) # 设置包含当前目录 +endif() + +find_package(DtkCore REQUIRED) # 寻找Dtk组件Core + +add_executable(${PROJECT_NAME} # 生成可执行文件 + main.cpp + data.qrc +) + +target_link_libraries(${PROJECT_NAME} PRIVATE # 添加需要链接的共享库 + Dtk::Core +) +``` + +settings.json: + +```json +{ + "groups": [{ + "key": "base", + "name": "Basic settings", + "groups": [{ + "key": "open_action", + "name": "Open Action", + "options": [{ + "key": "alway_open_on_new", + "type": "checkbox", + "text": "Always Open On New Windows", + "default": true + }, + { + "key": "open_file_action", + "name": "Open File:", + "type": "combobox", + "default": "" + } + ] + }, + { + "key": "new_tab_windows", + "name": "New Tab & Window", + "options": [{ + "key": "new_window_path", + "name": "New Window Open:", + "type": "combobox", + "default": "" + }, + { + "key": "new_tab_path", + "name": "New Tab Open:", + "type": "combobox", + "default": "" + } + ] + } + ] + }] +} +``` + +data.qrc + +```xml + + + data/settings.json + + +``` + +main.cpp + +```cpp +#include +#include +#include +#include +#include +#include +#include + +DCORE_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + // 初始化一个存储后端 + QTemporaryFile tmpFile; + tmpFile.open(); + QPointer backend = new QSettingBackend(tmpFile.fileName()); + + // 从json中初始化配置 + QPointer settings = DSettings::fromJsonFile(":/data/settings.json"); + settings->setBackend(backend); + + // 读取配置 + // 该组中包含一个base的root组,两个子组: open_action/new_tab_windows,每个子组有包含若干选项。 + // 对于"New Window Open:"这个配置,其完整的访问id为base.new_tab_windows.new_window_path。 + QPointer opt = settings->option("base.new_tab_windows.new_window_path"); + qDebug() << opt->value(); + + // 修改配置 + opt->setValue("Test"); + qDebug() << opt->value(); + + // 获取所有keys + QStringList keys = settings->keys(); + qDebug() << keys; + + // base.open_action对应的组 + QPointer group = settings->group("base.open_action"); + qDebug() << group->key(); + + return a.exec(); +} +``` + +编译运行: + +```bash +cmake -Bbuild +cmake --build build +./build/dsetting-example +``` + +运行结果如下图: + +![img](/docs/src/dsettings.png) + +@defgroup dsettings +@brief dtk设置组件 diff --git a/docs/src/dciicon-tree.png b/docs/src/dciicon-tree.png new file mode 100644 index 0000000000000000000000000000000000000000..72ff777d79b554cd214d5eaae376571300fa0b9d GIT binary patch literal 58801 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 z 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 BZKVJJ literal 0 HcmV?d00001 diff --git a/docs/src/dconfig_example1.png b/docs/src/dconfig_example1.png new file mode 100644 index 0000000000000000000000000000000000000000..3491a96ec850d79d431cfcbd83a6c77aca69ab3b GIT binary patch literal 60295 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 A)c^nh literal 0 HcmV?d00001 diff --git a/docs/src/dconfigfile_example1.png b/docs/src/dconfigfile_example1.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d43ef97f463cd61ca708cef42952115e9eba07 GIT binary patch literal 52955 zcmV)eK&HQmP)*_sm z1Rw+iBua!;_bS_<>=^`q)k|c2;g|JFJ=*2TtqoXIO@kQ{Kqe`6ZwLS=kVMT;5W>S7 zpvBTSbcuLU;a8&9L=N{+8708BY{kdvdvGbQM1+W3MB_-JeOI8r0{r4)Z#6&waKKBe zil&wj!x}8%(4r|MRq2H$DQckyO*&0ORV^Yy9}JM}xkxoJ8exLmCn#eKWlZ2Gg@BI0 zLMfQi7SI(1PYv~xYK#VDI7a$WS!dlGB{&68Habb>ziB7qCNM6?ebbF05*G#qyeKAv zAc|rdJEls2M5Nh{x`33A`2$8DLm|31Z7pBVG$FV=h4Jjwx@3 zK2hujV~++#WWMGvQ93LHj9^pN&92HjMqNo7KGZi*=!%O@Jlf*5IntyHNmAIK3T!xZ8JEAj1VkR4by_URf4eQv_}r3|#y6f{M?U;wp9QyDb`) z-5eMYv@lqv#{!$k5JyBcwJ`7^03Kw3bTEa~k|Tp?ahwSWn*Umlx(jhbM6ydG$S44S z65!}2LGTdxD~sY6jZRGY5Gu^vEAdCA-7#xKZ1&CH8uq~SM+E_Ml&MfP1!hDfcm^0r zykapkQA8xfUa0_^z;Uum3yC(B415hz88?IsYn=-*t)T9Y`w(qf2{{bJs&Q+~WYjvG~UANRJh`-Jksqs3}jPSJ*~PuSzaPqDYrq@N7B zCL>d@^VnszvPeLT<`El1UzHFe8VW0*ZzB2&`Ihch+hV~@H29PNxDMSIqBQ6Y&kB zp3y*4DSoV>lz%I9Cfg2z3cmZ4?F7cD=#Wh0A%Sgncou(TBtrlzQV`%JN`nbJg34!b z120~xS$L%XD77OFWaPQc2#QE*n#FXkJY>qEl03tFCR=^@xzGjWkXp=7by z4kP+Snre+!wB$+irMMC& z6H_$%RiBpxgasT%KYe9rm1B^FLkTVsl3Wh5{u~uWS|-v--M_tEhv3!r6e-PECAL zU2ADoawv_go{p=@1aYLag+xTHLV|8g9f(*cV=ta+Aq`7Ya>g9ZnxKcx^dy zLuyRTN3C^Cca2Pd_VC8kjs!aPlvh^ZF!Y&DFfYks(^Vv=*yUS5M`Iw&kaQ@@n42^~ zlzRiLY|6#VNm7l3_G+ELWUc9Qbh&O^SU8l|iUbvjmB%P4gdfpig#>_(J@Jy@s6+)X z1TI-5!I8#P8-CT!wqi=)O)MlW0Hpvi$8MmYtW^{eBk##JtXzb_2*)A_kmrT?s3^^A zOw4qsU}IJI;scNzmq3QpLVff~33mg`n<~X3yXQjJMdx{@tyc3K{Rj~YNd^<7tVb;A zs6?#b1Vcq9eA**scWmL6WRlEOd8I;#TGpdisQz-{izSCF%4t23X3%mZ+_flGjnOXQ zvY->4ScXxn8~@8<5z^w!qTRl|D&x2rhgkuFVce}?Br%_rWYmF(!XRE3W0Z`?JSaVg zVRKZ8+K>^$Pi)AD?WN#BLt*cN91cb+vN)@aAg>>vToMtW!;HBcD(Xkafv3hB@?u8&i*`+RF~+3?6UMb#k)hoH0OTnHO#}nb|7q#Tuk;K)3B^XnoAt|uPB?0l z^}42^N>-SlH*n?WZKfgTQZHVM`67n2L?@1%C{X)a)H})J1cH)zrx&QA9WjL93ow>L zE~TJE)A;vof-mCr0l@Ra*}H?u`>4DdvuSVr0%za&sMBz8Q*iBT-nQAeXR-}(;fuT= zoW0BJa6$xRIH)ODZgz-au>7@f+|dXdZ}S{y%baK=%VMKxDEK3@Y_SQsO!tCW*}4*6 zDO;rM3~?T)YDT0WW(MR0{<7Cd;^l6c<7}A&q&DS9{;1p*s#SA=9LB}VP(3tn5-
  • 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%0Af+*O*BH!j=M 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%0Ddcns{NflOeoy)6*aS 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

    ) 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 literal 0 HcmV?d00001 diff --git a/docs/src/ddesktopentry_example1.png b/docs/src/ddesktopentry_example1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c72f7bf8d8457833856badd35e983fd393bbbdd GIT binary patch literal 254041 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�E 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

    HxU6EB>v+q3Aq0LS5i(w8 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 literal 0 HcmV?d00001 diff --git a/docs/src/dsettings.png b/docs/src/dsettings.png new file mode 100644 index 0000000000000000000000000000000000000000..1a1bee9a386a761f7d9bfb5dd37ecbfc815b6eab GIT binary patch literal 123942 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 IM6N<$f+&>B;s5{u literal 0 HcmV?d00001 diff --git a/docs/src/layout.png b/docs/src/layout.png new file mode 100644 index 0000000000000000000000000000000000000000..57fae7c519dbfa1eaaeefd03e4825cc9719f43bf GIT binary patch literal 18169 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 + id从小到大, 单位从低级到高级. 各相邻单位之间的进率可以是不均匀的, 实现者只需实现unitConvertRate, 返回当前单位到下一高级单位(从id为x的单位到id为x+1的单位)的进率是正确的.
    + 事实上, 实现者如果保证unitConvertRate对于任一id为x的单位, 其到id为x+1的单位的换算比率(允许小于1)是正确的, 不需满足id递增, 单位级别递增的约束(即unitConvertRate总是大于1的约束)
    + 注意, 实现者此时需重写其他接口以同时保证正确性. + +@fn DAbstractUnitFormatter::DAbstractUnitFormatter() +@brief 空参构造函数 +@note 注意, 该类为抽象类, 不可直接实例化, 该构造函数仅供实现子类使用. + +@fn @pure virtual int DAbstractUnitFormatter::unitMax() const = 0 +@brief 获取最大的单位id +@return 最大的单位id + +@fn @pure virtual int DAbstractUnitFormatter::unitMin() const = 0 +@brief 获取最小的单位id +@return 最小的单位id + +@fn @pure virtual uint DAbstractUnitFormatter::unitConvertRate(int unitId) const = 0 +@brief 获取当前单位到下一高级单位的进率 +@param[in] unitId 当前单位id +@return 进率, 正常情况下, 大于1 +@note 下一高级单位指id为unitId + 1的单位. + +@fn virtual qreal DAbstractUnitFormatter::unitValueMax(int unitId) const +@brief 获取当前单位的最大值 +@param[in] unitId 当前单位id +@return 单位最大值 + +@fn virtual qreal DAbstractUnitFormatter::unitValueMin(int unitId) const +@brief 获取当前单位的最小值 +@param[in] unitId 当前单位id +@return 单位最小值 + +@fn virtual QString DAbstractUnitFormatter::unitStr(int unitId) const = 0 +@brief 获取当前单位的字符串表示 +@param[in] unitId 当前单位id +@return 单位字符串表示 + +@fn qreal DAbstractUnitFormatter::formatAs(qreal value, int currentUnit, const int targetUnit) const +@brief 格式化数值到指定单位 +@param[in] value 当前单位下表示的数值 +@param[in] currentUnit 当前单位id +@param[in] targetUnit 目标单位id +@return 格式化后以目标单位表示的数值 + +@fn QPair DAbstractUnitFormatter::format(const qreal value, const int unit) const +@brief 格式化数值到合适的单位 +@param[in] value 当前单位下表示的数值 +@param[in] unit 当前单位 +@return 格式化后的合适的数值和单位 + +合适是指: 如果单位大于unitMin()或者小于unitMax(), 会尽量保证值被转换到接近最小值的合适单位上. + +@fn QList > DAbstractUnitFormatter::formatAsUnitList(const qreal value, int unit) const +@brief 包括完整转换数据版本的format() +@param[in] value 当前单位下表示的数值 +@param[in] unit 当前单位 +@return 格式化产生的所有的数值和单位 + + +*/ diff --git a/docs/util/ddbusextentedabstractinterface.zh_CN.dox b/docs/util/ddbusextentedabstractinterface.zh_CN.dox new file mode 100644 index 0000000..511b3c9 --- /dev/null +++ b/docs/util/ddbusextentedabstractinterface.zh_CN.dox @@ -0,0 +1,127 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/ddbusextendedabstractinterface.h + +该文件提供了一个扩展DBus接口工具类 + +@class Dtk::Core::DDBusExtendedAbstractInterface +@brief 扩展DBus接口, 继承自QDBusAbstractInterface +@details 和QDBusAbstractInterface相比, 该类连接了org.freedesktop.DBus.Properties接口, 提供了异步访问属性的接口, 可以方便地通过此类进行异步DBus通信.
    +同时此类提供了属性改变信号的分发和中继. + +@fn DDBusExtendedAbstractInterface::DDBusExtendedAbstractInterface(const QString &service, const QString &path, const char *interface, const QDBusConnection &connection, QObject *parent) +@brief 构造函数 +@param[in] service 该interface属于的服务 +@param[in] path 该interface属于的对象路径 +@param[in] interface 该interface实际连接的接口 +@param[in] connection 用于连接该interface的DBus连接 +@param[in] parent 父对象 +@note 该构造函数受到保护, 只有子对象才能访问. + +@property Dtk::Core::DDBusExtendedAbstractInterface::sync +@brief 是否同步获取属性 +@details 当sync为false的时候, 在调用属性的get函数的时候会一直返回空值, 解决方法是监听属性的changed信号并自行保存一份缓存, 让changed信号修改这个缓存. + +@property Dtk::Core::DDBusExtendedAbstractInterface::useCache +@brief 是否使用缓存 +@details 如果使用缓存, 在内部获取属性的时候将不再进行DBus调用更新属性. + +@fn inline bool DDBusExtendedAbstractInterface::sync() const +@brief 获取是否同步 +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) + +@fn void DDBusExtendedAbstractInterface::setSync(bool sync, bool autoStart) +@brief 设置是否同步和自启动 +@param[in] sync 是否同步 +@param[in] autoStart 是否自启动 +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) + + +@fn void DDBusExtendedAbstractInterface::setSync(bool sync) +@brief 设置是否同步 +@param[in] sync 是否是同步模式 +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) +@details 该函数内部实现调用[setSync](@ref DDBusExtendedAbstractInterface::setSync(bool sync, bool autoStart)), autoStart参数值为true, 即默认自启动. + +@fn inline bool DDBusExtendedAbstractInterface::useCache() const +@brief 获取是否使用缓存 +@sa [useCache](@ref Dtk::Core::DDBusExtendedAbstractInterface::useCache) + +@fn inline void DDBusExtendedAbstractInterface::setUseCache() +@brief 设置是否使用缓存 +@sa [useCache](@ref Dtk::Core::DDBusExtendedAbstractInterface::useCache) + +@fn void DDBusExtendedAbstractInterface::getAllProperties() +@brief 获取所有属性 +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) +@details 该方法会调用org.freedesktop.DBus.Properties接口的GetAll方法, 获取所有属性并且发送属性改变信号, 如果是同步模式(sync为true), 该方法会使用同步调用call.
    +sync为false的时候会使用异步调用asyncCall. + +@fn inline QDBusError DDBusExtendedAbstractInterface::lastExtendedError() const +@brief 获取上一次的错误 +@return QDBusError 上一次由DBus调用引起的错误 + +@fn void DDBusExtendedAbstractInterface::startServiceProcess() +@brief 启动服务进程 +@details 该函数会调用org.freedesktop.DBus的服务的/路径的StartServiceByName方法启动DDBusExtendedAbstractInterface对应的Service. + +@fn void DDBusExtendedAbstractInterface::serviceValidChanged(const bool valid) const +@brief 服务是否有效状态改变信号 +@param[in] valid 服务是否有效 + +@fn void DDBusExtendedAbstractInterface::serviceStartFinished(const quint32 ret) const +@brief 服务启动完成通知信号 +@param[in] ret 启动服务的返回值 +@details 启动服务是调用org.freedesktop.DBus服务的/路径的StartServiceByName方法, ret为StartServiceByName的返回值. + +@fn void DDBusExtendedAbstractInterface::propertyChanged(const QString &propertyName, const QVariant &value) +@brief 属性改变信号 +@param[in] propertyName 改变的属性名 +@param[in] value 改变后的属性值 + +@fn void DDBusExtendedAbstractInterface::propertyInvalidated(const QString &propertyName) +@brief 属性失效通知信号 +@param[in] propertyName 失效的属性名 +@details 该信号会在DBus属性改变但是本地反序列化失败的情况下发出. + +@fn void DDBusExtendedAbstractInterface::asyncPropertyFinished(const QString &propertyName) +@brief 异步获取属性完成通知信号 +@param[in] propertyName 获取成功的属性名 + +@fn void DDBusExtendedAbstractInterface::asyncSetPropertyFinished(const QString &propertyName) +@brief 异步设置属性完成通知信号 +@param[in] propertyName 设置成功的属性名 + +@fn void DDBusExtendedAbstractInterface::asyncGetAllPropertiesFinished() +@brief 异步获取所有属性完成的通知信号 +@sa [getAllProperties](@ref Dtk::Core::DDBusExtendedAbstractInterface::getAllProperties()) +@details getAllProperties方法并没有返回值, 须监听此信号以实现完整功能. + + +@fn void DDBusExtendedAbstractInterface::connectNotify(const QMetaMethod &signal) +@brief 信号连接通知函数 +@param[in] signal 连接到该对象的信号 +@details 该函数重写了QObject的connectNotify函数, 当有某一个信号连接到该对象的时候, 该函数就会被调用. + +@fn void DDBusExtendedAbstractInterface::disconnectNotify(const QMetaMethod &signal) +@brief 信号断开连接通知函数 +@param[in] signal 断连的信号 +@details 该函数重写了QObject的disconnectNotify函数, 当有某一个连接到该对象的信号断连时, 该函数就会被调用. + +@fn QVariant DDBusExtendedAbstractInterface::internalPropGet(const char *propname, void *propertyPtr) +@brief 内部属性获取函数 +@param[in] propname 属性名 +@param[in] propertyPtr 属性缓存指针 +@sa [useCache](@ref Dtk::Core::DDBusExtendedAbstractInterface::useCache) +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) +@details 当useCache为true的时候, 该函数仅仅返回propertyPtr指向的内存拷贝. + +@fn void DDBusExtendedAbstractInterface::internalPropSet(const char *propname, const QVariant &value, void *propertyPtr) +@brief 内部属性设置函数 +@param[in] propname 属性名 +@param[in] value 要设置的值 +@param[in] propertyPtr 属性缓存指针 +@sa [sync](@ref Dtk::Core::DDBusExtendedAbstractInterface::sync) + +*/ diff --git a/docs/util/ddbussender.zh_CN.dox b/docs/util/ddbussender.zh_CN.dox new file mode 100644 index 0000000..e2c54df --- /dev/null +++ b/docs/util/ddbussender.zh_CN.dox @@ -0,0 +1,89 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/ddbussender.h + +本文件包含了DDBusSender类和相对应的工具类 + +@class DDBusData +@brief DBus数据存储类 +@details 该类用来存储DBus连接的相关信息 + +@var DDBusData::service +@brief 请求调用服务名 + +@var DDBusData::path +@brief 请求调用对象路径 + +@var DDBusData::interface +@brief 请求调用接口名 + +@var DDBusData::queryName +@brief 请求调用函数名 + +@var DDBusData::connection +@brief 进行调用的维护的DBus连接 + +@class DDBusCaller +@brief DBus接口调用工具类 +@details 该类用于完成实际的DBus接口调用 + +@fn template DDBusCaller DDBusCaller::arg(const T &argument) +@brief 添加调用参数 +@details 改接口符合链式编程规则 +@param[in] argument 调用参数 +@return DDBusCaller 添加参数之后的caller + +@fn QDBusPendingCall DDBusCaller::call() +@brief 发起实际调用 +@return QDBusPendingCall 异步调用对象 + +@class DDBusProperty +@brief DBus属性操作对象 +@details 该类的作用和DDBusCaller类似, 用于完成实际的调用, 其封装了org.freedesktop.DBus.Properties的接口, 提供方便快捷地属性访问方法set和get + +@fn QDBusPendingCall DDBusProperty::get() +@brief 获取属性值 +@return QDBusPendingCall 异步调用对象, 在完成之后可用于获取属性值 + +@fn template QDBusPendingCall DDBusProperty::set(const T &value) +@brief 设置属性值 +@param[in] value 需要设置的值 +@return QDBusPendingCall 异步调用对象, 在完成之后可用于判断设置操作是否成功 + +@class DDBusSender +@brief DBus请求工具类 +@details 通过该类的方法可以方便地调用某个服务的某个方法. 该类的设计采用链式编程, 多个api都会返回操作之后的对象, 这使得原本需要使用QDBusMessage多行代码完成的调用只需要一行代码即可完成. + +@fn DDBusSender DDBusSender::service(const QString &service) +@brief 设置请求服务名 +@param[in] service 请求服务名 +@return DDBusSender 设置之后的sender + +@fn DDBusSender DDBusSender::interface(const QString &interface) +@brief 设置请求接口名 +@param[in] interface 请求接口名 +@return DDBusSender 设置之后的sender + +@fn DDBusSender DDBusSender::path(const QString &path) +@brief 设置请求对象路径 +@param[in] path 请求对象路径 +@return DDBusSender 设置之后的sender + +@fn DDBusCaller DDBusSender::method(const QString &method) +@brief 设置请求方法名并获取请求调用对象 +@details 确保在调用该方法之前, service, path和interface都已经被正确设置 +@param[in] method 请求方法名 +@return DDBusCaller 方法调用工具对象, 调用该对象的call函数即可完成最终调用 + +@fn DDBusProperty DDBusSender::property(const QString &property) +@brief 设置访问的属性名并获得属性操作对象 +@details 确保在调用该方法之前, service, path和interface都已经被正确设置 +@param[in] property 访问属性名 +@return DDBusProperty 属性操作对象 + +@fn static DDBusSender DDBusSender::system() +@brief 获取 systembus 访问的能力 +@details DDBusSender 默认使用 sessionbus ,此接口提供 systembus 的访问能力 +@return DDBusSender 可以访问 systembus 的 sender 对象 +*/ diff --git a/docs/util/ddisksizeformatter.zh_CN.dox b/docs/util/ddisksizeformatter.zh_CN.dox new file mode 100644 index 0000000..c52c997 --- /dev/null +++ b/docs/util/ddisksizeformatter.zh_CN.dox @@ -0,0 +1,46 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/ddisksizeformatter.h + +本文件定义了用于转换磁盘大小单位的类DDiskSizeFormatter + +@class Dtk::Core::DDiskSizeFormatter +@brief 磁盘大小单位转换类 +@details 继承自DAbstractUnitFormatter, 支持最小的单位为字节, 最大的单位为T字节, 支持修改相邻单位之间的进率, 是采用1000还是1024. 默认使用1000作为进率 + +@enum Dtk::Core::DDiskSizeFormatter::DiskUnits +@brief 磁盘大小单位枚举 +@var Dtk::Core::DDiskSizeFormatter::DiskUnits Dtk::Core::DDiskSizeFormatter::B +@brief 字节 +@var Dtk::Core::DDiskSizeFormatter::DiskUnits Dtk::Core::DDiskSizeFormatter::K +@brief 千字节 +@var Dtk::Core::DDiskSizeFormatter::DiskUnits Dtk::Core::DDiskSizeFormatter::M +@brief 兆字节 +@var Dtk::Core::DDiskSizeFormatter::DiskUnits Dtk::Core::DDiskSizeFormatter::G +@brief 吉字节 +@var Dtk::Core::DDiskSizeFormatter::DiskUnits Dtk::Core::DDiskSizeFormatter::T +@brief 太字节| + +@fn QString DDiskSizeFormatter::unitStr(int unitId) const override +@brief 获取unitId对应单位的字符串表示 +@param[in] unitId 单位id +@return QString 字符串表示 + +@fn DDiskSizeFormatter DDiskSizeFormatter::rate(int rate) +@brief 设置当前的单位进率 +@param[in] rate 需要设置的进率 +@return DDiskSizeFormatter 设置之后的formatter + +@fn int DDiskSizeFormatter::unitMin() const override +@brief 获取最小的单位枚举 +@return int 最小的单位 + +@fn int DDiskSizeFormatter::unitMax() const override +@brief 获取最大的单位枚举 +@return int 最大的单位 + +@fn uint DDiskSizeFormatter::unitConvertRate(int unitId) const override +@brief 获取unitId对应单位到下一个单位的进率 +@param[in] unitId 当前单位id +*/ diff --git a/docs/util/dtextencoding.zh_CN.dox b/docs/util/dtextencoding.zh_CN.dox new file mode 100644 index 0000000..ac7745f --- /dev/null +++ b/docs/util/dtextencoding.zh_CN.dox @@ -0,0 +1,72 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/dtextencoding.h +@details 本文件包含文本编码识别和文本编码转换的公共接口。 + +@class Dtk::Core::DTextEncoding +@brief 文本编码信息类,提供文本编码识别和文本编码转换的公共接口。 +@details 提供文本编码识别和文本编码转换的公共接口,默认使用 QTextCodec 进行检测, + 若系统环境中存在 libuchardet.so 及 libicuuc.so 库,可拓展支持的编码格式。 + +@fn QByteArray Dtk::Core::DTextEncoding::detectTextEncoding(const QByteArray &content) +@brief 检测给定文本的编码格式。 +@details 默认使用 QTextCodec 检测,若系统环境中存在 libuchardet.so 及 libicuuc.so 库,可拓展支持的编码格式。 + 检测会判断最接近的编码格式,未成功识别或为 ASCII 编码格式,将返回 UTF-8 编码格式。 +@param[in] content 待检测的文本内容 +@return 文本编码格式 + +@fn QByteArray Dtk::Core::DTextEncoding::detectFileEncoding(const QString &fileName, bool *isOk) +@brief 检测给定文件的文本编码格式,将读取文件头部最多 64KB 的文本用于检测。若文件访问失败,返回空编码格式。 +@param[in] fileName 文件路径 +@param[out] isOk 检测是否成功,主要判断文件内容能否正确读取 +@return 文本编码格式 +@sa DTextEncoding::detectTextEncoding + +@fn bool Dtk::Core::DTextEncoding::convertTextEncoding(QByteArray &content, QByteArray &outContent, const QByteArray &toEncoding, const QByteArray &fromEncoding, QString *errString) +@brief 将输入的文本 `content` 从 `fromEncoding` 编码格式转换到 `toEncoding` 编码格式,转换后的文本保存到 `outContent` 。 + 若转换过程中出现错误,将返回 false , 并设置 `errString` 错误信息,已转换的文本仍会写入 `outContent` 。 +@note 当处理大量文本数据时,需考虑并行处理,防止阻塞线程。 +@param[in] content 传入的文本 +@param[out] outContent 编码转换后的文本 +@param[in] toEncoding 转换的编码格式 +@param[in] fromEncoding 原始的编码格式,默认为空,会通过 `DTextEncoding::detectTextEncoding` 检测编码格式 +@param[out] errString 错误信息 +@return 是否转换成功 +@sa DTextEncoding::convertTextEncodingEx + +@fn bool Dtk::Core::DTextEncoding::convertTextEncodingEx(QByteArray &content, QByteArray &outContent, const QByteArray &toEncoding, const QByteArray &fromEncoding, QString *errString, int *convertedBytes) +@brief 将输入的文本 `content` 从 `fromEncoding` 编码格式转换到 `toEncoding` 编码格式,转换后的文本保存到 `outContent` 。 + 若转换过程中出现错误,将返回 false , 并设置 `errString` 错误信息,已转换的文本仍会写入 `outContent` 。 +@note 当处理大量文本数据时,需考虑并行处理,防止阻塞线程。 +@note 返回 false 时,已转换的文本仍会写入 `outContent` ,同时 `convertedBytes` 会记录已转换数据长度,你可以决定保留或移除转换文本。 +@param[in] content 传入的文本 +@param[out] outContent 编码转换后的文本 +@param[in] toEncoding 转换的编码格式 +@param[in] fromEncoding 原始的编码格式,默认为空,会通过 `DTextEncoding::detectTextEncoding` 检测编码格式 +@param[out] errString 错误信息 +@param[out] convertedBytes 已转换的 `content` 数据长度,若转换过程出现错误,这个值会指向异常字符出现的位置 +@return 是否转换成功 + +@fn bool DTextEncoding::convertFileEncoding(const QString &fileName, const QByteArray &toEncoding, const QByteArray &fromEncoding, QString *errString) +@brief 读取输入的 `fileName` 文件内容,将文件内容从 `fromEncoding` 编码格式转换到 `toEncoding` 编码格式,转换后的文本保存到 `fileName` 。 + 若转换过程中出现错误,将返回 false , 并设置 `errString` 错误信息,已转换的文本会被抛弃。 +@param[in] fileName 传入及保存的文件路径 +@param[in] toEncoding 转换的编码格式 +@param[in] fromEncoding 原始的编码格式,为空时会通过 `DTextEncoding::detectTextEncoding` 检测编码格式 +@param[out] errString 错误信息 +@return 是否转换成功 +@sa DTextEncoding::convertTextEncoding + +@fn bool DTextEncoding::convertFileEncodingTo(const QString &fromFile, const QString &toFile, const QByteArray &toEncoding, const QByteArray &fromEncoding, QString *errString) +@brief 读取输入的 `fromFile` 文件内容,将文件内容从 `fromEncoding` 编码格式转换到 `toEncoding` 编码格式,转换后的文本保存到 `toFile` 。 + 若转换过程中出现错误,将返回 false , 并设置 `errString` 错误信息,已转换的文本会被抛弃。 +@param[in] fromFile 传入的文件路径 +@param[in] toFile 保存的文件路径 +@param[in] toEncoding 转换的编码格式 +@param[in] fromEncoding 原始的编码格式,为空时会通过 `DTextEncoding::detectTextEncoding` 检测编码格式 +@param[out] errString 错误信息 +@return 是否转换成功 +@sa DTextEncoding::convertTextEncoding + + */ diff --git a/docs/util/dthreadutils.zh_CN.dox b/docs/util/dthreadutils.zh_CN.dox new file mode 100644 index 0000000..c56ca7f --- /dev/null +++ b/docs/util/dthreadutils.zh_CN.dox @@ -0,0 +1,55 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/dthreadutils.h + +本文件定义了线程相关的帮助类 + +@class DThreadUtils +@brief 线程帮助类 +@details 本类主要用来进行异步线程调用, 此外本类所有的public接口都是线程安全的 + +@fn static DThreadUtils& DThreadUtils::gui() +@brief 获取以GUI线程初始化的静态对象 +@return DThreadUtils& 静态对象的引用 + +@fn QThread* DThreadUtils::thread() const noexcept +@brief 获取DThreadUtils对应的线程 +@return QThread* 对应线程的QThread对象的指针 + +@fn template inline auto run(QObject *context,typename QtPrivate::FunctionPointer::Object *obj, Func fun, Args &&...args) +@brief 在对应的线程执行传入的成员函数, 非阻塞 +@param[in] context 对象上下文, 用来在执行调用时判断对象是否存在 +@param[in] obj 对象指针 +@param[in] fun 成员函数指针 +@param[in] args 对应函数的参数 +@return 以成员函数返回值类型实例化的QFuture对象 + +@fn template inline auto run(typename QtPrivate::FunctionPointer::Object *obj, Func fun, Args &&...args) +@brief 在对应的线程执行传入的成员函数, 非阻塞 +@param[in] obj 对象指针 +@param[in] fun 成员函数指针 +@param[in] args 对应函数的参数 +@return 以成员函数返回值类型实例化的QFuture对象 + +@fn template inline QFuture, Args...>> run(QObject *context, Func fun, Args &&...args) +@brief 在对应的线程执行传入的成员函数, 非阻塞 +@param[in] context 对象上下文, 用来在执行调用时判断对象是否存在 +@param[in] fun 成员函数指针 +@param[in] args 对应函数的参数 +@return 以成员函数返回值类型实例化的QFuture对象 + +@fn template inline QFuture, Args...>> run(Func fun, Args &&...args) +@brief 在对应的线程执行传入的成员函数, 非阻塞 +@param[in] fun 可调用对象 +@param[in] args 调用对应的参数 +@return 以函数返回值类型实例化的QFuture对象 + +@fn template inline decltype(auto) exec(T &&...args) +@brief 在对应的线程执行传入的成员函数, 阻塞 +@details 本函数是run函数的包装 +@note 调用此函数的一方需要确保对应线程有事件循环, 否则会无限等待 +@param[in] args 参数包, 具体含义参考run函数 +@return 传入函数的返回值 + +*/ diff --git a/docs/util/dtimeunitformatter.zh_CN.dox b/docs/util/dtimeunitformatter.zh_CN.dox new file mode 100644 index 0000000..7c0780c --- /dev/null +++ b/docs/util/dtimeunitformatter.zh_CN.dox @@ -0,0 +1,40 @@ +/*! +@~chinese +@ingroup dutil +@file include/util/dtimeunitformatter.h + +该文件定义了用于转换时间单位的工具类DTimeUnitFormatter. + +@class Dtk::Core::DTimeUnitFormatter +@brief 转换时间单位的工具类 +@details 继承自DAbstractUnitFormatter, 支持最小单位为秒, 最大单位为天. + +@enum Dtk::Core::DTimeUnitFormatter::TimeUnits +@brief 时间单位枚举 +@var Dtk::Core::DTimeUnitFormatter::TimeUnits Dtk::Core::DTimeUnitFormatter::Seconds +@brief 秒 +@var Dtk::Core::DTimeUnitFormatter::TimeUnits Dtk::Core::DTimeUnitFormatter::Minute +@brief 分钟 +@var Dtk::Core::DTimeUnitFormatter::TimeUnits Dtk::Core::DTimeUnitFormatter::Hour +@brief 小时 +@var Dtk::Core::DTimeUnitFormatter::TimeUnits Dtk::Core::DTimeUnitFormatter::Day +@brief 天 + +@fn QString DTimeUnitFormatter::unitStr(int unitId) const override +@brief 获取unitId对应单位的字符串表示 +@param[in] unitId 单位id +@return QString 字符串表示 + +@fn int DTimeUnitFormatter::unitMin() const override +@brief 获取最小的单位枚举 +@return int 最小的单位 + +@fn int DTimeUnitFormatter::unitMax() const override +@brief 获取最大的单位枚举 +@return int 最大的单位 + +@fn uint DTimeUnitFormatter::unitConvertRate(int unitId) const override +@brief 获取unitId对应单位到下一个单位的进率 +@param[in] unitId 当前单位id + +*/ diff --git a/docs/util/dutil.zh_CN.dox b/docs/util/dutil.zh_CN.dox new file mode 100644 index 0000000..7a95396 --- /dev/null +++ b/docs/util/dutil.zh_CN.dox @@ -0,0 +1,31 @@ +/*! +@chinese +@ingroup dutil +@file include/util/dutil.h + +该文件定义和实现了一些小的工具函数. + +@fn QString DUtil::escapeToObjectPath(const QString &str) +@brief 将字符串转义成符合DBus ObjectPath规则字符串 +@param[in] str 需要转义的字符串 +@return 转义后字符串 +@attention 不要传入完整的dbus路径, 否则'/'也会被转义 + +@fn QString DUtil::unescapeFromObjectPath(const QString &str) +@brief 将DBus ObjectPath的部分路径转义成原来的字符串 +@param[in] str 需要转义的字符串 +@return 转义后字符串 + +@fn QString DUtil::getAppIdFromAbsolutePath(const QString &path) +@brief 从desktop文件的绝对路径中提取出AppId +@param[in] path 文件路径 +@return 代表AppId的字符串 +@attention AppId可能为空, 代表无法获取AppId + +@fn QStringList DUtil::getAbsolutePathFromAppId(const QString &appId) +@brief 从appId中获取符合条件的Desktop文件路径 +@param[in] appId app的Id +@return desktop文件的路径 +@attention 可能有多个desktop文件的appId相同, 所以返回所有符合条件的列表 + +*/ diff --git a/docs/util/index.zh_CN.md b/docs/util/index.zh_CN.md new file mode 100644 index 0000000..5662655 --- /dev/null +++ b/docs/util/index.zh_CN.md @@ -0,0 +1,13 @@ +@page util util--DTK工具组件 + +# DTK util + +## 模块介绍 + +该模块提供一些实用工具用于开发,包括: + ++ 同种数据类的单位转换接口 ++ DBus接口工具类 + +@defgroup dutil +@brief dtk实用工具 diff --git a/dtkcore.cmake b/dtkcore.cmake new file mode 100644 index 0000000..95c98d4 --- /dev/null +++ b/dtkcore.cmake @@ -0,0 +1,153 @@ +set(LIB_NAME dtk${DTK_VERSION_MAJOR}core) +set(DtkCore Dtk${DTK_VERSION_MAJOR}Core) + +macro(add_sub_dir dir) +# message("add_subdirectory(${dir} ${OUTPUT_DIR}/${dir})") + add_subdirectory(${dir} ${OUTPUT_DIR}/${dir}) +endmacro() + +message("Current Qt Version: ${QT_VERSION_MAJOR}") +message("Current Dtk Version: ${DTK_VERSION_MAJOR}") + +set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set (LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") +set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${PROJECT_VERSION_MAJOR}/DCore") +set (TOOL_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/dtk${PROJECT_VERSION_MAJOR}/DCore/bin") +set (MKSPECS_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/mkspecs/modules" CACHE STRING "Install dir for qt pri files") +set (FEATURES_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/mkspecs/features" CACHE STRING "Install dir for qt prf files") +set (CONFIG_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${DtkCore}" CACHE STRING "Install dir for cmake config files") +set (DSG_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}" CACHE STRING "PREFIX of DSG_DATA_DIRS") +set (DSYSINFO_PREFIX "" CACHE STRING "PREFIX of DSysInfo") + +set (BUILD_EXAMPLES ON CACHE BOOL "Build examples") +set (BUILD_VERSION "0" CACHE STRING "buildversion") + +if(UNIX AND NOT APPLE) + set(LINUX TRUE) +endif() + +set (BUILD_WITH_SYSTEMD OFF CACHE BOOL "Build with systemd") +if (BUILD_WITH_SYSTEMD) + add_definitions(-DBUILD_WITH_SYSTEMD) +endif() + +set(CMAKE_CXX_STANDARD 17) + +# CXX FILAGS +if("${QT_VERSION_MAJOR}" STREQUAL "5") + set (BUILD_DOCS ON CACHE BOOL "Generate doxygen-based documentation") +else() + # dtk6 not build doc + set (BUILD_DOCS OFF CACHE BOOL "Generate doxygen-based documentation") +endif() +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -pie") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(BUILD_TESTING ON) + endif () + string(REPLACE "-O3" "-Ofast" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") +endif() + +if (BUILD_DOCS) + add_sub_dir(docs) +endif () + +add_sub_dir(src) +if(BUILD_TESTING) + message("==================================") + message(" Now Testing is enabled ") + message("==================================") + enable_testing() + add_sub_dir(tests) +endif() +if(BUILD_EXAMPLES) + message("===================================") + message("You can build and run examples now ") + message("===================================") + add_sub_dir(examples) +endif() +add_sub_dir(tools) + +if("${QT_VERSION_MAJOR}" STREQUAL "6") + set(DTK_VERSION_MAJOR 6) +endif() + +configure_package_config_file(cmake/DtkCMake/DtkCMakeConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_VERSION_MAJOR}CMakeConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}CMake" + PATH_VARS TOOL_INSTALL_DIR) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_VERSION_MAJOR}CMakeConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}CMake") + +configure_package_config_file(cmake/DtkTools/DtkToolsConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_VERSION_MAJOR}ToolsConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools + PATH_VARS TOOL_INSTALL_DIR) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_VERSION_MAJOR}ToolsConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools") + +install(FILES cmake/DtkTools/DtkSettingsToolsMacros.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools" + RENAME Dtk${DTK_VERSION_MAJOR}SettingsToolsMacros.cmake) + +install(FILES cmake/DtkTools/DtkDBusMacros.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools") + +if (NOT DTK_VERSION_MAJOR) + set(DCONFIG_DEPRECATED_FUNCS [=[ +# deprecated since dtk6 +function(dconfig_meta_files) + dtk_add_config_meta_files(${ARGV}) +endfunction() +function(dconfig_override_files) + dtk_add_config_override_files(${ARGV}) +endfunction()]=]) +endif() + +configure_package_config_file(cmake/DtkDConfig/DtkDConfigConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_VERSION_MAJOR}DConfigConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}DConfig" + PATH_VARS TOOL_INSTALL_DIR) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_VERSION_MAJOR}DConfigConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}DConfig") + +configure_package_config_file(misc/DtkCoreConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${DtkCore}Config.cmake + INSTALL_DESTINATION ${CONFIG_CMAKE_INSTALL_DIR} + PATH_VARS TOOL_INSTALL_DIR) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${DtkCore}ConfigVersion.cmake" + VERSION ${DTK_VERSION} + COMPATIBILITY SameMajorVersion +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DtkCore}Config.cmake DESTINATION ${CONFIG_CMAKE_INSTALL_DIR}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DtkCore}ConfigVersion.cmake DESTINATION ${CONFIG_CMAKE_INSTALL_DIR}) + +configure_file(misc/dtkcore.pc.in ${LIB_NAME}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +configure_file(misc/qt_lib_dtkcore.pri.in qt_lib_dtkcore.pri @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qt_lib_dtkcore.pri DESTINATION "${MKSPECS_INSTALL_DIR}") +install(FILES misc/dtk_install_dconfig.prf DESTINATION ${FEATURES_INSTALL_DIR}) +set(CONFIGNAME include/global/dtkcore_config.h) +file(WRITE ${CONFIGNAME} + "// it is auto make config\n" + "#define DTK_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}\n" + "#define DTK_VERSION_MINOR ${PROJECT_VERSION_MINOR}\n" + "#define DTK_VERSION_PATCH ${PROJECT_VERSION_PATCH}\n" + "#define DTK_VERSION_BUILD ${BUILD_VERSION}\n" + "#define DTK_VERSION_STR \"${PROJECT_VERSION}\"\n" + "\n" +) +file(GLOB CONFIGSOURCE include/DtkCore/*) + +foreach(FILENAME ${CONFIGSOURCE}) + get_filename_component(thefile ${FILENAME} NAME) + file(APPEND ${CONFIGNAME} "#define DTKCORE_CLASS_${thefile}\n") +endforeach() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6a01ca4..5fe9f25 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,2 +1,4 @@ -add_subdirectory(dasync-example) add_subdirectory(expintf-example) +add_subdirectory(textcodec-example) +add_subdirectory(filewatcher-example) +add_subdirectory(dlog-example) diff --git a/examples/dasync-example/CMakeLists.txt b/examples/dasync-example/CMakeLists.txt deleted file mode 100644 index 9813915..0000000 --- a/examples/dasync-example/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(BINNAME dasync) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -find_package(Qt5 REQUIRED COMPONENTS Widgets) -find_package(Qt5 REQUIRED COMPONENTS Core) - -add_executable(${BINNAME} - main.cpp -) - -target_link_libraries( - ${BINNAME} PRIVATE - Qt5::Core - Qt5::Widgets - dtkcore - -lpthread -) -target_include_directories(${BINNAME} PUBLIC - ../../include/global/ - ../../include/util/ - ../../include/ -) diff --git a/examples/dasync-example/main.cpp b/examples/dasync-example/main.cpp deleted file mode 100644 index 84c2a7d..0000000 --- a/examples/dasync-example/main.cpp +++ /dev/null @@ -1,444 +0,0 @@ -// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include -#include -#include -#include -#include - -#include - -#include "util/dasync.h" -#include "util/dthreadutils.h" - -#ifdef QT_DEBUG -#include -#endif - -DCORE_USE_NAMESPACE - -#define XLog() qDebug() << __LINE__ << " " - -#define RUN_IN_SUB_THREAD 1 - -#define THREAD_BEGIN std::thread thread([&]{ -#define THREAD_END }); thread.detach(); - -#if RUN_IN_SUB_THREAD -# define OPT_THREAD_BEGIN THREAD_BEGIN -# define OPT_THREAD_END THREAD_END -#else -# define OPT_THREAD_BEGIN -# define OPT_THREAD_END -#endif - -#define TIMED_EXIT(second, loop) QTimer::singleShot(second * 1000, [&]{ loop.exit(); }) - -struct Configure -{ - QObject *o = nullptr; - QWidget *w = nullptr; -} conf; -static Configure *config = &conf; - -int main1(int argc, char *argv[]); -int main2(int argc, char *argv[]); -int main3(int argc, char *argv[]); - -int main(int argc, char *argv[]) { - QApplication app(argc, argv); - - // 将以下所有新建的对象都托管给 w、o - config->w = new QWidget; - config->o = new QObject; - - config->w->show(); - - main1(argc, argv); - main2(argc, argv); - main3(argc, argv); - - QTimer::singleShot(1 * 1000, [&]{ - config->w->deleteLater(); - config->o->deleteLater(); - }); - - QTimer::singleShot(2 * 1000, [&]{ - qApp->exit(0); - }); - - qDebug() << "finished xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - - return app.exec(); -} - -#pragma mark main1 ------------------------------------------------------------ - -// 这是一个最基础的示例程序 -DAsync *testTask() { - auto task = new DAsync(config->o); - - int i = 0; - while (i < 100) { - task->postData(i++); - } - - task->post([](int arg) { - - Q_ASSERT(!D_THREAD_IN_MAIN()); - XLog() << "run in child thread: " << arg; - return arg * 2; - - })->then([&](int arg) { - - Q_ASSERT(D_THREAD_IN_MAIN()); - XLog() << "run in main thread:" << arg; - - })->start(); - - task->postData(i++); - - return task; -} - -void runTest() -{ - OPT_THREAD_BEGIN - auto task = testTask(); - // 删除前应该先等待所有的任务执行完或取消未执行的任务 - // 主线程中只能用 isFinished 查询状态,用 cancelAll 取消之后的任务队列 - // 其它子线程中(非 post、非 then 函数)中可以直接 waitForFinished 然后删除 - // 也可以使用 task->setParent 去托管,自动释放 - if (!D_THREAD_IN_MAIN()) { - task->waitForFinished(false); - // task->deleteLater(); - } - OPT_THREAD_END -} - -int main1(int argc, char *argv[]) { - QEventLoop loop; - TIMED_EXIT(3, loop); - - XLog() << "in main thread: " << pthread_self(); - - // DAsync 依赖事件循环,不能被阻塞,比如 thread.join 就不行 - // 运行在主线程中和运行在子线程中应该有一样的结果才对 - OPT_THREAD_BEGIN - runTest(); - OPT_THREAD_END - - return loop.exec(); -} - -#pragma mark main2 ------------------------------------------------------------ - -int main2(int argc, char *argv[]) { - QEventLoop loop; - TIMED_EXIT(3, loop); - - OPT_THREAD_BEGIN - QWidget *w = DThreadUtil::runInMainThread([&](){ - QWidget *w = new QWidget(config->w); - w->setBackgroundRole(QPalette::HighlightedText); - w->show(); - return w; - }); - // w->show(); - OPT_THREAD_END - - return loop.exec(); -} - -#pragma mark main3 ------------------------------------------------------------ - -int test1(); -int test2(); -int test3(); -int test4(); -int test5(); -int test6(); -int test7(); -int test8(); - -int main3(int argc, char *argv[]) { - std::clog << "in main thread: " << pthread_self() << std::endl; - - // 示例 1,输入输出都是基本类型 - test1(); - - // 示例 2,输入基本类型,输出复合类型 - test2(); - - // 示例 3,输入输出都是复合类型 - test3(); - - // 示例 4,输入输出都是自定义类型的指针 - test4(); - - // 示例 5, 异步执行一个输入复合类型、没有输出的一次性任务,执行结束后通知主线程 - // 间歇性输入数据,要保证生产者消费者模型的正确性。 - test5(); - - // 示例 6, 异步执行一个没有输入、输出参数的一次性任务,执行结束后通知在主线 - test6(); - - // 示例 7, 异步运行一个没有输入参数的一次性任务,执行后在主线程处理结果 - test7(); - - // 示例 8, 在子线程中异步创建一个 widget 并显示出来: - test8(); - // std::thread thread([&]{ test8(); }); - // thread.detach(); - - return 0; -} - -int test1() { - QEventLoop loop; - TIMED_EXIT(2, loop); - - // 加 static 防止函数执行结束后线程中继续 postData 访问已经释放的栈上变量 - static auto task1 = new DAsync(config->o); - static int i = 0; - - while (i < 100) { - task1->postData(i++); - } - - task1->post([](int arg) { - - XLog() << "async task: " << arg; - return arg * 2; - - })->then([](int arg) { - - XLog() << "get result: " << arg; - - })->start(); - - return loop.exec(); -} - -int test2() { - QEventLoop loop; - - static auto task2 = new DAsync(config->o); - - static int i = 0; - static bool stopFlag = false; - - // TIMED_EXIT(3, loop); - QTimer::singleShot(3 * 1000, [&]{ - stopFlag = true; - loop.exit(); - }); - - while(i < 100) { - task2->postData(i++); - } - - task2->post([](int arg) -> QString { - - XLog() << "async task: " << arg; - return QString::number(arg); - - })->then([](QString arg) { - - XLog() << "get result: " << arg; - - })->start(); - - THREAD_BEGIN - while (!stopFlag && i < 220) { - XLog() << "post data: " << i; - task2->postData(i++); - usleep(200 * 1000); - } - THREAD_END - - // task2->waitForFinished(); - // task2->deleteLater(); - - return loop.exec(); -} - -int test3() { - QEventLoop loop; - TIMED_EXIT(3, loop); - - static auto task3 = new DAsync(config->o); - - static int i = 0; - while (i < 100) { - task3->postData(QString::number(i++)); - } - - task3->post([](QString arg) -> QString { - - XLog() << "async task: " << arg; - return arg; - - })->then([](QString arg) { - - XLog() << "get result " << arg; - - })->start(); - - // task3->waitForFinished(); - // task3->deleteLater(); - - return loop.exec(); -} - -int test4() { - QEventLoop loop; - TIMED_EXIT(3, loop); - - class Test : public QObject { - public: - Test(int in, QObject *parent = nullptr) - : QObject (parent) - , count (in) - { - } - int count = 0; - }; - - static auto task4 = new DAsync(config->o); - static int i = 0; - - while (i < 100) { - task4->postData(new Test(i++, config->o)); - } - - task4->post([](Test *arg) -> Test * { - - XLog() << "async task: " << arg->count; - return arg; - - })->then([](Test *arg) { - - XLog() << "get result " << arg->count; - - })->start(); - - return loop.exec(); -} - -int test5() { - QEventLoop loop; - // TIMED_EXIT(3, loop); - static bool stopFlag = false; - QTimer::singleShot(3 * 1000, [&]{ - stopFlag = true; - loop.exit(); - }); - - static auto task5 = new DAsync(config->o); - static int i = 0; - - while (i < 100) { - task5->postData(QString::number(i++)); - } - - task5->post([](QString arg) { - - XLog() << "async task." << arg; - - })->then([]() { - - XLog() << "get void"; - - })->start(); - - OPT_THREAD_BEGIN - while (!stopFlag) { - usleep(200 * 1000); - task5->postData(QString::number(i++)); - } - OPT_THREAD_END - - return loop.exec(); -} - -int test6() { - QEventLoop loop; - TIMED_EXIT(1, loop); - - static auto task6 = new DAsync(config->o); - - task6->post([]() { - - XLog() << "async task."; - - })->then([]() { - - XLog() << "get result."; - - })->start(); - - // 如果只想在子线程执行一个任务,不需要主线程的任何处理,按照以下方式, - // 其实也只是只设置一个函数就可以了: - // task6->post([]() { XLog() << "async task."; }); - // task6->startUp(); - - return loop.exec(); -} - -int test7() { - QEventLoop loop; - TIMED_EXIT(1, loop); - - static auto task7 = new DAsync(config->o); - static int i = 0; - - task7->post([&]() { - - XLog() << "async task."; - return QString("%1").arg(i++); - - })->then([](QString arg) { - - XLog() << "get result " << arg; - - })->start(); - - return loop.exec(); -} - -int test8() { - QEventLoop loop; - TIMED_EXIT(1, loop); - - static auto task8 = new DAsync(config->o); - - // 注意,任务是异步执行的,传进去的一定不能是栈区变量! - static int i = 0; - task8->post([&]() -> QString { - Q_ASSERT(!D_THREAD_IN_MAIN()); - QWidget *w = DThreadUtil::runInMainThread([](){ - Q_ASSERT(D_THREAD_IN_MAIN()); - QWidget *w = new QWidget(config->w); - w->setBackgroundRole(QPalette::Text); - w->show(); - return w; - }); - - // 在外面调用并不合适,虽然也能显示出来。比如 mac 上这么用就显示不出来 - // w->setBackgroundRole(QPalette::Text); - // w->show(); - - XLog() << "async task." << QString("%1").arg(i++); - return QString("%1").arg(i++); - - })->then([](QString str) { - - XLog() << "get result " << str; - - })->start(); - - return loop.exec(); -} diff --git a/examples/dlog-example/CMakeLists.txt b/examples/dlog-example/CMakeLists.txt new file mode 100644 index 0000000..9999110 --- /dev/null +++ b/examples/dlog-example/CMakeLists.txt @@ -0,0 +1,16 @@ +set(BIN_NAME dlog${DTK_VERSION_MAJOR}) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) + +add_executable(${BIN_NAME} + main.cpp +) + +target_link_libraries( + ${BIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::Core + ${LIB_NAME} +) +target_include_directories(${BIN_NAME} PUBLIC + ../../include/ +) diff --git a/examples/dlog-example/main.cpp b/examples/dlog-example/main.cpp new file mode 100644 index 0000000..dca30a0 --- /dev/null +++ b/examples/dlog-example/main.cpp @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include +#include + +DCORE_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); +#ifdef Q_OS_LINUX + DLogManager::registerJournalAppender(); +#endif + DLogManager::registerConsoleAppender(); + dDebug() << "Anything that can possibly go wrong, will go wrong. "; + qWarning() << "FBI Warning: Code smells."; + qInfo() << "Why dark mode? Because light attracts bugs"; + qCritical() << "You Should Never Run `sudo rm -rf /`"; + + { + dDebugTime("Test the running time of a code block"); + QTimer timer; + timer.setInterval(500); + QEventLoop loop; + QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); + timer.start(); + loop.exec(); + } + + return app.exec(); +} diff --git a/examples/expintf-example/CMakeLists.txt b/examples/expintf-example/CMakeLists.txt index 9cdb1e4..bf31c5a 100644 --- a/examples/expintf-example/CMakeLists.txt +++ b/examples/expintf-example/CMakeLists.txt @@ -1,17 +1,17 @@ -set(BINNAME exprintf) +set(BIN_NAME exprintf${DTK_VERSION_MAJOR}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -find_package(Qt5 REQUIRED COMPONENTS DBus) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) -add_executable(${BINNAME} +add_executable(${BIN_NAME} main.cpp ) target_link_libraries( - ${BINNAME} PRIVATE - Qt5::DBus - dtkcore + ${BIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::DBus + ${LIB_NAME} ) -target_include_directories(${BINNAME} PUBLIC +target_include_directories(${BIN_NAME} PUBLIC ../../include/base ../../include/base/private/ ../../include/filesystem/ diff --git a/examples/filewatcher-example/CMakeLists.txt b/examples/filewatcher-example/CMakeLists.txt new file mode 100644 index 0000000..0b0f1e5 --- /dev/null +++ b/examples/filewatcher-example/CMakeLists.txt @@ -0,0 +1,18 @@ +set(BIN_NAME filewatcher${DTK_VERSION_MAJOR}) + +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) + +add_executable(${BIN_NAME} + main.cpp +) + +target_link_libraries( + ${BIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::Core + ${LIB_NAME} +) + +target_include_directories(${BIN_NAME} PUBLIC + ../../include/filesystem/ + ../../include/ +) diff --git a/examples/filewatcher-example/main.cpp b/examples/filewatcher-example/main.cpp new file mode 100644 index 0000000..570d037 --- /dev/null +++ b/examples/filewatcher-example/main.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "filesystem/dfilewatchermanager.h" +#include +#include +#include +DCORE_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + DFileWatcherManager manager; + QTemporaryFile tmpfile1; + tmpfile1.open(); + QFile file1(tmpfile1.fileName()); + QTemporaryFile tmpfile2; + tmpfile2.open(); + QFile file2(tmpfile2.fileName()); + + manager.add(tmpfile1.fileName()); + manager.add(tmpfile2.fileName()); + + QObject::connect(&manager, &Dtk::Core::DFileWatcherManager::fileModified, &app, [=](const QString value) { + qDebug() << "文件发生变动:" << value; + }); + + QObject::connect(&manager, &Dtk::Core::DFileWatcherManager::fileDeleted, &app, [=](const QString value) { + qDebug() << "文件被删除:" << value; + }); + + file1.open(QIODevice::WriteOnly | QIODevice::Text); + file1.write("test"); + file1.flush(); + file1.close(); + + file2.open(QIODevice::WriteOnly | QIODevice::Text); + file2.write("test"); + file2.close(); + + qDebug() << manager.watchedFiles(); + qDebug() << "---------------------------"; + app.processEvents(); + manager.removeAll(); + qDebug() << manager.watchedFiles(); + return app.exec(); +} diff --git a/examples/textcodec-example/CMakeLists.txt b/examples/textcodec-example/CMakeLists.txt new file mode 100644 index 0000000..04e1dd9 --- /dev/null +++ b/examples/textcodec-example/CMakeLists.txt @@ -0,0 +1,18 @@ +set(BIN_NAME textcodec${DTK_VERSION_MAJOR}) + +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) + +add_executable(${BIN_NAME} + main.cpp +) + +target_link_libraries( + ${BIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::Core + ${LIB_NAME} +) + +target_include_directories(${BIN_NAME} PUBLIC + ../../include/util/ + ../../include/ +) diff --git a/examples/textcodec-example/main.cpp b/examples/textcodec-example/main.cpp new file mode 100644 index 0000000..a47eedf --- /dev/null +++ b/examples/textcodec-example/main.cpp @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include + +#include +#include +#include +#include + +DCORE_USE_NAMESPACE + +void convertFileEncoding(const QString &fromFile, + const QString &toFile, + const QByteArray &toEncoding, + const QByteArray &fromEncoding = QByteArray()) +{ + QByteArray contentEncoding = fromEncoding; + if (contentEncoding.isEmpty()) { + bool isOk = false; + contentEncoding = DTextEncoding::detectFileEncoding(fromFile, &isOk); + if (!isOk) { + qInfo().noquote() << QString("Detect file %1 encoding failed").arg(fromFile); + return; + } + } + + QString errString; + if (!DTextEncoding::convertFileEncodingTo(fromFile, toFile, toEncoding, contentEncoding, &errString)) { + qInfo().noquote() << QString("Convert file %1 encoding from %2 to %3 failed. error: %4") + .arg(fromFile) + .arg(QString::fromUtf8(contentEncoding)) + .arg(QString::fromUtf8(toEncoding)) + .arg(errString); + } else { + qInfo().noquote() << QString("Convert file %1 encoding from %2 to %3 successed.") + .arg(fromFile) + .arg(QString::fromUtf8(contentEncoding)) + .arg(QString::fromUtf8(toEncoding)); + } +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName("Text codec"); + + QCommandLineOption toEncodingOption({"t", "toEncoding"}, "Convert file encoding to specified encoding.", "encoding"); + QCommandLineOption fromEncodingOption({"f", "fromEncoding"}, "Convert file encoding from specified encoding.", "encoding"); + QCommandLineOption outputOption( + {"o", "output"}, "Save converted text with file path, only supported when opening a single file.", "path"); + + QCommandLineParser parser; + parser.setApplicationDescription("Text codec, provide encoding detection and encoding conversion."); + parser.addHelpOption(); + parser.addOption(toEncodingOption); + parser.addOption(fromEncodingOption); + parser.addOption(outputOption); + parser.addPositionalArgument("file", "Open file.", "[file...]"); + parser.process(app); + + const QStringList args = parser.positionalArguments(); + if (args.isEmpty()) { + parser.showHelp(); + } + + const QStringList fileArgs = parser.positionalArguments(); + if (fileArgs.isEmpty()) { + qInfo().noquote() << "Not set open file."; + return 0; + } + + if (parser.isSet(outputOption)) { + if (fileArgs.size() > 1) { + qInfo().noquote() << "Output file path only supported when opening a single file."; + return 0; + } else if (!parser.isSet(toEncodingOption)) { + qInfo().noquote() << "Convert file with not set convert encoding."; + } else { + QString fromFile = fileArgs.first(); + QString toFile = parser.value(outputOption); + QByteArray toEncoding = parser.value(toEncodingOption).toUtf8(); + + convertFileEncoding(fromFile, toFile, toEncoding, parser.value(fromEncodingOption).toUtf8()); + return 0; + } + } + + QByteArray toEncoding = parser.value(toEncodingOption).toUtf8(); + for (QString fileName : fileArgs) { + if (toEncoding.isEmpty()) { + // Only display file encoding. + qInfo().noquote() << fileName << DTextEncoding::detectFileEncoding(fileName); + } else { + // Convert file encoding. + convertFileEncoding(fileName, fileName, toEncoding, parser.value(fromEncodingOption).toUtf8()); + } + } + + return 0; +} diff --git a/include/DtkCore/DDBusExtended b/include/DtkCore/DDBusExtended deleted file mode 100644 index 2798dc4..0000000 --- a/include/DtkCore/DDBusExtended +++ /dev/null @@ -1 +0,0 @@ -#include "ddbusextended.h" diff --git a/include/DtkCore/DLicenseInfo b/include/DtkCore/DLicenseInfo new file mode 100644 index 0000000..75e6ac4 --- /dev/null +++ b/include/DtkCore/DLicenseInfo @@ -0,0 +1 @@ +#include "dlicenseinfo.h" diff --git a/include/DtkCore/DLog b/include/DtkCore/DLog index a9ab429..0c4a85a 100644 --- a/include/DtkCore/DLog +++ b/include/DtkCore/DLog @@ -1,7 +1,9 @@ -#include "RollingFileAppender.h" -#include "Logger.h" -#include "LogManager.h" -#include "FileAppender.h" -#include "ConsoleAppender.h" -#include "AbstractStringAppender.h" -#include "AbstractAppender.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/include/DtkCore/DTextEncoding b/include/DtkCore/DTextEncoding new file mode 100644 index 0000000..7c66759 --- /dev/null +++ b/include/DtkCore/DTextEncoding @@ -0,0 +1 @@ +#include "dtextencoding.h" diff --git a/include/base/dexpected.h b/include/base/dexpected.h index a44514c..5dbe9bb 100644 --- a/include/base/dexpected.h +++ b/include/base/dexpected.h @@ -369,6 +369,7 @@ private: * 模板类Dtk::Core::DExpected提供存储两个值之一的方式。Dtk::Core::DExpected的对象要么保有一个期待的T类型值,要么保有一个不期待的E类型值,不会没有值。 * @tparam T 期待的类型 * @tparam E 不期待的类型 + * @note 该类自DtkCore 5.6.3引入 */ template class DExpected @@ -469,18 +470,11 @@ public: { } - /*! - * @brief Dtk::Core::DExpected的默认拷贝构造函数 - */ - DExpected(const DExpected &) = default; - /*! * @brief Dtk::Core::DExpected的拷贝构造函数 */ - template ::value and std::is_copy_constructible::value and - (!std::is_trivially_copy_constructible::value or - !std::is_trivially_copy_constructible::value), - bool>::type = true> + template < + typename std::enable_if::value and std::is_copy_constructible::value, bool>::type = true> DExpected(const DExpected &_x) noexcept( std::is_nothrow_copy_constructible::value and std::is_nothrow_copy_constructible::value) : m_has_value(_x.m_has_value) @@ -491,18 +485,11 @@ public: construct_at(std::addressof(m_error), _x.m_error); } - /*! - * @brief Dtk::Core::DExpected的默认移动构造函数 - */ - DExpected(DExpected &&) = default; - /*! * @brief Dtk::Core::DExpected的移动构造函数 */ - template ::value and std::is_move_constructible::value and - (!std::is_trivially_move_constructible::value or - !std::is_trivially_move_constructible::value), - bool>::type = true> + template < + typename std::enable_if::value and std::is_move_constructible::value, bool>::type = true> DExpected(DExpected &&_x) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_constructible::value) : m_has_value(_x.m_has_value) @@ -1244,10 +1231,7 @@ public: { } - DExpected(const DExpected &) = default; - - template ::value and !std::is_trivially_copy_constructible::value, - bool>::type = true> + template ::value, bool>::type = true> DExpected(const DExpected &_x) noexcept(std::is_nothrow_copy_constructible::value) : m_has_value(_x.m_has_value) , m_void() @@ -1256,10 +1240,7 @@ public: construct_at(std::addressof(m_error), _x.m_error); } - DExpected(DExpected &&) = default; - - template ::value and !std::is_trivially_move_constructible::value, - bool>::type = true> + template ::value, bool>::type = true> DExpected(DExpected &&_x) noexcept(std::is_nothrow_move_constructible::value) : m_has_value(_x.m_has_value) , m_void() diff --git a/include/base/dsingleton.h b/include/base/dsingleton.h index e8a9cbd..2ddcb2d 100644 --- a/include/base/dsingleton.h +++ b/include/base/dsingleton.h @@ -45,13 +45,14 @@ template class LIBDTKCORESHARED_EXPORT DSingleton { public: +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QT_DEPRECATED_X("Use ref") static inline T *instance() { static T *_instance = new T; return _instance; } - +#endif static T& ref() { static T instance; diff --git a/include/dci/ddcifile.h b/include/dci/ddcifile.h index 09c2d45..848ac4c 100644 --- a/include/dci/ddcifile.h +++ b/include/dci/ddcifile.h @@ -16,7 +16,7 @@ #include -QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE diff --git a/include/filesystem/dcapfile.h b/include/filesystem/dcapfile.h index 826391e..49995df 100644 --- a/include/filesystem/dcapfile.h +++ b/include/filesystem/dcapfile.h @@ -31,7 +31,7 @@ public: bool exists() const; static bool exists(const QString &fileName); -#if QT_DEPRECATED_SINCE(5, 13) +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED_X("Use QFile::symLinkTarget() instead") QString readLink() const; #endif diff --git a/include/filesystem/dcapmanager.h b/include/filesystem/dcapmanager.h index 35b206e..b4e7787 100644 --- a/include/filesystem/dcapmanager.h +++ b/include/filesystem/dcapmanager.h @@ -18,9 +18,12 @@ class DCapManager : public QObject, public DObject D_DECLARE_PRIVATE(DCapManager) public: static DCapManager *instance(); +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + QT_DEPRECATED_X("This api will no longer take effect, please use DCapDir or DCapFile") static void registerFileEngine(); + QT_DEPRECATED_X("This api will no longer take effect, please use DCapDir or DCapFile") static void unregisterFileEngine(); - +#endif void appendPath(const QString &path); void appendPaths(const QStringList &pathList); diff --git a/include/filesystem/dfilewatchermanager.h b/include/filesystem/dfilewatchermanager.h index 355564b..66a3cf8 100644 --- a/include/filesystem/dfilewatchermanager.h +++ b/include/filesystem/dfilewatchermanager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,6 +9,7 @@ #include "dobject.h" #include +#include DCORE_BEGIN_NAMESPACE @@ -25,7 +26,8 @@ public: DFileWatcher *add(const QString &filePath); void remove(const QString &filePath); - + void removeAll(); + QStringList watchedFiles() const; Q_SIGNALS: void fileDeleted(const QString &filePath); void fileAttributeChanged(const QString &filePath); diff --git a/include/filesystem/dstandardpaths.h b/include/filesystem/dstandardpaths.h index f2f1f34..0a32700 100644 --- a/include/filesystem/dstandardpaths.h +++ b/include/filesystem/dstandardpaths.h @@ -29,11 +29,33 @@ public: static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList()); static void setMode(Mode mode); + /** + * @brief About XDG dir, view it in https://gitlab.freedesktop.org/xdg/xdg-specs/ + */ enum class XDG { + /* + * @brief DataHome, usually is ~/.local/share, also can be defined by ${XDG_DATA_HOME}, where stores the data of applications + */ DataHome, + /* + * @brief ConfigHome, usually is ~/.config, can be defined by ${XDG_CONFIG_HOME}, where stores the config of applications + */ ConfigHome, + /* + * @brief CacheHome, usually is ~/.cache, can be defined by ${XDG_CACHE_HOME}, where stores caches, can be always cleared + */ CacheHome, - RuntimeTime + /* + * @brief Where temp files or sock files always be put in, like sddm.sock. It is unique per session. It is /run/user/${uid} or ${XDG_RUNTIME_DIR}, + */ + RuntimeDir, +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + RuntimeTime [[deprecated("Use RuntimeDir Instead")]] = RuntimeDir, +#endif + /* + * @brief where history file and state file should be. It is induced because users do not want to mix their config files and state files. It is always ~/.local/state, or defined by ${XDG_STATE_HOME} + */ + StateHome }; enum class DSG { @@ -43,6 +65,9 @@ public: static QString homePath(); static QString homePath(const uint uid); + /* + * @brief Get the XDG dir path by XDG type + */ static QString path(XDG type); static QString path(DSG type); static QStringList paths(DSG type); diff --git a/include/global/dconfig.h b/include/global/dconfig.h index dc405ae..8759a48 100644 --- a/include/global/dconfig.h +++ b/include/global/dconfig.h @@ -22,6 +22,7 @@ public: virtual void setValue(const QString &/*key*/, const QVariant &/*value*/) = 0; virtual void reset(const QString &key) { setValue(key, QVariant());} virtual QString name() const {return QString("");} + virtual bool isDefaultValue(const QString &/*key*/) const { return true; } }; class DConfigPrivate; @@ -43,12 +44,19 @@ public: QObject *parent = nullptr); static DConfig *create(DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath = QString(), QObject *parent = nullptr); + static DConfig *createGeneric(const QString &name, const QString &subpath = QString(), + QObject *parent = nullptr); + static DConfig *createGeneric(DConfigBackend *backend, const QString &name, const QString &subpath = QString(), + QObject *parent = nullptr); + + static void setAppId(const QString &appId); QString backendName() const; QStringList keyList() const; bool isValid() const; + bool isDefaultValue(const QString &key) const; QVariant value(const QString &key, const QVariant &fallback = QVariant()) const; void setValue(const QString &key, const QVariant &value); void reset(const QString &key); diff --git a/include/global/dconfigfile.h b/include/global/dconfigfile.h index cd4fd8c..5959fd9 100644 --- a/include/global/dconfigfile.h +++ b/include/global/dconfigfile.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -28,7 +28,8 @@ class LIBDTKCORESHARED_EXPORT DConfigFile : public DObject{ public: enum Flag { NoOverride = 1 << 0, - Global = 1 << 1 + Global = 1 << 1, + UserPublic = 1 << 2 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -61,6 +62,7 @@ public: bool isValid() const; QVariant value(const QString &key, DConfigCache *userCache = nullptr) const; + QVariant cacheValue(DConfigCache *userCache, const QString &key) const; bool setValue(const QString &key, const QVariant &value, const QString &callerAppid, DConfigCache *userCache = nullptr); @@ -96,6 +98,8 @@ public: virtual QStringList allOverrideDirs(const bool useAppId, const QString &prefix = QString()) const = 0; virtual QVariant value(const QString &key) const = 0; + static QStringList genericMetaDirs(const QString &localPrefix = QString()); + static QStringList applicationMetaDirs(const QString &localPrefix, const QString &appId); }; class LIBDTKCORESHARED_EXPORT DConfigCache { @@ -114,6 +118,8 @@ public: virtual QVariant value(const QString &key) const = 0; virtual int serial(const QString &key) const = 0; virtual uint uid() const = 0; + + virtual void setCachePathPrefix(const QString &prefix) = 0; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/include/global/ddesktopentry.h b/include/global/ddesktopentry.h index 877bdfd..9333035 100644 --- a/include/global/ddesktopentry.h +++ b/include/global/ddesktopentry.h @@ -18,13 +18,13 @@ class LIBDTKCORESHARED_EXPORT DDesktopEntry Q_GADGET public: enum EntryType { - Unknown = 0, //!< Unknown desktop file type. Maybe is invalid. - Application, //!< The file describes application. - Link, //!< The file describes URL. - Directory, //!< The file describes directory settings. - ServiceType, //!< KDE specific type. mentioned in the spec, so listed here too. - Service, //!< KDE specific type. mentioned in the spec, so listed here too. - FSDevice //!< KDE specific type. mentioned in the spec, so listed here too. + Unknown = 0, //!<@~english Unknown desktop file type. Maybe is invalid. + Application, //!<@~english The file describes application. + Link, //!<@~english The file describes URL. + Directory, //!<@~english The file describes directory settings. + ServiceType, //!<@~english KDE specific type. mentioned in the spec, so listed here too. + Service, //!<@~english KDE specific type. mentioned in the spec, so listed here too. + FSDevice //!<@~english KDE specific type. mentioned in the spec, so listed here too. }; Q_ENUM(EntryType) @@ -39,9 +39,9 @@ public: Q_ENUM(ValueType) enum Status { - NoError = 0, //!< No error occurred. - AccessError, //!< An access error occurred (e.g. trying to write to a read-only file). - FormatError //!< A format error occurred (e.g. loading a malformed desktop entry file). + NoError = 0, //!<@~english No error occurred. + AccessError, //!<@~english An access error occurred (e.g. trying to write to a read-only file). + FormatError //!<@~english A format error occurred (e.g. loading a malformed desktop entry file). }; Q_ENUM(Status) diff --git a/include/global/dlicenseinfo.h b/include/global/dlicenseinfo.h new file mode 100644 index 0000000..1aa182b --- /dev/null +++ b/include/global/dlicenseinfo.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DLICENSEINFO_H +#define DLICENSEINFO_H + +#include + +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DLicenseInfoPrivate; +class LIBDTKCORESHARED_EXPORT DLicenseInfo : public DObject +{ +public: + explicit DLicenseInfo(DObject *parent = nullptr); + + bool loadContent(const QByteArray &content); + bool loadFile(const QString &file); + void setLicenseSearchPath(const QString &path); + QByteArray licenseContent(const QString &licenseName); + + class DComponentInfoPrivate; + class LIBDTKCORESHARED_EXPORT DComponentInfo : public DObject + { + public: + explicit DComponentInfo(DObject *parent = nullptr); + ~DComponentInfo() override; + + QString name() const; + QString version() const; + QString copyRight() const; + QString licenseName() const; + + private: + D_DECLARE_PRIVATE(DComponentInfo) + friend class DLicenseInfoPrivate; + }; + using DComponentInfos = QVector; + DComponentInfos componentInfos() const; + +private: + D_DECLARE_PRIVATE(DLicenseInfo) +}; + +DCORE_END_NAMESPACE + +#endif // DLICENSEINFO_H diff --git a/include/global/dsysinfo.h b/include/global/dsysinfo.h index 807f111..89eacf9 100644 --- a/include/global/dsysinfo.h +++ b/include/global/dsysinfo.h @@ -38,7 +38,8 @@ public: DeepinDesktop, DeepinProfessional, DeepinServer, - DeepinPersonal + DeepinPersonal, + DeepinMilitary }; enum LogoType { @@ -49,9 +50,9 @@ public: }; enum OrgType { - Distribution, //!< distribution itself - Distributor, //!< distributer of the current distribution - Manufacturer //!< manufacturer of the current distribution or device + Distribution, //!<@~english distribution itself + Distributor, //!<@~english distributer of the current distribution + Manufacturer //!<@~english manufacturer of the current distribution or device }; enum UosType { @@ -59,6 +60,7 @@ public: UosDesktop, UosServer, UosDevice, + UosSmart, UosTypeCount // must at last }; @@ -138,9 +140,11 @@ public: static QString deepinCopyright(); // uos version interface - Q_DECL_DEPRECATED_X("Use arch() instead") static UosType uosType(); + static UosType uosType(); static UosEdition uosEditionType(); - static UosArch uosArch(); +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + Q_DECL_DEPRECATED_X("Use arch() instead") static UosArch uosArch(); +#endif static QString uosProductTypeName(const QLocale &locale = QLocale::system()); static QString uosSystemName(const QLocale &locale = QLocale::system()); static QString uosEditionName(const QLocale &locale = QLocale::system()); @@ -152,16 +156,18 @@ public: static QString buildVersion(); // xyzs #endif +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) Q_DECL_DEPRECATED_X("Use distributionInfoPath() instead") static QString deepinDistributionInfoPath(); + Q_DECL_DEPRECATED_X("Use distributionOrgName() instead") static QString deepinDistributorName(); + Q_DECL_DEPRECATED_X("Use distributionOrgWebsite() instead") static QPair deepinDistributorWebsite(); + Q_DECL_DEPRECATED_X("Use distributionOrgLogo() instead") static QString deepinDistributorLogo(LogoType type = Normal, const QString & fallback = QString()); +#endif static QString distributionInfoPath(); static QString distributionInfoSectionName(OrgType type); static QString distributionOrgName(OrgType type = Distribution, const QLocale &locale = QLocale::system()); - Q_DECL_DEPRECATED_X("Use deepinDistributionOrgName() instead") static QString deepinDistributorName(); static QPair distributionOrgWebsite(OrgType type = Distribution); - Q_DECL_DEPRECATED_X("Use deepinDistributionOrgWebsite() instead") static QPair deepinDistributorWebsite(); static QString distributionOrgLogo(OrgType orgType = Distribution, LogoType type = Normal, const QString & fallback = QString()); - Q_DECL_DEPRECATED_X("Use deepinDistributionOrgLogo() instead") static QString deepinDistributorLogo(LogoType type = Normal, const QString & fallback = QString()); static QString operatingSystemName(); static ProductType productType(); diff --git a/include/global/dtkcore_global.h b/include/global/dtkcore_global.h index c3efe0c..504c944 100644 --- a/include/global/dtkcore_global.h +++ b/include/global/dtkcore_global.h @@ -47,14 +47,26 @@ #define D_DECL_DEPRECATED_X(text) Q_DECL_HIDDEN #define D_DECL_DEPRECATED Q_DECL_HIDDEN #else +#ifdef __GNUC__ +#if __GNUC__ < 13 +#define D_DECL_DEPRECATED __attribute__((__deprecated__)) +#define D_DECL_DEPRECATED_X(text) __attribute__((__deprecated__(text))) +#else #define D_DECL_DEPRECATED Q_DECL_DEPRECATED #define D_DECL_DEPRECATED_X Q_DECL_DEPRECATED_X #endif +#else +#define D_DECL_DEPRECATED Q_DECL_DEPRECATED +#define D_DECL_DEPRECATED_X Q_DECL_DEPRECATED_X +#endif +#endif #define DTK_VERSION_CHECK(major, minor, patch, build) ((major<<24)|(minor<<16)|(patch<<8)|build) #define DTK_VERSION DTK_VERSION_CHECK(DTK_VERSION_MAJOR, DTK_VERSION_MINOR, DTK_VERSION_PATCH, DTK_VERSION_BUILD) +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) extern "C" { int LIBDTKCORESHARED_EXPORT dtkVersion(); const LIBDTKCORESHARED_EXPORT char *dtkVersionString(); } +#endif diff --git a/include/log/AbstractAppender.h b/include/log/AbstractAppender.h deleted file mode 100644 index 9435da3..0000000 --- a/include/log/AbstractAppender.h +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef ABSTRACTAPPENDER_H -#define ABSTRACTAPPENDER_H - -#include "dtkcore_global.h" -#include - -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT AbstractAppender -{ -public: - AbstractAppender(); - virtual ~AbstractAppender(); - - Logger::LogLevel detailsLevel() const; - void setDetailsLevel(Logger::LogLevel level); - void setDetailsLevel(const QString &level); - - void write(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg); - -protected: - virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg) = 0; - -private: - QMutex m_writeMutex; - - Logger::LogLevel m_detailsLevel; - mutable QMutex m_detailsLevelMutex; -}; - -DCORE_END_NAMESPACE -#endif // ABSTRACTAPPENDER_H diff --git a/include/log/AbstractStringAppender.h b/include/log/AbstractStringAppender.h deleted file mode 100644 index 3172c8b..0000000 --- a/include/log/AbstractStringAppender.h +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef ABSTRACTSTRINGAPPENDER_H -#define ABSTRACTSTRINGAPPENDER_H - -#include "AbstractAppender.h" - -#include -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT AbstractStringAppender : public AbstractAppender -{ -public: - AbstractStringAppender(); - virtual QString format() const; - void setFormat(const QString &format); - - static QString stripFunctionName(const char *name); -protected: - QString formattedString(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg) const; - -private: - static QByteArray qCleanupFuncinfo(const char*); - - QString m_format; - mutable QReadWriteLock m_formatLock; -}; - -DCORE_END_NAMESPACE -#endif // ABSTRACTSTRINGAPPENDER_H diff --git a/include/log/ConsoleAppender.h b/include/log/ConsoleAppender.h deleted file mode 100644 index be63061..0000000 --- a/include/log/ConsoleAppender.h +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef CONSOLEAPPENDER_H -#define CONSOLEAPPENDER_H - -#include "dtkcore_global.h" -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT ConsoleAppender : public AbstractStringAppender -{ -public: - ConsoleAppender(); - virtual QString format() const; - void ignoreEnvironmentPattern(bool ignore); - -protected: - virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg); - -private: - bool m_ignoreEnvPattern; -}; - -DCORE_END_NAMESPACE - -#endif // CONSOLEAPPENDER_H diff --git a/include/log/FileAppender.h b/include/log/FileAppender.h deleted file mode 100644 index 9f5e378..0000000 --- a/include/log/FileAppender.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef FILEAPPENDER_H -#define FILEAPPENDER_H - -// Logger -#include "dtkcore_global.h" -#include - -// Qt -#include -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT FileAppender : public AbstractStringAppender -{ -public: - FileAppender(const QString &fileName = QString()); - ~FileAppender(); - - QString fileName() const; - void setFileName(const QString &s); - - qint64 size() const; - -protected: - virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg); - bool openFile(); - void closeFile(); - -private: - QFile m_logFile; - QTextStream m_logStream; - mutable QMutex m_logFileMutex; -}; - -DCORE_END_NAMESPACE - -#endif // FILEAPPENDER_H diff --git a/include/log/LogManager.h b/include/log/LogManager.h index 8e761f1..ab07805 100644 --- a/include/log/LogManager.h +++ b/include/log/LogManager.h @@ -6,20 +6,20 @@ #ifndef LOGMANAGER_H #define LOGMANAGER_H -#include +#include #include "dtkcore_global.h" DCORE_BEGIN_NAMESPACE -class ConsoleAppender; -class RollingFileAppender; - +class DLogManagerPrivate; class LIBDTKCORESHARED_EXPORT DLogManager { + Q_DISABLE_COPY(DLogManager) public: static void registerConsoleAppender(); static void registerFileAppender(); + static void registerJournalAppender(); static QString getlogFilePath(); @@ -32,13 +32,9 @@ public: static void setLogFormat(const QString &format); private: - QString m_format; - QString m_logPath; - ConsoleAppender* m_consoleAppender; - RollingFileAppender* m_rollingFileAppender; - void initConsoleAppender(); void initRollingFileAppender(); + void initJournalAppender(); QString joinPath(const QString &path, const QString &fileName); inline static DLogManager* instance(){ @@ -47,8 +43,9 @@ private: } explicit DLogManager(); ~DLogManager(); - DLogManager(const DLogManager &); - DLogManager & operator = (const DLogManager &); + + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(DLogManager) }; DCORE_END_NAMESPACE diff --git a/include/log/Logger.h b/include/log/Logger.h deleted file mode 100644 index d69557e..0000000 --- a/include/log/Logger.h +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later -#ifndef LOGGER_H -#define LOGGER_H - -#include -#include -#include - -#include "dloggerdefs.h" - -DCORE_BEGIN_NAMESPACE - -class AbstractAppender; -class LoggerPrivate; -class LIBDTKCORESHARED_EXPORT Logger -{ - Q_DISABLE_COPY(Logger) -public: - //! the log levels - enum LogLevel { - Trace, //!< ~english Trace level. Can be used for mostly unneeded records used for internal code tracing. - Debug, //!< ~english Debug level.for the debugging of the software. - Info, //!< ~english Info level. Can be used for informational records, which may be interesting for not only developers. - Warning, //!< ~english Warning. May be used to log some non-fatal warnings detected by your application. - Error, //!< ~english May be used for a big problems making your application work wrong but not crashing. - Fatal //!< ~english Fatal. Used for unrecoverable errors, crashes the application (abort) right after the log record is written. - }; - - Logger(); - Logger(const QString &defaultCategory); - ~Logger(); - - static Logger *globalInstance(); - - static QString levelToString(LogLevel level); - static LogLevel levelFromString(const QString &str); - - void registerAppender(AbstractAppender *appender); - void registerCategoryAppender(const QString &category, AbstractAppender *appender); - - void logToGlobalInstance(const QString &category, bool logToGlobal = false); - - void setDefaultCategory(const QString &category); - QString defaultCategory() const; - - void write(const QDateTime &time, LogLevel level, const char *file, int line, - const char *func, const char *category, const QString &msg); - void write(LogLevel level, const char *file, int line, - const char *func, const char *category, const QString &msg); - QDebug write(LogLevel level, const char *file, int line, - const char *func, const char *category); - void writeAssert(const char *file, int line, - const char *func, const char *condition); - -private: - void write(const QDateTime &time, LogLevel level, const char *file, int line, - const char *func, const char *category, - const QString &msg, bool fromLocalInstance); - Q_DECLARE_PRIVATE(Logger) - LoggerPrivate *d_ptr; -}; - - -class LIBDTKCORESHARED_EXPORT CuteMessageLogger -{ - Q_DISABLE_COPY(CuteMessageLogger) - -public: - Q_DECL_CONSTEXPR CuteMessageLogger(Logger *l, Logger::LogLevel level, - const char *file, int line, const char *func) - : m_l(l), - m_level(level), - m_file(file), - m_line(line), - m_function(func), - m_category(nullptr) - {} - - Q_DECL_CONSTEXPR CuteMessageLogger(Logger *l, Logger::LogLevel level, const char *file, - int line, const char *func, const char *category) - : m_l(l), - m_level(level), - m_file(file), - m_line(line), - m_function(func), - m_category(category) - {} - - void write(const char *msg, ...) const -#if defined(Q_CC_GNU) && !defined(__INSURE__) - #if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG) - __attribute__((format(gnu_printf, 2, 3))); - #else - __attribute__((format(printf, 2, 3))); - #endif -#endif - - void write(const QString &msg) const; - QDebug write() const; - -private: - Logger *m_l; - Logger::LogLevel m_level; - const char *m_file; - int m_line; - const char *m_function; - const char *m_category; -}; - -class LIBDTKCORESHARED_EXPORT LoggerTimingHelper -{ - Q_DISABLE_COPY(LoggerTimingHelper) -public: - inline explicit LoggerTimingHelper(Logger *l, Logger::LogLevel level, - const char *file, int line, const char *func) - : m_logger(l), - m_logLevel(level), - m_file(file), - m_line(line), - m_function(func) - {} - - void start(const char *msg, ...) -#if defined(Q_CC_GNU) && !defined(__INSURE__) - #if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG) - __attribute__((format(gnu_printf, 2, 3))); - #else - __attribute__((format(printf, 2, 3))); - #endif -#endif - - void start(const QString &msg = QString()); - - ~LoggerTimingHelper(); - -private: - Logger *m_logger; - QTime m_time; - Logger::LogLevel m_logLevel; - const char *m_file; - int m_line; - const char *m_function; - QString m_block; -}; - -DCORE_END_NAMESPACE -#endif // LOGGER_H diff --git a/include/log/RollingFileAppender.h b/include/log/RollingFileAppender.h deleted file mode 100644 index 534c572..0000000 --- a/include/log/RollingFileAppender.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef ROLLINGFILEAPPENDER_H -#define ROLLINGFILEAPPENDER_H - -#include - -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT RollingFileAppender : public FileAppender -{ - public: - /*! - The enum DatePattern defines constants for date patterns. - \sa setDatePattern(DatePattern) - */ - enum DatePattern - { - /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */ - MinutelyRollover = 0, - /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */ - HourlyRollover, - /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */ - HalfDailyRollover, - /*! The daily date pattern string is "'.'yyyy-MM-dd". */ - DailyRollover, - /*! The weekly date pattern string is "'.'yyyy-ww". */ - WeeklyRollover, - /*! The monthly date pattern string is "'.'yyyy-MM". */ - MonthlyRollover - }; - - RollingFileAppender(const QString &fileName = QString()); - - DatePattern datePattern() const; - void setDatePattern(DatePattern datePattern); - void setDatePattern(const QString &datePattern); - - QString datePatternString() const; - - void setLogFilesLimit(int limit); - int logFilesLimit() const; - - void setLogSizeLimit(int qint64); - qint64 logSizeLimit() const; - - protected: - virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg); - - private: - void rollOver(); - void computeRollOverTime(); - void computeFrequency(); - void removeOldFiles(); - void setDatePatternString(const QString &datePatternString); - - QString m_datePatternString; - DatePattern m_frequency; - - QDateTime m_rollOverTime; - QString m_rollOverSuffix; - int m_logFilesLimit; - qint64 m_logSizeLimit; - mutable QMutex m_rollingMutex; -}; - -DCORE_END_NAMESPACE - -#endif // ROLLINGFILEAPPENDER_H diff --git a/include/log/dloggerdefs.h b/include/log/dloggerdefs.h deleted file mode 100644 index 8395103..0000000 --- a/include/log/dloggerdefs.h +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later -#ifndef DLOGGER_DEFINE_H -#define DLOGGER_DEFINE_H - -#include "dtkcore_global.h" - -DCORE_BEGIN_NAMESPACE - -class Logger; -class CuteMessageLogger; -class LoggerTimingHelper; -LIBDTKCORESHARED_EXPORT Logger *loggerInstance(); -#define logger loggerInstance() - -#define dTrace CuteMessageLogger(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO).write -#define dDebug CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO).write -#define dInfo CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO).write -#define dWarning CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO).write -#define dError CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO).write -#define dFatal CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO).write - -#define dCDebug(category) CuteMessageLogger(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO, category).write() -#define dCInfo(category) CuteMessageLogger(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO, category).write() -#define dCWarning(category) CuteMessageLogger(loggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO, category).write() -#define dCError(category) CuteMessageLogger(loggerInstance(), Logger::Error, __FILE__, __LINE__, Q_FUNC_INFO, category).write() -#define dCFatal(category) CuteMessageLogger(loggerInstance(), Logger::Fatal, __FILE__, __LINE__, Q_FUNC_INFO, category).write() - -#define dTraceTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start -#define dDebugTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start -#define dInfoTime LoggerTimingHelper loggerTimingHelper(loggerInstance(), Logger::Info, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start - -#define dAssert(cond) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, #cond) : qt_noop()) -#define dAssertX(cond, msg) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, msg) : qt_noop()) - -#define dCategory(category) \ - private:\ - Logger* loggerInstance()\ - {\ - static Logger customLoggerInstance(category);\ - return &customLoggerInstance;\ - }\ - -#define dGlobalCategory(category) \ - private:\ - Logger* loggerInstance()\ - {\ - static Logger customLoggerInstance(category);\ - customLoggerInstance.logToGlobalInstance(category, true);\ - return &customLoggerInstance;\ - }\ - -DCORE_END_NAMESPACE - -#endif // DLOGGER_DEFINE_H diff --git a/include/log/win32/OutputDebugAppender.h b/include/log/win32/OutputDebugAppender.h deleted file mode 100644 index 73bb115..0000000 --- a/include/log/win32/OutputDebugAppender.h +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: 2010 Karl-Heinz Reichel (khreichel at googlemail dot com) -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef OUTPUTDEBUGAPPENDER_H -#define OUTPUTDEBUGAPPENDER_H - -#include "dtkcore_global.h" -#include - -DCORE_BEGIN_NAMESPACE - -class LIBDTKCORESHARED_EXPORT OutputDebugAppender : public AbstractStringAppender -{ - protected: - virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg); -}; - -DCORE_END_NAMESPACE - -#endif // OUTPUTDEBUGAPPENDER_H diff --git a/include/util/dasync.h b/include/util/dasync.h index 957fb90..b25e78e 100644 --- a/include/util/dasync.h +++ b/include/util/dasync.h @@ -21,150 +21,162 @@ DCORE_BEGIN_NAMESPACE #define D_THREAD_IN_MAIN() (qApp->instance() && qApp->instance()->thread() == QThread::currentThread()) // TODO: 添加 DtkCorePrivate 到 dtkcore_global.h -namespace DtkCorePrivate +namespace DtkCorePrivate { +// 本类是继承实现的,只有子类方法是安全的,暂不对外提供接口 +template +class DSafeQueue : public QQueue { - // 本类是继承实现的,只有子类方法是安全的,暂不对外提供接口 - template - class DSafeQueue : public QQueue { - public: - inline void enqueue(const T &t) { - QMutexLocker lkc(&m_mtx); - QQueue::enqueue(t); - } - inline T dequeue() { - QMutexLocker lkc(&m_mtx); - return QQueue::dequeue(); - } - inline int size() { - QMutexLocker lkc(&m_mtx); - return QQueue::size(); - } - inline T &head() { - QMutexLocker lkc(&m_mtx); - return QQueue::head(); - } - inline const T &head() const { - QMutexLocker lkc(&m_mtx); - return QQueue::head(); - } - private: - mutable QMutex m_mtx; - }; +public: + inline void enqueue(const T &t) + { + QMutexLocker lkc(&m_mtx); + QQueue::enqueue(t); + } + inline T dequeue() + { + QMutexLocker lkc(&m_mtx); + return QQueue::dequeue(); + } + inline int size() + { + QMutexLocker lkc(&m_mtx); + return QQueue::size(); + } + inline T &head() + { + QMutexLocker lkc(&m_mtx); + return QQueue::head(); + } + inline const T &head() const + { + QMutexLocker lkc(&m_mtx); + return QQueue::head(); + } - // 内部使用,不对外提供接口 - class MainWorker : public QObject { +private: + mutable QMutex m_mtx; +}; + +// 内部使用,不对外提供接口 +class MainWorker : public QObject +{ Q_OBJECT - std::function m_handle; - std::function m_handleProxy; + std::function m_handle; + std::function m_handleProxy; - std::function m_handleV; - std::function m_handleVProxy; + std::function m_handleV; + std::function m_handleVProxy; - bool m_dasyncDestroyed = false; - char __padding[7]; - public: - void setDAsyncDestroyed() { - m_dasyncDestroyed = true; - } - bool dasyncDestroyed() { - return m_dasyncDestroyed; - } - public: - MainWorker(QObject *parent = nullptr) - : QObject (parent) - { - // Ensure that QApplication is initialized - Q_ASSERT(qApp->instance() && qApp->instance()->thread()); - moveToThread(qApp->instance()->thread()); + bool m_dasyncDestroyed = false; + char __padding[7]; - bool isStartInMain = D_THREAD_IN_MAIN(); - - QObject::connect(this, &MainWorker::sigRunInMain, - this, &MainWorker::slotRunInMain, - isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection); +public: + void setDAsyncDestroyed() { m_dasyncDestroyed = true; } + bool dasyncDestroyed() { return m_dasyncDestroyed; } - QObject::connect(this, &MainWorker::sigRunInMainVoid, - this, &MainWorker::slotRunInMainVoid, - isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection); - } +public: + MainWorker(QObject *parent = nullptr) + : QObject(parent) + { + // Ensure that QApplication is initialized + Q_ASSERT(qApp->instance() && qApp->instance()->thread()); + moveToThread(qApp->instance()->thread()); + + bool isStartInMain = D_THREAD_IN_MAIN(); + + QObject::connect(this, + &MainWorker::sigRunInMain, + this, + &MainWorker::slotRunInMain, + isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection); + + QObject::connect(this, + &MainWorker::sigRunInMainVoid, + this, + &MainWorker::slotRunInMainVoid, + isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection); + } - // 1. handle arg is non void - template - typename std::enable_if::value>::type - setHandle(FUNC &&func) { - m_handle = [&] (void *arg) { - DSafeQueue *q = static_cast*>(arg); - while (q && q->size()) { - // 这里是 then 回调真正执行到的地方 - func(q->dequeue()); - } - }; + // 1. handle arg is non void + template + typename std::enable_if::value>::type setHandle(FUNC &&func) + { + m_handle = [&](void *arg) { + DSafeQueue *q = static_cast *>(arg); + while (q && q->size()) { + // 这里是 then 回调真正执行到的地方 + func(q->dequeue()); + } + }; - m_handleProxy = [this] (void *arg) { - if (m_handle) { - m_handle(arg); - } - }; - } + m_handleProxy = [this](void *arg) { + if (m_handle) { + m_handle(arg); + } + }; + } - // 2. handle arg is void - template - typename std::enable_if::value>::type - setHandle(FUNC &&func) { - m_handleV = [&] (void) { - // 这里是 then 回调真正执行到的地方 - func(); - }; + // 2. handle arg is void + template + typename std::enable_if::value>::type setHandle(FUNC &&func) + { + m_handleV = [&](void) { + // 这里是 then 回调真正执行到的地方 + func(); + }; - m_handleVProxy = [this] (void) { - if (m_handleV) { - m_handleV(); - } - }; - } - Q_SIGNALS: - void sigRunInMain(void *arg); - void sigRunInMainVoid(); - public Q_SLOTS: - void slotRunInMain(void *arg) { - Q_ASSERT(D_THREAD_IN_MAIN()); - if (m_handleProxy && !m_dasyncDestroyed) { - m_handleProxy(arg); + m_handleVProxy = [this](void) { + if (m_handleV) { + m_handleV(); } + }; + } +Q_SIGNALS: + void sigRunInMain(void *arg); + void sigRunInMainVoid(); +public Q_SLOTS: + void slotRunInMain(void *arg) + { + Q_ASSERT(D_THREAD_IN_MAIN()); + if (m_handleProxy && !m_dasyncDestroyed) { + m_handleProxy(arg); } - void slotRunInMainVoid(void) { - Q_ASSERT(D_THREAD_IN_MAIN()); - if (m_handleVProxy && !m_dasyncDestroyed) { - m_handleVProxy(); - } + } + void slotRunInMainVoid(void) + { + Q_ASSERT(D_THREAD_IN_MAIN()); + if (m_handleVProxy && !m_dasyncDestroyed) { + m_handleVProxy(); } - }; -} + } +}; +} // namespace DtkCorePrivate -class DAsyncState : public QObject { +class DAsyncState : public QObject +{ Q_OBJECT public: explicit DAsyncState(QObject *parent = nullptr) noexcept - : QObject (parent) + : QObject(parent) { } enum AsyncTaskState { - NotReady = 0x00, // initial state - Ready = 0x02, // deffered = false - Running = 0x04, // thread started - Pending = Ready | Running, // condition wait - Cancel = 0x08, // set thread canceled - WaitFinished = 0x10, // wiaitForFinished - Finished = 0x20, // thread exit - Forever = 0x30, // TODO: DAsync::post execute forever + NotReady = 0x00, // initial state + Ready = 0x02, // deffered = false + Running = 0x04, // thread started + Pending = Ready | Running, // condition wait + Cancel = 0x08, // set thread canceled + WaitFinished = 0x10, // wiaitForFinished + Finished = 0x20, // thread exit + Forever = 0x30, // TODO: DAsync::post execute forever }; Q_DECLARE_FLAGS(AsyncTaskStatus, AsyncTaskState) }; // Template classes not supported by Q_OBJECT, so class MainWorker is independent template -class DAsync : public QObject { - +class D_DECL_DEPRECATED DAsync : public QObject +{ class Helper; std::mutex m_mtxIn; @@ -173,37 +185,39 @@ class DAsync : public QObject { std::mutex m_mtxForWaitTask; std::condition_variable m_cvForWaitTask; - class Guard { + class Guard + { DAsync *m_as; // 如果 DAsync 已经析构了,工作线程还没结束 // DAsync 中的有些数据就不能在 guard 的析构里面访问了 bool m_dasDestructed = false; + public: - bool destructed() { - return m_dasDestructed; - } - void setDestructed() { - m_dasDestructed = true; - } + bool destructed() { return m_dasDestructed; } + void setDestructed() { m_dasDestructed = true; } + public: - explicit Guard(DAsync *as) noexcept : m_as (as) + explicit Guard(DAsync *as) noexcept + : m_as(as) { m_as->m_status.setFlag(DAsyncState::Ready); - m_as->m_status.setFlag(DAsyncState::Finished, false); // 防止重入 + m_as->m_status.setFlag(DAsyncState::Finished, false); // 防止重入 } - ~Guard() { + ~Guard() + { if (destructed()) { return; } m_as->m_threadGuard = nullptr; m_as->m_status.setFlag(DAsyncState::Finished); - m_as->m_status.setFlag(DAsyncState::Ready, false); // 防止重入 + m_as->m_status.setFlag(DAsyncState::Ready, false); // 防止重入 if (m_as->m_status.testFlag(DAsyncState::WaitFinished)) { m_as->m_cvForWaitTask.notify_one(); } setPending(false); } - void setPending(bool isPending) { + void setPending(bool isPending) + { if (!destructed()) { m_as->m_status.setFlag(DAsyncState::Pending, isPending); } @@ -217,10 +231,15 @@ class DAsync : public QObject { * 在 emitHelper 中调用 post 进来的任务,然后将结果传到主线程中处理 * 数据传递使用 void * 做转换,对于复合类型避免了使用 qRegisterMetaType */ - template - struct DataQueueType { DtkCorePrivate::DSafeQueue m_queue; }; - template - struct DataQueueType::value>::type> { }; + template + struct DataQueueType + { + DtkCorePrivate::DSafeQueue m_queue; + }; + template + struct DataQueueType::value>::type> + { + }; using DataInQueue = DataQueueType; using DataOutQueue = DataQueueType; // Queue 中处理完的结果经由 m_QueueIn 变量暂存,然后经由 signal、slot 传给 then 中的回调函数做参数 @@ -228,32 +247,41 @@ class DAsync : public QObject { DataOutQueue m_QueueOut; // 存储不同类型的输入函数 - template - struct FuncType { + template + struct FuncType + { }; - template - struct FuncType::value>::type, - typename std::enable_if::value>::type> { - std::function cbp; + template + struct FuncType::value>::type, + typename std::enable_if::value>::type> + { + std::function cbp; }; - template - struct FuncType::value>::type, - typename std::enable_if::value>::type> { - std::function cbp; + template + struct FuncType::value>::type, + typename std::enable_if::value>::type> + { + std::function cbp; }; - template - struct FuncType::value>::type, - typename std::enable_if::value>::type> { - std::function cbp; + template + struct FuncType::value>::type, + typename std::enable_if::value>::type> + { + std::function cbp; }; - template - struct FuncType::value>::type, - typename std::enable_if::value>::type> { - std::function cbp; + template + struct FuncType::value>::type, + typename std::enable_if::value>::type> + { + std::function cbp; }; std::mutex m_mtxFunc; @@ -262,14 +290,15 @@ class DAsync : public QObject { public: explicit DAsync(QObject *parent = nullptr) noexcept - : QObject (parent) - , m_func ({nullptr}) - , m_status (DAsyncState::NotReady) + : QObject(parent) + , m_func({nullptr}) + , m_status(DAsyncState::NotReady) { m_mainWorker = new DtkCorePrivate::MainWorker(); m_helper = new Helper(this, this); } - ~DAsync() { + ~DAsync() + { if (m_threadGuard) { m_threadGuard->setDestructed(); } @@ -287,49 +316,49 @@ public: private: // 1. input void & emit void template - typename std::enable_if::value && std::is_void::value>::type - emitHelper() { + typename std::enable_if::value && std::is_void::value>::type emitHelper() + { m_func.cbp(); Q_EMIT m_mainWorker->sigRunInMainVoid(); } // 2. input non void & emit non void template - typename std::enable_if::value && !std::is_void::value>::type - emitHelper() { + typename std::enable_if::value && !std::is_void::value>::type emitHelper() + { m_QueueOut.m_queue.enqueue(m_func.cbp(m_QueueIn.m_queue.dequeue())); Q_EMIT m_mainWorker->sigRunInMain(static_cast(&(m_QueueOut.m_queue))); } // 3. input non void & emit void template - typename std::enable_if::value && std::is_void::value>::type - emitHelper() { + typename std::enable_if::value && std::is_void::value>::type emitHelper() + { m_func.cbp(m_QueueIn.m_queue.dequeue()); Q_EMIT m_mainWorker->sigRunInMainVoid(); } // 4. input void & emit non void template - typename std::enable_if::value && !std::is_void::value>::type - emitHelper() { + typename std::enable_if::value && !std::is_void::value>::type emitHelper() + { m_QueueOut.m_queue.enqueue(m_func.cbp()); Q_EMIT m_mainWorker->sigRunInMain(static_cast(&(m_QueueOut.m_queue))); } public: - void startUp() { + void startUp() + { if (m_status.testFlag(DAsyncState::Cancel)) { return; } m_helper->start(); } - void cancelAll() { + void cancelAll() + { m_status.setFlag(DAsyncState::Cancel); if (m_status.testFlag(DAsyncState::Pending)) { m_cvIn.notify_one(); } } - bool isFinished() { - return m_status.testFlag(DAsyncState::Finished); - } + bool isFinished() { return m_status.testFlag(DAsyncState::Finished); } /* * 不能在 QTimer 中使用 waitForFinished,防止阻塞主线程 * 也不能在主线程执行前使用 waitForFinished() @@ -341,7 +370,8 @@ public: * 任务结束只要调用 cancelAll + isFinished 轮询判断就行了, * DAsync 的工作线程就会在完成后自动退出。 */ - void waitForFinished(bool cancelAllWorks = true) { + void waitForFinished(bool cancelAllWorks = true) + { Q_ASSERT(!D_THREAD_IN_MAIN()); if (cancelAllWorks) { cancelAll(); @@ -351,19 +381,19 @@ public: m_cvIn.notify_one(); } m_status.setFlag(DAsyncState::WaitFinished); - std::unique_lock lck(m_mtxForWaitTask); + std::unique_lock lck(m_mtxForWaitTask); m_cvForWaitTask.wait(lck); } } // 输入数据不是 void 类型则依赖于 m_QueueIn template - typename std::enable_if::value, Helper *>::type - post(FUNC &&func) { + typename std::enable_if::value, Helper *>::type post(FUNC &&func) + { m_func.cbp = std::forward(func); if (m_postProxy) { return m_helper; } - m_postProxy = [this] () { + m_postProxy = [this]() { std::thread thread([this] { if (m_status.testFlag(DAsyncState::Cancel)) { return; @@ -371,7 +401,7 @@ public: Guard guard(this); m_threadGuard = &guard; - std::unique_lock lck(m_mtxIn); + std::unique_lock lck(m_mtxIn); while (true) { while (!m_status.testFlag(DAsyncState::Ready) || !m_QueueIn.m_queue.size()) { guard.setPending(true); @@ -395,8 +425,8 @@ public: } template - typename std::enable_if::value, Helper *>::type - post(FUNC &&func) { + typename std::enable_if::value, Helper *>::type post(FUNC &&func) + { { std::lock_guard lckFunc(m_mtxFunc); m_func.cbp = std::forward(func); @@ -404,7 +434,7 @@ public: if (m_postProxy) { return m_helper; } - m_postProxy = [this] () { + m_postProxy = [this]() { std::thread thread([this] { if (m_status.testFlag(DAsyncState::Cancel)) { return; @@ -412,13 +442,13 @@ public: Guard guard(this); m_threadGuard = &guard; - std::unique_lock lck(m_mtxIn); + std::unique_lock lck(m_mtxIn); while (true) { if (!m_status.testFlag(DAsyncState::Ready)) { guard.setPending(true); // 定时查询 flag,防止睡死的情况发生 m_cvIn.wait_for(lck, std::chrono::milliseconds(200)); - if (guard.destructed() || m_status.testFlag(DAsyncState::Cancel)){ + if (guard.destructed() || m_status.testFlag(DAsyncState::Cancel)) { return; } } @@ -427,7 +457,7 @@ public: if (m_func.cbp) { std::lock_guard lckFunc(m_mtxFunc); emitHelper(); - m_func.cbp = nullptr; // reset + m_func.cbp = nullptr; // reset } } }); @@ -439,8 +469,8 @@ public: // only support DAsync template - typename std::enable_if::value>::type - postData(const InputType &data) { + typename std::enable_if::value>::type postData(const InputType &data) + { if (Q_UNLIKELY(!m_status.testFlag(DAsyncState::Cancel))) { m_QueueIn.m_queue.enqueue(data); if (m_status.testFlag(DAsyncState::Pending)) { @@ -451,22 +481,26 @@ public: private: std::function m_postProxy; - class Helper : public QObject { + class Helper : public QObject + { DAsync *m_async; + public: explicit Helper(DAsync *async, QObject *parent = nullptr) noexcept - : QObject (parent) - , m_async (async) + : QObject(parent) + , m_async(async) { } template - Helper *then(FUNC &&func) { + Helper *then(FUNC &&func) + { m_async->m_mainWorker->template setHandle(std::forward(func)); return this; } // 仅启动,非阻塞 - void start(bool immediately = true) { + void start(bool immediately = true) + { if (m_async->m_postProxy) { m_async->m_postProxy(); } @@ -486,4 +520,4 @@ private: }; DCORE_END_NAMESPACE -#endif //DASYNC_H +#endif // DASYNC_H diff --git a/include/util/ddbusextended.h b/include/util/ddbusextended.h deleted file mode 100644 index 9ca5cb7..0000000 --- a/include/util/ddbusextended.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2015 Jolla Ltd. -// -// SPDX-License-Identifier: LGPL-2.1-or-later - -#ifndef QT_DBUS_EXTENDED_H -#define QT_DBUS_EXTENDED_H - -#if defined(QT_DBUS_EXTENDED_LIBRARY) -# define QT_DBUS_EXTENDED_EXPORT Q_DECL_EXPORT -#else -# define QT_DBUS_EXTENDED_EXPORT Q_DECL_IMPORT -#endif - -#endif /* QT_DBUS_EXTENDED_H */ diff --git a/include/util/ddbusextendedabstractinterface.h b/include/util/ddbusextendedabstractinterface.h index af72b14..d89dac7 100644 --- a/include/util/ddbusextendedabstractinterface.h +++ b/include/util/ddbusextendedabstractinterface.h @@ -4,16 +4,16 @@ #ifndef DBUSEXTENDEDABSTRACTINTERFACE_H #define DBUSEXTENDEDABSTRACTINTERFACE_H - -#include +#include "dtkcore_global.h" #include #include - class QDBusPendingCallWatcher; +DCORE_BEGIN_NAMESPACE + class DDBusExtendedPendingCallWatcher; -class QT_DBUS_EXTENDED_EXPORT DDBusExtendedAbstractInterface: public QDBusAbstractInterface +class LIBDTKCORESHARED_EXPORT DDBusExtendedAbstractInterface : public QDBusAbstractInterface { Q_OBJECT @@ -36,11 +36,8 @@ public Q_SLOTS: void startServiceProcess(); protected: - DDBusExtendedAbstractInterface(const QString &service, - const QString &path, - const char *interface, - const QDBusConnection &connection, - QObject *parent); + DDBusExtendedAbstractInterface( + const QString &service, const QString &path, const char *interface, const QDBusConnection &connection, QObject *parent); void connectNotify(const QMetaMethod &signal); void disconnectNotify(const QMetaMethod &signal); @@ -57,9 +54,9 @@ Q_SIGNALS: void asyncGetAllPropertiesFinished(); private Q_SLOTS: - void onPropertiesChanged(const QString& interfaceName, - const QVariantMap& changedProperties, - const QStringList& invalidatedProperties); + void onPropertiesChanged(const QString &interfaceName, + const QVariantMap &changedProperties, + const QStringList &invalidatedProperties); void onDBusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void onAsyncPropertyFinished(QDBusPendingCallWatcher *w); void onAsyncSetPropertyFinished(QDBusPendingCallWatcher *w); @@ -69,7 +66,8 @@ private Q_SLOTS: private: QVariant asyncProperty(const QString &propertyName); void asyncSetProperty(const QString &propertyName, const QVariant &value); - static QVariant demarshall(const QString &interface, const QMetaProperty &metaProperty, const QVariant &value, QDBusError *error); + static QVariant + demarshall(const QString &interface, const QMetaProperty &metaProperty, const QVariant &value, QDBusError *error); bool m_sync; bool m_useCache; @@ -78,5 +76,6 @@ private: QString m_dbusOwner; bool m_propertiesChangedConnected; }; +DCORE_END_NAMESPACE #endif /* DBUSEXTENDEDABSTRACTINTERFACE_H */ diff --git a/include/util/ddbusinterface.h b/include/util/ddbusinterface.h index d0fe593..595224e 100644 --- a/include/util/ddbusinterface.h +++ b/include/util/ddbusinterface.h @@ -10,6 +10,7 @@ DCORE_BEGIN_NAMESPACE class DDBusInterfacePrivate; +// Imported since 5.6.3 class DDBusInterface : public QDBusAbstractInterface { Q_OBJECT @@ -17,7 +18,7 @@ class DDBusInterface : public QDBusAbstractInterface public: explicit DDBusInterface(const QString &service, const QString &path, - const QString &interface = QString(), + const QString &interface, const QDBusConnection &connection = QDBusConnection::sessionBus(), QObject *parent = nullptr); virtual ~DDBusInterface() override; diff --git a/include/util/ddbussender.h b/include/util/ddbussender.h index b6410d9..92b8992 100644 --- a/include/util/ddbussender.h +++ b/include/util/ddbussender.h @@ -18,6 +18,7 @@ class LIBDTKCORESHARED_EXPORT DDBusData { public: DDBusData(); + QDBusPendingCall asyncCallWithArguments(const QString &method, const QVariantList &arguments, const QString &iface = QString()); QString service; QString path; @@ -73,11 +74,8 @@ private: template QDBusPendingCall DDBusProperty::set(const T &value) { - QDBusInterface iface(m_dbusData->service, m_dbusData->path, QStringLiteral("org.freedesktop.DBus.Properties"), m_dbusData->connection); - - const QVariantList args = { QVariant::fromValue(m_dbusData->interface), QVariant::fromValue(m_propertyName), QVariant::fromValue(QDBusVariant(value)) }; - - return iface.asyncCallWithArgumentList(QStringLiteral("Set"), args); + QVariantList args{QVariant::fromValue(m_dbusData->interface), QVariant::fromValue(m_propertyName), QVariant::fromValue(QDBusVariant(value))}; + return m_dbusData->asyncCallWithArguments(QStringLiteral("Set"), args, QStringLiteral("org.freedesktop.DBus.Properties")); } class LIBDTKCORESHARED_EXPORT DDBusSender @@ -91,6 +89,7 @@ public: DDBusCaller method(const QString &method); DDBusProperty property(const QString &property); + static DDBusSender system(); private: DDBusSender type(const QDBusConnection::BusType busType); diff --git a/include/util/dpinyin.h b/include/util/dpinyin.h index a98dbb2..ba8572b 100644 --- a/include/util/dpinyin.h +++ b/include/util/dpinyin.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -11,8 +11,22 @@ DCORE_BEGIN_NAMESPACE +// without polyphonic support QString LIBDTKCORESHARED_EXPORT Chinese2Pinyin(const QString& words); +//!< @~english enum ToneStyle - pinyin tone style +enum ToneStyle { + TS_NoneTone, /*!< @~english pinyin without tone */ + TS_Tone, /*!< @~english pinyin tone, default style in dictory file*/ + TS_ToneNum, /*!< @~english pinyin tone number */ +}; + +// support polyphonic +QStringList LIBDTKCORESHARED_EXPORT pinyin(const QString& words, ToneStyle ts = TS_Tone, bool *ok = nullptr); + +// support polyphonic +QStringList LIBDTKCORESHARED_EXPORT firstLetters(const QString& words); + DCORE_END_NAMESPACE #endif // DPINYIN_H diff --git a/include/util/dtextencoding.h b/include/util/dtextencoding.h new file mode 100644 index 0000000..3bc5b00 --- /dev/null +++ b/include/util/dtextencoding.h @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DTEXTENCODING_H +#define DTEXTENCODING_H + +#include + +#include +#include + +DCORE_BEGIN_NAMESPACE + +class LIBDTKCORESHARED_EXPORT DTextEncoding +{ +public: + static QByteArray detectTextEncoding(const QByteArray &content); + static QByteArray detectFileEncoding(const QString &fileName, bool *isOk = nullptr); + + static bool convertTextEncoding(QByteArray &content, + QByteArray &outContent, + const QByteArray &toEncoding, + const QByteArray &fromEncoding = QByteArray(), + QString *errString = nullptr); + static bool convertTextEncodingEx(QByteArray &content, + QByteArray &outContent, + const QByteArray &toEncoding, + const QByteArray &fromEncoding = QByteArray(), + QString *errString = nullptr, + int *convertedBytes = nullptr); + static bool convertFileEncoding(const QString &fileName, + const QByteArray &toEncoding, + const QByteArray &fromEncoding = QByteArray(), + QString *errString = nullptr); + static bool convertFileEncodingTo(const QString &fromFile, + const QString &toFile, + const QByteArray &toEncoding, + const QByteArray &fromEncoding = QByteArray(), + QString *errString = nullptr); +}; + +DCORE_END_NAMESPACE + +#endif // DTEXTENCODING_H diff --git a/include/util/dthreadutils.h b/include/util/dthreadutils.h index 2b6d212..8962782 100644 --- a/include/util/dthreadutils.h +++ b/include/util/dthreadutils.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2020 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,8 +13,15 @@ #include #include +#if DTK_VERSION >= DTK_VERSION_CHECK(6, 0, 0, 0) +#include +#include +#include +#endif + DCORE_BEGIN_NAMESPACE +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) namespace DThreadUtil { typedef std::function FunctionType; @@ -152,7 +159,170 @@ inline typename QtPrivate::FunctionPointer::ReturnType return runInMainThread(obj, obj, fun, std::forward(args)...); } } +#else +class LIBDTKCORESHARED_EXPORT DThreadUtils final +{ + friend class Caller; +public: + explicit DThreadUtils(QThread *thread); + ~DThreadUtils(); -DCORE_END_NAMESPACE + static DThreadUtils &gui(); + + QThread *thread() const noexcept; -#endif // DTHREADUTILS_H + template + inline auto run(QObject *context,typename QtPrivate::FunctionPointer::Object *obj, Func fun, Args &&...args) + { + return call(context, fun, *obj, std::forward(args)...); + } + template + inline auto run(typename QtPrivate::FunctionPointer::Object *obj, Func fun, Args &&...args) + { + if constexpr (std::is_base_of::Object>::value) { + return call(obj, fun, *obj, std::forward(args)...); + } else { + return call(static_cast(nullptr), fun, *obj, std::forward(args)...); + } + } + template + inline QFuture, Args...>> run(QObject *context, Func fun, Args &&...args) + { + return call(context, fun, std::forward(args)...); + } + template + inline QFuture, Args...>> run(Func fun, Args &&...args) + { + return call(static_cast(nullptr), fun, std::forward(args)...); + } + template + inline decltype(auto) exec(T &&...args) + { + auto future = run(std::forward(args)...); + if (!thread()->isRunning()) { + qWarning() << "The target thread is not running, maybe lead to deadlock."; + } + future.waitForFinished(); + if constexpr (std::is_same_v>) { + return; + } else { + return future.result(); + } + } + +private: + class AbstractCallEvent : public QEvent + { + public: + AbstractCallEvent(QEvent::Type type) + : QEvent(type) + { + } + virtual void call() = 0; + }; + + template + class Q_DECL_HIDDEN CallEvent : public AbstractCallEvent + { + using FunInfo = QtPrivate::FunctionPointer>; + using ReturnType = std::invoke_result_t, Args...>; + + public: + CallEvent(QEvent::Type type, Func &&fun, Args &&...args) + : AbstractCallEvent(type) + , function(std::forward(fun)) + , arguments(std::forward(args)...) + { + } + + QEvent *clone() const override { return nullptr; } + + void call() override + { + if (promise.isCanceled()) { + return; + } + + if (contextChecker == context) { + promise.start(); +#ifndef QT_NO_EXCEPTIONS + try { +#endif + if constexpr (std::is_void_v) { + std::apply(function, arguments); + } else { + promise.addResult(std::apply(function, arguments)); + } +#ifndef QT_NO_EXCEPTIONS + } catch (...) { + promise.setException(std::current_exception()); + } +#endif + promise.finish(); + } else { + promise.start(); + promise.setException(std::make_exception_ptr(std::runtime_error("The context object is destroyed."))); + promise.finish(); + } + } + + Func function; + const std::tuple arguments; + QPromise promise; + + QObject *context{nullptr}; + QPointer contextChecker; + }; + + template + inline auto call(QObject *context, Func fun, Args &&...args) + { + using FuncInfo = QtPrivate::FunctionPointer>; + using ReturnType = std::invoke_result_t, Args...> ; + + if constexpr (FuncInfo::IsPointerToMemberFunction) { + static_assert(std::is_same_v::Car>, typename FuncInfo::Object>, + "The obj and function are not compatible."); + static_assert( + QtPrivate::CheckCompatibleArguments::Cdr, typename FuncInfo::Arguments>::value, + "The args and function are not compatible."); + } else if constexpr (FuncInfo::ArgumentCount != -1) { + static_assert(QtPrivate::CheckCompatibleArguments, typename FuncInfo::Arguments>::value, + "The args and function are not compatible."); + } else { // for lambda and impl operator() + static_assert(std::is_invocable_r_v, + "The callable object can't invoke with supplied args"); + } + + QPromise promise; + auto future = promise.future(); + + if (Q_UNLIKELY(QThread::currentThread() == m_thread)) { + promise.start(); + if constexpr (std::is_void_v) { + std::invoke(fun, std::forward(args)...); + } else { + promise.addResult(std::invoke(fun, std::forward(args)...)); + } + promise.finish(); + } else { + auto event = new CallEvent(eventType, std::move(fun), std::forward(args)...); + event->promise = std::move(promise); + event->context = context; + event->contextChecker = context; + + QCoreApplication::postEvent(ensureThreadContextObject(), event); + } + + return future; + } + + QObject *ensureThreadContextObject(); + + static inline QEvent::Type eventType; + QThread *m_thread; + QAtomicPointer threadContext; +}; +#endif // version macro end +DCORE_END_NAMESPACE +#endif // protect macro end diff --git a/include/util/dutil.h b/include/util/dutil.h index 7462fcc..4353b85 100644 --- a/include/util/dutil.h +++ b/include/util/dutil.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2016 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,6 +8,11 @@ #include #include #include +#include +#include +#include +#include +#include namespace DUtil { @@ -32,16 +37,95 @@ inline void TimerSingleShot(int msec, Func1 slot) template void SecureErase(T *p, size_t size) { - memset(p, 0, size); + static_assert(std::is_standard_layout::value && std::is_trivially_destructible::value, + "try to erase content of raw pointer, but type T isn't suitable"); + + std::memset(p, 0, size); } template void SecureErase(T &obj) { + static_assert(std::is_default_constructible::value, + "container's value type must have a default constructor."); + for (typename T::iterator i = obj.begin(); i != obj.end(); ++i) { - *i = 0; + *i = typename T::value_type{}; } - obj.clear(); } +inline QString escapeToObjectPath(const QString &str) +{ + if (str.isEmpty()) { + return "_"; + } + + auto ret = str; + QRegularExpression re{R"([^a-zA-Z0-9])"}; + auto matcher = re.globalMatch(ret); + while (matcher.hasNext()) { + auto replaceList = matcher.next().capturedTexts(); + replaceList.removeDuplicates(); + for (const auto &c : replaceList) { + auto hexStr = QString::number(static_cast(c.front().toLatin1()), 16); + ret.replace(c, QString{R"(_%1)"}.arg(hexStr)); + } + } + return ret; +} + +inline QString unescapeFromObjectPath(const QString &str) +{ + auto ret = str; + for (int i = 0; i < str.size(); ++i) { + if (str[i] == '_' && i + 2 < str.size()) { + auto hexStr = str.mid(i + 1, 2); + ret.replace(QString{"_%1"}.arg(hexStr), QChar::fromLatin1(hexStr.toUInt(nullptr, 16))); + i += 2; + } + } + return ret; +} + +inline QString getAppIdFromAbsolutePath(const QString &path) +{ + static QString desktopSuffix{u8".desktop"}; + const auto &appDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation); + if (!path.endsWith(desktopSuffix) || + !std::any_of(appDirs.cbegin(), appDirs.constEnd(), [&path](const QString &dir) { return path.startsWith(dir); })) { + return {}; + } + + auto tmp = path.chopped(desktopSuffix.size()); + auto components = tmp.split(QDir::separator(), Qt::SkipEmptyParts); + auto location = std::find(components.cbegin(), components.cend(), "applications"); + if (location == components.cend()) { + return {}; + } + + auto appId = QStringList{location + 1, components.cend()}.join('-'); + return appId; +} + +inline QStringList getAbsolutePathFromAppId(const QString &appId) +{ + auto components = appId.split('-', Qt::SkipEmptyParts); + auto appDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation); + + QStringList ret; + for (const auto &dirPath : appDirs) { + auto currentDir = dirPath; + for (auto it = components.cbegin(); it != components.cend(); ++it) { + auto currentName = QStringList{it, components.cend()}.join('-') + QString{".desktop"}; + QDir dir{currentDir}; + if (dir.exists(currentName)) { + ret.append(dir.filePath(currentName)); + } + + currentDir.append(QDir::separator() + *it); + } + } + + return ret; +} } diff --git a/include/util/dvtablehook.h b/include/util/dvtablehook.h index 79be2f7..29c6b6f 100644 --- a/include/util/dvtablehook.h +++ b/include/util/dvtablehook.h @@ -10,12 +10,18 @@ #include #include #include - +#include #include #include DCORE_BEGIN_NAMESPACE +#ifndef QT_DEBUG +inline Q_LOGGING_CATEGORY(vtableHook, "dtk.vtableHook", QtInfoMsg); +#else +inline Q_LOGGING_CATEGORY(vtableHook, "dtk.vtableHook"); +#endif + class LIBDTKCORESHARED_EXPORT DVtableHook { public: @@ -27,8 +33,12 @@ public: static inline int getVtableSize(quintptr **obj) { quintptr *begin = *obj; - while(*begin) ++begin; - return begin - *obj; + while (true) { + if ((int64_t)*begin == 0 or (int64_t)*begin < QSysInfo::WordSize) // offset will grater than 8 bytes(64 bit) + break; + ++begin; + } + return begin - *obj + 2; // for offset and rtti info } static inline quintptr *getVtableOfObject(const void *obj) @@ -44,11 +54,7 @@ public: quintptr *vfptr_t1 = reinterpret_cast(resolve(vtable_symbol.constData())); - if (!vfptr_t1) - return nullptr; - - // symbol address + 2 * sizeof(quintptr) = virtal table start address - return vfptr_t1 + 2; + return vfptr_t1 ? adjustToEntry(vfptr_t1) : nullptr; } static int getDestructFunIndex(quintptr **obj, std::function destoryObjFun); @@ -107,7 +113,7 @@ public: { typedef QtPrivate::FunctionPointer FunInfo1; // 检查析构函数是否为虚 - class OverrideDestruct : public FunInfo1::Object { ~OverrideDestruct() override;}; + class OverrideDestruct : public FunInfo1::Object { ~OverrideDestruct() override;}; //TODO: we can use std::has_virtual_destructor if (!ensureVtable((void*)t1, std::bind(&_destory_helper, t1))) { return false; @@ -174,7 +180,7 @@ public: quintptr fun1_offset = toQuintptr(&fun1); quintptr fun2_offset = toQuintptr(&fun2); - if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX) + if (fun1_offset > UINT_LEAST16_MAX) return false; quintptr *vfun = vfptr_t1 + fun1_offset / sizeof(quintptr); @@ -194,9 +200,8 @@ public: static inline StdFunType fun(StdFunType f, bool check = true) { static StdFunType fun = f; static bool initialized = false; - if (initialized && check) { - qWarning("The StdFunWrap is dirty! Don't use std::bind(use lambda functions)."); - } + if (initialized && check) + qCWarning(vtableHook, "The StdFunWrap is dirty! Don't use std::bind(use lambda functions)."); initialized = true; return fun; } @@ -311,7 +316,7 @@ public: rvf.oldFun = DVtableHook::resetVfptrFun((void*)obj, fun_offset); if (!rvf.oldFun) { - qWarning() << "Reset the function failed, object:" << obj; + qCWarning(vtableHook) << "Reset the function failed, object: " << obj; abort(); } @@ -322,6 +327,26 @@ public: private: static bool copyVtable(quintptr **obj); static bool clearGhostVtable(const void *obj); +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + Q_DECL_DEPRECATED static bool isFinalClass(quintptr *obj); + Q_DECL_DEPRECATED static quintptr **adjustThis(quintptr *obj); +#endif + + template + static T adjustToTop(T obj) // vtableTop: vtable start address, Usually refers to offset_to_top + { + // this function should'n be called when entry is parent entry + using fundamentalType = typename std::remove_cv::type>::type; + return obj - static_cast(2); // vtable start address = vtable entry - 2 + } + + template + static T adjustToEntry(T obj) // vtableEntry: is located after rtti in the virtual table + { + // this function should'n be called when entry is parent entry + using fundamentalType = typename std::remove_cv::type>::type; + return obj + static_cast(2); // vtable entry = vtable start address + 2 + } template static void _destory_helper(const T *obj) { diff --git a/linglong.yaml b/linglong.yaml new file mode 100644 index 0000000..d3bc904 --- /dev/null +++ b/linglong.yaml @@ -0,0 +1,29 @@ +package: + id: dtkcore + name: dtkcore + kind: lib + version: 5.6.3 + description: | + Deepin Tool Kit Core Devel library \ + DtkCore is base devel library of Deepin Qt/C++ applications. + +base: + id: org.deepin.base/23.0.0 + +depends: + - id: qtbase/5.15.7 + - id: dtkcommon/5.6.0.1 + - id: gsettings-qt/0.3.1.1 + +source: + kind: local + +variables: + extra_args: | + -DBUILD_EXAMPLES=OFF \ + -DBUILD_DOCS=OFF \ + -DBUILD_TESTING=OFF \ + -DDTK_VERSION=${VERSION} + +build: + kind: cmake diff --git a/misc/DtkConfig.cmake.in b/misc/DtkConfig.cmake.in deleted file mode 100644 index 9d3df4e..0000000 --- a/misc/DtkConfig.cmake.in +++ /dev/null @@ -1,14 +0,0 @@ -@PACKAGE_INIT@ - -set_and_check(DtkCore_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") -set_and_check(DtkCore_LIBRARY_DIRS "@PACKAGE_LIBRARY_INSTALL_DIR@") -set(DtkCore_TOOL_DIRS "@PACKAGE_TOOL_INSTALL_DIR@") -set(DtkCore_LIBRARIES dtkcore) - -include_directories("${DtkCore_INCLUDE_DIRS}") - -check_required_components(DtkCore) - -# Keep deprecated variables for compatibility -set(DTKCORE_INCLUDE_DIRS ${DtkCore_INCLUDE_DIRS}) -set(DTKCORE_TOOL_DIRS ${DtkCore_TOOL_DIRS}) diff --git a/misc/DtkCoreConfig.cmake.in b/misc/DtkCoreConfig.cmake.in new file mode 100644 index 0000000..ca89735 --- /dev/null +++ b/misc/DtkCoreConfig.cmake.in @@ -0,0 +1,27 @@ +@PACKAGE_INIT@ + +if(UNIX AND NOT APPLE) + set(LINUX TRUE) +endif() +include(CMakeFindDependencyMacro) +find_dependency(Qt@QT_VERSION_MAJOR@Core) +find_dependency(Qt@QT_VERSION_MAJOR@Xml) +find_dependency(Dtk@DTK_VERSION_MAJOR@Log) + +if (LINUX) + find_dependency(Qt@QT_VERSION_MAJOR@DBus) +endif() +find_dependency(Dtk@DTK_VERSION_MAJOR@DConfig) +include(${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@CoreTargets.cmake) + +set(DtkCore_LIBRARIES Dtk@DTK_VERSION_MAJOR@::Core) +get_target_property(DtkCore_INCLUDE_DIRS Dtk@DTK_VERSION_MAJOR@::Core INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(DtkCore_LIBRARY_DIRS Dtk@DTK_VERSION_MAJOR@::Core INTERFACE_LINK_DIRECTORIES) +set(DtkCore_TOOL_DIRS "@PACKAGE_TOOL_INSTALL_DIR@") +check_required_components(DtkCore) + +# Keep deprecated variables for compatibility +set(DTKCORE_INCLUDE_DIRS ${DtkCore_INCLUDE_DIRS}) +set(DTKCORE_TOOL_DIRS ${DtkCore_TOOL_DIRS}) + +add_definitions(-DQT_MESSAGELOGCONTEXT) diff --git a/misc/dtk_install_dconfig.prf b/misc/dtk_install_dconfig.prf new file mode 100644 index 0000000..fa237d1 --- /dev/null +++ b/misc/dtk_install_dconfig.prf @@ -0,0 +1,83 @@ +# This prf file is used to deploy files that dconfig's meta and override configure. +# +# get variable `$$DSG_DATA_DIR` 's value, it’s consistent with class DConfigFile code. +isEmpty(DSG_DATA_DIR) { + isEmpty(PREFIX) { + DSG_DATA_DIR=/usr/share/dsg + } else { + DSG_DATA_DIR=$$PREFIX/share/dsg + } +} + +# deploy some `meta` 's configure. +# +# files - deployed files. +# base - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# appid - working for the app, if it's empty, depending on `TEMPLATE`. +# commonid - working for common, if it's empyt, depending on `TEMPLATE`. +# +# e.g: +# dconfig_example.files += \ +# $$PWD/configs/dconf-example.json \ +# $$PWD/configs/a/dconf-example.json +# dconfig_example.base = $$PWD/configs +# dconfig_example.appid = $$TARGET +# +# dconfig_example2.files += $$PWD/configs/a/dconf-example.json +# +# DCONFIG_META_FILES += dconfig_example dconfig_example2 +# +for(metaitem, DCONFIG_META_FILES) { + eval(dconfig_meta_$${metaitem}.files = $$eval($${metaitem}.files)) + eval(dconfig_meta_$${metaitem}.base = $$eval($${metaitem}.base)) + isEmpty($${metaitem}.appid) { + is_common_configuration=true + isEmpty($${metaitem}.commonid) { + equals(TEMPLATE, app) { + eval(dconfig_meta_$${metaitem}.path = $$DSG_DATA_DIR/configs/$$TARGET/) + is_common_configuration=false + } + } + if ($$is_common_configuration) { + eval(dconfig_meta_$${metaitem}.path = $$DSG_DATA_DIR/configs) + } + } else { + eval(dconfig_meta_$${metaitem}.path = $$DSG_DATA_DIR/configs/$$eval($${metaitem}.appid)) + } + INSTALLS += dconfig_meta_$${metaitem} +} + + +# deploy some `meta` 's override configure. +# +# configuration for the `meta_name` 's override configure. +# +# files - deployed files. +# base - used to get subpath, if it's empty, only copy files, and ignore it's subpath structure. +# appid - working for the app, if it's empty, working for all app. +# meta_name - override for the meta configure. +# +# e.g : +# dconfig_example.files += \ +# $$PWD/configs/dconf-example.override.json \ +# $$PWD/configs/a/dconf-example.override.a.json +# dconfig_example.base = $$PWD/configs +# dconfig_example.meta_name = example +# dconfig_example.appid = $$TARGET +# +# dconfig_example2.files += $$PWD/configs/a/dconf-example.override.a.json +# dconfig_example2.meta_name = example2 +# +# DCONFIG_OVERRIDE_FILES += dconfig_example dconfig_example2 +# +for(overrideitem, DCONFIG_OVERRIDE_FILES) { + eval(dconfig_override_$${overrideitem}.files = $$eval($${overrideitem}.files)) + eval(dconfig_override_$${overrideitem}.base = $$eval($${overrideitem}.base)) + isEmpty($${overrideitem}.meta_name) : error("Please set meta_name for the override configuration." $${overrideitem}) + isEmpty($${overrideitem}.appid) { + eval(dconfig_override_$${overrideitem}.path = $$DSG_DATA_DIR/configs/overrides/$$eval($${overrideitem}.meta_name)) + } else { + eval(dconfig_override_$${overrideitem}.path = $$DSG_DATA_DIR/configs/overrides/$$eval($${overrideitem}.appid)/$$eval($${overrideitem}.meta_name)) + } + INSTALLS += dconfig_override_$${overrideitem} +} diff --git a/misc/dtkcore.pc.in b/misc/dtkcore.pc.in index 58763ca..890d622 100644 --- a/misc/dtkcore.pc.in +++ b/misc/dtkcore.pc.in @@ -1,10 +1,11 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} -libdir=@LIBRARY_INSTALL_DIR@ -includedir=@INCLUDE_INSTALL_DIR@ +libdir=${prefix}/@LIBRARY_INSTALL_DIR@ +includedir=${prefix}/@INCLUDE_INSTALL_DIR@ -Name: dtkcore +Name: dtk@DTK_VERSION_MAJOR@core Description: Deepin Tool Kit dtkcore header files Version: @CMAKE_PROJECT_VERSION@ -Libs: -L${libdir} -ldtkcore -Cflags: -I${includedir} +Libs: -L${libdir} -ldtk@DTK_VERSION_MAJOR@core +Cflags: -I${includedir} -DQT_MESSAGELOGCONTEXT +Requires: dtk@DTK_VERSION_MAJOR@log diff --git a/misc/qt_lib_dtkcore.pri.in b/misc/qt_lib_dtkcore.pri.in index 44afcfa..06ee503 100644 --- a/misc/qt_lib_dtkcore.pri.in +++ b/misc/qt_lib_dtkcore.pri.in @@ -3,12 +3,12 @@ QT.dtkcore.MAJOR_VERSION = @PROJECT_VERSION_MAJOR@ QT.dtkcore.MINOR_VERSION = @PROJECT_VERSION_MINOR@ QT.dtkcore.PATCH_VERSION = @PROJECT_VERSION_PATCH@ QT.dtkcore.name = dtkcore -QT.dtkcore.module = dtkcore -QT.dtkcore.tools = @TOOL_INSTALL_DIR@ -QT.dtkcore.libs = @LIBRARY_INSTALL_DIR@ -QT.dtkcore.includes = @INCLUDE_INSTALL_DIR@ +QT.dtkcore.module = dtk@DTK_VERSION_MAJOR@core +QT.dtkcore.tools = @CMAKE_INSTALL_PREFIX@/@TOOL_INSTALL_DIR@ +QT.dtkcore.libs = @CMAKE_INSTALL_PREFIX@/@LIBRARY_INSTALL_DIR@ +QT.dtkcore.includes = @CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ QT.dtkcore.frameworks = -QT.dtkcore.depends = core dbus xml +QT.dtkcore.depends = core dbus xml dtklog QT.dtkcore.module_config = v2 ltcg -QT.dtkcore.DEFINES = +QT.dtkcore.DEFINES += QT_MESSAGELOGCONTEXT QT_MODULES += diff --git a/rpm/dtkcore.spec b/rpm/dtkcore.spec index b3ede9f..d2bf85b 100644 --- a/rpm/dtkcore.spec +++ b/rpm/dtkcore.spec @@ -15,6 +15,8 @@ BuildRequires: annobin BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(gsettings-qt) BuildRequires: gtest-devel +BuildRequires: uchardet-devel +BuildRequires: libicu-devel # since f30 Obsoletes: deepin-tool-kit <= 0.3.3 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41ed7f6..b987702 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,4 @@ #cmake_minimum_required(VERSION 3.5) -set(LIBNAME dtkcore) - set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -8,25 +6,27 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -set (DSG_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}" CACHE STRING "PREFIX of DSG_DATA_DIRS") -add_definitions(-DPREFIX="${DSG_PREFIX_PATH}") -add_definitions(-DLIBDTKCORE_LIBRARY) -find_package(Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) +find_package(Dtk${DTK_VERSION_MAJOR}Log REQUIRED) if(LINUX) -find_package(PkgConfig REQUIRED) -pkg_check_modules(QGSettings REQUIRED gsettings-qt) -find_package(Qt5 REQUIRED COMPONENTS DBus) + find_package(PkgConfig REQUIRED) + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) + if("${QT_VERSION_MAJOR}" STREQUAL "5") + pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) #Dtk6 removed. + endif() + endif() -find_package(Qt5 REQUIRED COMPONENTS Xml) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml) +find_package(DtkBuildHelper REQUIRED) -# start base +# start text encoding +find_package(ICU REQUIRED COMPONENTS uc) +pkg_check_modules(uchardet REQUIRED uchardet) +# end text encoding + +# start base include(base/base.cmake) # end base -if(LINUX) - include(dbus/dbus.cmake) -endif() -#message(${dbus_SRCS}) -# end dbus # start dci include(dci/dci.cmake) @@ -35,14 +35,14 @@ include(dci/dci.cmake) #start filesystem include(filesystem/filesystem.cmake) #end filesystem -# start log +# start log include(log/log.cmake) #end log -# start settings +# start settings include(settings/settings.cmake) #end settings -#start utils +#start utils include(util/util.cmake) #end utils @@ -50,8 +50,7 @@ include(util/util.cmake) include(glob.cmake) #endGLOG if(LINUX) - add_library(${LIBNAME} SHARED - ${dbus_SRCS} + add_library(${LIB_NAME} SHARED ${base_SRCS} ${dci_SRCS} ${filesystem_SRCS} @@ -61,14 +60,23 @@ if(LINUX) ${glob_SRC} ) target_link_libraries( - ${LIBNAME} PRIVATE - Qt5::Core - Qt5::DBus - Qt5::Xml - ${QGSettings_LIBRARIES} + ${LIB_NAME} PUBLIC + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::DBus + Qt${QT_VERSION_MAJOR}::Xml + Dtk${DTK_VERSION_MAJOR}::Log + ) + target_link_libraries(${LIB_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::CorePrivate ) + if("${QT_VERSION_MAJOR}" STREQUAL "5") + target_link_libraries(${LIB_NAME} PRIVATE + PkgConfig::QGSettings + ) + endif() + else() - add_library(${LIBNAME} SHARED + add_library(${LIB_NAME} SHARED ${base_SRCS} ${dci_SRCS} ${filesystem_SRCS} @@ -78,29 +86,72 @@ else() ${glob_SRC} ) target_link_libraries( - ${LIBNAME} PRIVATE - Qt5::Core - Qt5::Xml + ${LIB_NAME} PUBLIC + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Xml ) + target_link_libraries(${LIB_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::CorePrivate + ) + if("${QT_VERSION_MAJOR}" STREQUAL "5") + target_link_libraries(${LIB_NAME} PRIVATE + PkgConfig::QGSettings + ) + endif() endif() -set_target_properties(${LIBNAME} PROPERTIES +set_target_properties(${LIB_NAME} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION} SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR} + EXPORT_NAME Core +) + +target_compile_definitions(${LIB_NAME} PUBLIC + PREFIX="${DSG_PREFIX_PATH}" + DSYSINFO_PREFIX="${DSYSINFO_PREFIX}" +) + +target_compile_definitions(${LIB_NAME} PRIVATE + LIBDTKCORE_LIBRARY +) + +target_include_directories(${LIB_NAME} PRIVATE + ${uchardet_INCLUDE_DIRS} ) -target_include_directories( ${LIBNAME} PUBLIC - ${QGSettings_INCLUDE_DIRS} - ${Qt5Core_PRIVATE_INCLUDE_DIRS} - ../include/util/ - ../include/dci/ - ../include/log/ - ../include/base/ - ../include/base/private - ../include/global/ - ../include/DtkCore/ - ../include/settings/ - ../include/filesystem/ - ../include/ +target_include_directories(${LIB_NAME} PUBLIC + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ ) + +target_include_directories(${LIB_NAME} INTERFACE + $ +) + +target_link_directories(${LIB_NAME} INTERFACE + $ + $ +) + +set(EnableCov CACHE BOOL OFF) +if (EnableCov) + dtk_setup_code_coverage(${LIB_NAME}) +endif() + +dtk_check_and_add_definitions(${LIB_NAME} + DEFS + OS_VERSION_TEST_FILE + LSB_RELEASE_TEST_FILE + OS_RELEASE_TEST_FILE + DEEPIN_VERSION_TEST_FILE +) + set(TOINSTALLBASE ../include/base/dobject.h ../include/base/dsingleton.h @@ -109,18 +160,20 @@ set(TOINSTALLBASE ../include/base/dexpected.h ) install(FILES ${TOINSTALLBASE} DESTINATION "${INCLUDE_INSTALL_DIR}") +install(FILES ${LOG_HEADER} DESTINATION "${INCLUDE_INSTALL_DIR}") +install(FILES ${SETTINGS_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}") +install(FILES ${UTILS_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}") + install(DIRECTORY ../include/dci/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h") install(DIRECTORY ../include/DtkCore/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") install(DIRECTORY ../include/filesystem/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h") install(DIRECTORY ../include/global/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h") -file(GLOB TOINSTALLLOG - ../include/log/*.h -) -install(FILES ${TOINSTALLLOG} DESTINATION "${INCLUDE_INSTALL_DIR}") -file(GLOB TOINSTALLSETTINGS - ../include/settings/*.h - ../include/settings/backend/*.h + +install(TARGETS ${LIB_NAME} EXPORT ${DtkCore}Targets + DESTINATION ${LIBRARY_INSTALL_DIR}) + +install(EXPORT ${DtkCore}Targets + FILE ${DtkCore}Targets.cmake + NAMESPACE Dtk${DTK_VERSION_MAJOR}:: + DESTINATION ${CONFIG_CMAKE_INSTALL_DIR} ) -install(FILES ${TOINSTALLSETTINGS} DESTINATION "${INCLUDE_INSTALL_DIR}") -install(DIRECTORY ../include/util/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h") -install(TARGETS ${LIBNAME} DESTINATION ${LIBRARY_INSTALL_DIR}) diff --git a/src/dbus/dbus.cmake b/src/dbus/dbus.cmake index 2d239e1..077b10e 100644 --- a/src/dbus/dbus.cmake +++ b/src/dbus/dbus.cmake @@ -1,21 +1,38 @@ set(dbus_SRCS) set_source_files_properties( - ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.xml - PROPERTIES - NO_NAMESPACE ON - CLASSNAME DSGConfig -) -qt5_add_dbus_interface(dbus_SRCS ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.xml - configmanager_interface + PROPERTIES + NO_NAMESPACE ON + CLASSNAME DSGConfig ) + +if("${QT_VERSION_MAJOR}" STREQUAL "6") + qt_add_dbus_interface(dbus_SRCS + ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.xml + configmanager_interface + ) +else() + qt5_add_dbus_interface(dbus_SRCS + ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.xml + configmanager_interface + ) +endif() + set_source_files_properties( ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.Manager.xml PROPERTIES NO_NAMESPACE ON CLASSNAME DSGConfigManager ) -qt5_add_dbus_interface(dbus_SRCS + +if("${QT_VERSION_MAJOR}" STREQUAL "6") + qt_add_dbus_interface(dbus_SRCS + ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.Manager.xml + manager_interface + ) +else() + qt5_add_dbus_interface(dbus_SRCS ${CMAKE_CURRENT_LIST_DIR}/org.desktopspec.ConfigManager.Manager.xml manager_interface -) + ) +endif() diff --git a/src/dbus/org.desktopspec.ConfigManager.Manager.xml b/src/dbus/org.desktopspec.ConfigManager.Manager.xml index 89a2aab..e279c85 100644 --- a/src/dbus/org.desktopspec.ConfigManager.Manager.xml +++ b/src/dbus/org.desktopspec.ConfigManager.Manager.xml @@ -13,6 +13,10 @@ SPDX-License-Identifier: LGPL-3.0-or-later + + + + diff --git a/src/dci/ddcifile.cpp b/src/dci/ddcifile.cpp index 0894daf..f0c7d58 100644 --- a/src/dci/ddcifile.cpp +++ b/src/dci/ddcifile.cpp @@ -92,25 +92,26 @@ public: QString linkPath() const { const QString &path = QString::fromUtf8(data); - if (path.startsWith('/')) + QStringView pathView{path}; + if (pathView.startsWith('/')) return path; // 转为绝对路径 auto pNode = parent; int pathStart = 0; - while (pathStart < path.size()) { - if (path.midRef(pathStart, 3) == QLatin1String("../")) { + while (pathStart < pathView.size()) { + if (pathView.mid(pathStart, 3) == QLatin1String("../")) { pathStart += 3; pNode = pNode->parent; if (!pNode) return QString(); - } else if (path.midRef(pathStart, 2) == QLatin1String("./")) { + } else if (pathView.mid(pathStart, 2) == QLatin1String("./")) { pathStart += 2; } else { break; } } Q_ASSERT(pNode); - return pNode->path() + QLatin1Char('/') + path.midRef(pathStart); + return pNode->path() + QLatin1Char('/') + path.mid(pathStart); } }; @@ -454,7 +455,7 @@ DDciFile::DDciFile(const QByteArray &data) bool DDciFile::isValid() const { D_DC(DDciFile); - return d->root; + return !!(d->root); } QString DDciFile::lastErrorString() const diff --git a/src/dci/private/ddcifileengine.cpp b/src/dci/private/ddcifileengine.cpp index 9e4fd6f..d111f0a 100644 --- a/src/dci/private/ddcifileengine.cpp +++ b/src/dci/private/ddcifileengine.cpp @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later +#include + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include //Avoid changing the access control of the standard library +#endif #define private public #define protected public @@ -25,14 +30,25 @@ Q_LOGGING_CATEGORY(logFE, "dtk.dci.fileengine", QtInfoMsg) #define DCI_FILE_SCHEME "dci:" #define DCI_FILE_SUFFIX ".dci" +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +std::unique_ptr DDciFileEngineHandler::create(const QString &fileName) const +#else QAbstractFileEngine *DDciFileEngineHandler::create(const QString &fileName) const +#endif { if (!fileName.startsWith(QStringLiteral(DCI_FILE_SCHEME))) return nullptr; +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + std::unique_ptr engine(new DDciFileEngine(fileName)); +#else DDciFileEngine *engine = new DDciFileEngine(fileName); +#endif + if (!engine->isValid()) { +#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) delete engine; +#endif return nullptr; } @@ -61,11 +77,24 @@ static DDciFileShared getDciFile(const QString &dciFilePath, bool usePath = true } DDciFileEngineIterator::DDciFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters) +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + : QAbstractFileEngineIterator(nullptr, filters, nameFilters) +#else : QAbstractFileEngineIterator(filters, nameFilters) +#endif { } +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) +DDciFileEngineIterator::DDciFileEngineIterator(QDirListing::IteratorFlags filters, const QStringList &nameFilters) + : QAbstractFileEngineIterator(nullptr, filters, nameFilters) +{ + +} +#endif + +#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) QString DDciFileEngineIterator::next() { current = nextValid; @@ -73,6 +102,9 @@ QString DDciFileEngineIterator::next() } bool DDciFileEngineIterator::hasNext() const +#else +bool DDciFileEngineIterator::advance() +#endif { if (!file) { const auto paths = DDciFileEngine::resolvePath(path()); @@ -106,6 +138,9 @@ bool DDciFileEngineIterator::hasNext() const continue; nextValid = i; +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + current = nextValid; +#endif return true; } @@ -132,7 +167,11 @@ bool DDciFileEngine::isValid() const return file && file->isValid(); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) +bool DDciFileEngine::open(QIODevice::OpenMode openMode, std::optional permissions) +#else bool DDciFileEngine::open(QIODevice::OpenMode openMode) +#endif { if (fileBuffer) { setError(QFile::OpenError, "The file is opened"); @@ -179,9 +218,15 @@ bool DDciFileEngine::open(QIODevice::OpenMode openMode) // 此时当文件不存在时应当创建它 if (openMode & QIODevice::WriteOnly) { realDciFile.setFileName(dciFilePath); +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + auto success = permissions ? realDciFile.open(openMode, permissions.value()) : realDciFile.open(openMode); + if (!success) + return false; +#else if (!realDciFile.open(openMode)) { return false; } +#endif // 不存在时尝试新建 if (!file->exists(subfilePath) @@ -327,8 +372,16 @@ bool DDciFileEngine::link(const QString &newName) return file->link(subfilePath, linkPath) && forceSave(); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) +bool DDciFileEngine::mkdir(const QString &dirName, + bool createParentDirectories, + std::optional permissions) const +{ + Q_UNUSED(permissions) +#else bool DDciFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const { +#endif if (!file->isValid()) return false; // 解析出新的 dci 内部文件路径 @@ -475,7 +528,11 @@ QString DDciFileEngine::fileName(QAbstractFileEngine::FileName file) const return QDir::cleanPath(DCI_FILE_SCHEME + dciFilePath); case BaseName: return QFileInfo(subfilePath).baseName(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + case AbsoluteLinkTarget: +#else case LinkName: +#endif return this->file->type(subfilePath) == DDciFile::Symlink ? this->file->symlinkTarget(subfilePath) : QString(); @@ -504,17 +561,38 @@ void DDciFileEngine::setFileName(const QString &fullPath) file = getDciFile(dciFilePath, QFile::exists(dciFilePath)); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 1) +QDateTime DDciFileEngine::fileTime(QFile::FileTime time) const +{ + return QFileInfo(dciFilePath).fileTime(time); +} +#else QDateTime DDciFileEngine::fileTime(QAbstractFileEngine::FileTime time) const { return QFileInfo(dciFilePath).fileTime(static_cast(time)); } - +#endif +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) +QAbstractFileEngine::IteratorUniquePtr DDciFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) +#elif QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +QAbstractFileEngine::IteratorUniquePtr DDciFileEngine::beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) +#else DDciFileEngine::Iterator *DDciFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames) +#endif { +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + Q_UNUSED(path); + return QAbstractFileEngine::IteratorUniquePtr(new DDciFileEngineIterator(filters, filterNames)); +#else return new DDciFileEngineIterator(filters, filterNames); +#endif } +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +QAbstractFileEngine::IteratorUniquePtr DDciFileEngine::endEntryList() +#else DDciFileEngine::Iterator *DDciFileEngine::endEntryList() +#endif { return nullptr; } diff --git a/src/dci/private/ddcifileengine_p.h b/src/dci/private/ddcifileengine_p.h index 5a2b84c..4413c92 100644 --- a/src/dci/private/ddcifileengine_p.h +++ b/src/dci/private/ddcifileengine_p.h @@ -24,7 +24,11 @@ DCORE_BEGIN_NAMESPACE class DDciFileEngineHandler : public QAbstractFileEngineHandler { public: +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + std::unique_ptr create(const QString &fileName) const override; +#else QAbstractFileEngine *create(const QString &fileName) const override; +#endif }; class DDciFile; @@ -35,8 +39,13 @@ class DDciFileEngineIterator : public QAbstractFileEngineIterator public: DDciFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters); +#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) QString next() override; bool hasNext() const override; +#else + DDciFileEngineIterator(QDirListing::IteratorFlags filters, const QStringList &nameFilters); + bool advance() override; +#endif QString currentFileName() const override; @@ -55,7 +64,11 @@ public: ~DDciFileEngine(); bool isValid() const; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + bool open(QIODevice::OpenMode openMode, std::optional permissions = std::nullopt) override; +#else bool open(QIODevice::OpenMode openMode) override; +#endif bool close() override; bool flushToFile(QFile *target, bool writeFile) const; bool flush() override; @@ -70,7 +83,13 @@ public: bool rename(const QString &newName) override; bool renameOverwrite(const QString &newName) override; bool link(const QString &newName) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + bool mkdir(const QString &dirName, + bool createParentDirectories, + std::optional permissions = std::nullopt) const override; +#else bool mkdir(const QString &dirName, bool createParentDirectories) const override; +#endif bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; bool setSize(qint64 size) override; bool caseSensitive() const override; @@ -85,11 +104,23 @@ public: void setFileName(const QString &fullPath) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 1) + QDateTime fileTime(QFile::FileTime time) const override; +#else QDateTime fileTime(FileTime time) const override; +#endif typedef DDciFileEngineIterator Iterator; +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) + IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) override; + IteratorUniquePtr endEntryList() override; +#elif QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) override; + IteratorUniquePtr endEntryList() override; +#else Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override; Iterator *endEntryList() override; +#endif qint64 read(char *data, qint64 maxlen) override; qint64 write(const char *data, qint64 len) override; diff --git a/src/dconfig.cpp b/src/dconfig.cpp index 86e244e..ef7325a 100644 --- a/src/dconfig.cpp +++ b/src/dconfig.cpp @@ -24,60 +24,75 @@ DCORE_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(cfLog) +static QString NoAppId; /*! - \class Dtk::Core::DConfigBackend +@~english + @class Dtk::Core::DConfigBackend \inmodule dtkcore - \brief 配置后端的抽象接口. + @brief Configure the abstract interface of the backend. - 所有DConfig使用的配置后端都继承此类,用户可以继承此类实现自己的配置后端. + All configuration backends used by DConfig inherit this class, and users can inherit this class to implement their own configuration backends. */ /*! - \fn bool DConfigBackend::load(const QString &) = 0 +@~english + @fn bool DConfigBackend::load(const QString &) = 0 - \brief 初始化后端 + @brief Initialize the backend - \a appId 管理的配置信息key值,默认为应用程序名称 + \a appId Managed configuration information key value, the default is the application name. */ /*! - \fn bool DConfigBackend::isValid() const = 0 +@~english + @fn bool DConfigBackend::isValid() const = 0 - \sa DConfig::isValid(). + @sa DConfig::isValid(). */ /*! - \fn QStringList DConfigBackend::keyList() const = 0 +@~english + @fn QStringList DConfigBackend::keyList() const = 0 - \sa DConfig::keyList() + @sa DConfig::keyList() */ /*! - \fn QVariant DConfigBackend::value(const QString &key, const QVariant &fallback = QVariant()) const = 0 +@~english + @fn QVariant DConfigBackend::value(const QString &key, const QVariant &fallback = QVariant()) const = 0 - \sa DConfig::value() + @sa DConfig::value() */ /*! - \fn void DConfigBackend::setValue(const QString &key, const QVariant &value) = 0 +@~english + @fn void DConfigBackend::setValue(const QString &key, const QVariant &value) = 0 - \sa DConfig::setValue() + @sa DConfig::setValue() */ /*! - \fn void DConfigBackend::reset(const QString &key) +@~english + @fn void DConfigBackend::reset(const QString &key) - \sa DConfig::reset() + @sa DConfig::reset() */ /*! - \fn QString DConfigBackend::name() const = 0 +@~english + @fn QString DConfigBackend::name() const = 0 - \brief 后端配置的唯一标识 + @brief The unique identity of the backend configuration + +/*! +@~english + @fn bool DConfigBackend::isDefaultValue(const QString &key) const = 0 + + @sa DConfig::isDefaultValue() */ @@ -85,6 +100,7 @@ DConfigBackend::~DConfigBackend() { } +static QString _globalAppId; class Q_DECL_HIDDEN DConfigPrivate : public DObjectPrivate { public: @@ -93,7 +109,7 @@ public: const QString &name, const QString &subpath) : DObjectPrivate(qq) - , appId(appId.isEmpty() ? DSGApplication::id() : appId) + , appId(appId) , name(name) , subpath(subpath) { @@ -149,8 +165,23 @@ public: configCache.reset(configFile->createUserCache(getuid())); const QString &prefix = localPrefix(); - return configFile->load(prefix) && - configCache->load(prefix); + if (!configFile->load(prefix) || !configCache->load(prefix)) + return false; + + // generic config doesn't need to fallback to generic configration. + if (owner->appId == NoAppId) + return true; + + QScopedPointer file(new DConfigFile(NoAppId, owner->name, owner->subpath)); + const bool canFallbackToGeneric = !file->meta()->metaPath(prefix).isEmpty(); + if (canFallbackToGeneric) { + QScopedPointer cache(file->createUserCache(getuid())); + if (file->load(prefix) && cache->load(prefix)) { + genericConfigFile.reset(file.take()); + genericConfigCache.reset(cache.take()); + } + } + return true; } virtual QStringList keyList() const override @@ -160,8 +191,29 @@ public: virtual QVariant value(const QString &key, const QVariant &fallback) const override { - const QVariant &v = configFile->value(key, configCache.get()); - return v.isValid() ? v : fallback; + const QVariant &vc = configFile->cacheValue(configCache.get(), key); + if (vc.isValid()) + return vc; + + // fallback to generic configuration, and use itself's configuration if generic isn't set. + if (genericConfigFile) { + const auto &tmp = genericConfigFile->cacheValue(genericConfigCache.get(), key); + if (tmp.isValid()) + return tmp; + } + const QVariant &v = configFile->value(key); + if (v.isValid()) + return v; + // fallback to default value of generic configuration. + const QVariant &vg = genericConfigFile->value(key); + return vg.isValid() ? vg : fallback; + } + + virtual bool isDefaultValue(const QString &key) const override + { + // Don't fallback to generic configuration + const QVariant &vc = configFile->cacheValue(configCache.get(), key); + return !vc.isValid(); } virtual void setValue(const QString &key, const QVariant &value) override @@ -174,8 +226,7 @@ public: virtual void reset(const QString &key) override { - const auto &originValue = configFile->meta()->value(key); - setValue(key, originValue); + setValue(key, QVariant()); } virtual QString name() const override @@ -195,6 +246,8 @@ private: private: QScopedPointer configFile; QScopedPointer configCache; + QScopedPointer genericConfigFile; + QScopedPointer genericConfigCache; DConfigPrivate* owner; const QByteArray envLocalPrefix = qgetenv("DSG_DCONFIG_FILE_BACKEND_LOCAL_PREFIX"); }; @@ -210,6 +263,14 @@ FileBackend::~FileBackend() configFile->save(prefix); configFile.reset(); } + if (genericConfigCache) { + genericConfigCache->save(prefix); + genericConfigCache.reset(); + } + if (genericConfigFile) { + genericConfigFile->save(prefix); + genericConfigFile.reset(); + } } #ifndef D_DISABLE_DBUS_CONFIG @@ -249,10 +310,11 @@ public: } /*! + @~english \internal - 初始化DBus连接,会先调用acquireManager动态获取一个配置连接, - 再通过这个配置连接进行配置文件的访问. + Initialize the DBus connection, the call acquireManager dynamically obtains a configuration connection, + The configuration file is then accessed through this configuration connection. */ virtual bool load(const QString &/*appId*/) override { @@ -331,14 +393,34 @@ public: return decodeQDBusArgument(reply.value().variant()); } + virtual bool isDefaultValue(const QString &key) const override + { + auto reply = config->isDefaultValue(key); + reply.waitForFinished(); + if (reply.isError()) { + qWarning() << "Failed to call `isDefaultValue`, key:" << key + << ", error message:" << reply.error().message(); + return false; + } + return reply.value(); + } + virtual void setValue(const QString &key, const QVariant &value) override { - config->setValue(key, QDBusVariant(value)); + auto reply = config->setValue(key, QDBusVariant(value)); + reply.waitForFinished(); + if (reply.isError()) + qCWarning(cfLog) << "Failed to setValue for the key:" << key + << ", error message:" << reply.error(); } virtual void reset(const QString &key) override { - config->reset(key); + auto reply = config->reset(key); + reply.waitForFinished(); + if (reply.isError()) + qCWarning(cfLog) << "Failed to reset for the key:" << key + << ", error message:" << reply.error(); } virtual QString name() const override @@ -425,12 +507,13 @@ DConfigPrivate::~DConfigPrivate() } /*! +@~english \internal - \brief 创建一个配置后端 + @brief Create a configuration backend - 默认使用的配置后端会优先根据环境变量来选择配置中心的D-Bus接口还是文件配置后端接口。 - 若没有配置此环境变量,则根据是否有配置中心提供D-Bus服务来选择配置中心服务还是文件配置后端接口. + The default configuration backend preferentially selects the D-Bus interface in the configuration center or the file configuration backend interface based on environment variables. + If this environment variable is not configured, the configuration center service or file configuration backend interface will be selected according to whether the configuration center provides D-Bus services */ DConfigBackend *DConfigPrivate::getOrCreateBackend() { @@ -462,11 +545,12 @@ DConfigBackend *DConfigPrivate::getOrCreateBackend() } /*! +@~english \internal - \brief 创建一个配置后端 + @brief Create a configuration backend - 尝试根据环境变量来选择配置中心的D-Bus接口还是文件配置后端接口。 + Try to choose between configuring the D-Bus interface in the center or the file configuration backend interface based on the environment variables. */ DConfigBackend *DConfigPrivate::createBackendByEnv() { @@ -501,21 +585,24 @@ DConfigBackend *DConfigPrivate::createBackendByEnv() } /*! - \class Dtk::Core::DConfig +@~english + @class Dtk::Core::DConfig \inmodule dtkcore - \brief 配置策略提供的接口类 + @brief Configure the interface class provided by the policy - 此接口规范定义了开发库所提供的关于配置文件读写的相关接口, - 如果应用程序所使用的开发库实现了此规范,则程序应当优先使用开发库提供的接口。 + + This interface specification defines the relevant interfaces provided by the development library for reading and writing configuration files, + If the application uses a development library that implements this specification, the application should use the interfaces provided by the development library first. */ /*! - * \brief 构造配置策略提供的对象 - * \a name 配置文件名 - * \a subpath 配置文件对应的子目录 - * \a parent 父对象 +@~english + * @brief Constructs the objects provided by the configuration policy + * \a name Configuration File Name + * \a subpath Subdirectory corresponding to the configuration file + * \a parent Parent object */ DConfig::DConfig(const QString &name, const QString &subpath, QObject *parent) : DConfig(nullptr, name, subpath, parent) @@ -523,36 +610,74 @@ DConfig::DConfig(const QString &name, const QString &subpath, QObject *parent) } DConfig::DConfig(DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent) - : DConfig(backend, QString(), name, subpath, parent) + : DConfig(backend, _globalAppId.isEmpty() ? DSGApplication::id() : _globalAppId, name, subpath, parent) { } + /*! - * \brief 构造配置策略提供的对象, 指定配置所属的应用Id +@~english + * @brief Constructs the object provided by the configuration policy, specifying the application Id to which the configuration belongs. * \a appId * \a name * \a subpath * \a parent - * \return 构造的配置策略对象,由调用者释放 + * @return The constructed configuration policy object, which is released by the caller + * @note \a appId is not empty. */ DConfig *DConfig::create(const QString &appId, const QString &name, const QString &subpath, QObject *parent) { + Q_ASSERT(appId != NoAppId); return new DConfig(nullptr, appId, name, subpath, parent); } DConfig *DConfig::create(DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent) { + Q_ASSERT(appId != NoAppId); return new DConfig(backend, appId, name, subpath, parent); } /*! - * \brief 使用自定义的配置策略后端构造对象 - * \a backend 调用者继承于DConfigBackend的配置策略后端 - * \a appId 配置文件所属的应用Id,为空时默认为本应用Id - * \a name 配置文件名 - * \a subpath 配置文件对应的子目录 - * \a parent 父对象 - * \note 调用者只构造backend,由DConfig释放。 + * \brief Constructs the object, and which is application. + * \param name + * \param subpath + * \param parent + * \return Dconfig object, which is released by the caller + * @note It's usually used for application independent, we should use DConfig::create if the configuration is a specific application. + */ +DConfig *DConfig::createGeneric(const QString &name, const QString &subpath, QObject *parent) +{ + return new DConfig(nullptr, NoAppId, name, subpath, parent); +} + +DConfig *DConfig::createGeneric(DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent) +{ + return new DConfig(backend, NoAppId, name, subpath, parent); +} + +/*! + * \brief Explicitly specify application Id for config. + * \param appId + * @note It's should be called before QCoreApplication constructed. + */ +void DConfig::setAppId(const QString &appId) +{ + if (!_globalAppId.isEmpty()) { + qCWarning(cfLog, "`setAppId`should only be called once."); + } + _globalAppId = appId; + qCDebug(cfLog, "Explicitly specify application Id as appId=%s for config.", qPrintable(appId)); +} + +/*! +@~english + * @brief Use custom configuration policy backend to construct objects + * \a backend The caller inherits the configuration policy backend of DConfigBackend + * \a appId The application Id of the configuration file. If it is blank, it will be the application Id by default + * \a name Configuration File Name + * \a subpath Subdirectory corresponding to the configuration file + * \a parent Parent object + * @note The caller only constructs backend, which is released by DConfig. */ DConfig::DConfig(DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent) : QObject(parent) @@ -560,8 +685,6 @@ DConfig::DConfig(DConfigBackend *backend, const QString &appId, const QString &n { D_D(DConfig); - Q_ASSERT(!d->appId.isEmpty()); - qCDebug(cfLog, "Load config of appid=%s name=%s, subpath=%s", qPrintable(d->appId), qPrintable(d->name), qPrintable(d->subpath)); @@ -575,9 +698,10 @@ DConfig::DConfig(DConfigBackend *backend, const QString &appId, const QString &n } /*! - * \brief DConfig::backendName - * \return 配置策略后端名称 - * \note 调用者只能用DConfig访问DConfigBackend对象,所以不返回DConfigBackend对象。 +@~english + * @brief DConfig::backendName + * @return Configure policy backend name + * @note The caller can only access the DConfigBackend object with DConfig, so the DConfigBackend object is not returned. */ QString DConfig::backendName() const { @@ -589,8 +713,9 @@ QString DConfig::backendName() const } /*! - * \brief 获得所有可用的配置项名称 - * \return 配置项名称集合 +@~english + * @brief Get all available configuration item names + * @return Configuration item name collection */ QStringList DConfig::keyList() const { @@ -602,8 +727,9 @@ QStringList DConfig::keyList() const } /*! - * \brief 判断此后端是否可用 - * \return +@~english + * @brief Check whether the backend is available + * @return */ bool DConfig::isValid() const { @@ -612,10 +738,25 @@ bool DConfig::isValid() const } /*! - * \brief 根据配置项名称获得对应值 - * \param key 配置项名称 - * \param fallback 没有获取到配置项值后提供的默认值 - * \return +@~english + * @brief Check whether the value is default according to the configuration item name + * @param key Configuration Item Name + * @return Return `true` if the value isn't been set, otherwise return `false` + */ +bool DConfig::isDefaultValue(const QString &key) const +{ + D_DC(DConfig); + if (d->invalid()) + return false; + return d->backend->isDefaultValue(key); +} + +/*! +@~english + * @brief Get the corresponding value according to the configuration item name + * @param key Configuration Item Name + * @param fallback The default value provided after the configuration item value is not obtained + * @return */ QVariant DConfig::value(const QString &key, const QVariant &fallback) const { @@ -627,9 +768,10 @@ QVariant DConfig::value(const QString &key, const QVariant &fallback) const } /*! - * \brief 根据配置项名称设置其值 - * \param 配置项名称 - * \param 需要更新的值 +@~english + * @brief Set the value according to the configuration item name + * @param key Configuration Item Name + * @param value Values that need to be updated */ void DConfig::setValue(const QString &key, const QVariant &value) { @@ -641,8 +783,9 @@ void DConfig::setValue(const QString &key, const QVariant &value) } /*! - * \brief 设置其配置项对应的默认值,此值为经过override机制覆盖后的值,不一定为此配置文件中meta中定义的值 - * \param 配置项名称 +@~english + * @brief Set the default value corresponding to its configuration item. This value is overridden by the override mechanism. It is not necessarily the value defined in the meta in this configuration file + * @param key Configuration Item Name */ void DConfig::reset(const QString &key) { @@ -654,8 +797,9 @@ void DConfig::reset(const QString &key) } /*! - * \brief 返回配置文件名称 - * \return +@~english + * @brief Return configuration file name + * @return */ QString DConfig::name() const { @@ -664,8 +808,9 @@ QString DConfig::name() const } /*! - * \brief 返回配置文件对应的子目录 - * \return +@~english + * @brief Return the subdirectory corresponding to the configuration file + * @return */ QString DConfig::subpath() const { diff --git a/src/dconfigfile.cpp b/src/dconfigfile.cpp index 6b875a4..896248a 100644 --- a/src/dconfigfile.cpp +++ b/src/dconfigfile.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -36,10 +36,34 @@ Q_LOGGING_CATEGORY(cfLog, "dtk.dsg.config"); #define FILE_SUFFIX QLatin1String(".json") +// subpath must be a subdirectory of the dir. +inline static bool subpathIsValid(const QString &subpath, const QDir &dir) +{ + if (subpath.isEmpty()) + return true; + + const QDir subDir(dir.filePath(subpath.mid(1))); + return subDir.absolutePath().startsWith(dir.absolutePath()); +} +// name must be a valid filename. +inline static bool isValidFilename(const QString& filename) +{ + static const QRegularExpression regex("^[\\w\\-\\.\\ ]+$"); + QRegularExpressionMatch match = regex.match(filename); + return match.hasMatch(); +} +// AppId don't contain ' ', but it can be empty. +inline static bool isValidAppId(const QString& appId) +{ + static const QRegularExpression regex("^[\\w\\-\\.]*$"); + QRegularExpressionMatch match = regex.match(appId); + return match.hasMatch(); +} /*! +@~english \internal - \brief 按子目录查找机制查找配置文件 + @brief 按子目录查找机制查找配置文件 在 \a baseDir目录下,查找名称为 \a name的文件, 若存在 \a subpath,则从 \a subpath叶子目录逐级向上查找名称为 \a name的文件, @@ -51,6 +75,10 @@ inline QString getFile(const QString &baseDir, const QString &subpath, const QSt qPrintable(baseDir), qPrintable(subpath), qPrintable(name)); const QDir base_dir(baseDir); + if (!subpathIsValid(subpath, base_dir)) { + qCDebug(cfLog, "subpath is invalid in the base dir:\"%s\", subpath:\"%s\".", qPrintable(baseDir), qPrintable(subpath)); + return QString(); + } QDir target_dir = base_dir; if (!subpath.isEmpty()) @@ -164,57 +192,83 @@ inline static QString getUserName(const uint uid) { } /*! - \class Dtk::Core::DConfigFile +@~english + @class Dtk::Core::DConfigFile \inmodule dtkcore - \brief 规范配置文件读写的相关接口的配置文件实现. + @brief Specification configuration file implementation of the interface that the configuration file reads and writes. */ /*! - \enum DConfigFile::Flag - - \value NoOverride 存在此标记时,将表明则此配置项不可被覆盖(详见下述 override 机制)。 - 反之,不存在此标记时表明此配置项允许被覆盖,对于此类配置项, - 如若其有界面设置入口,则当此项不可写时,应当隐藏或禁用界面的设置入口. - \value Global 当读写此类配置时,将忽略用户身份,无论程序使用哪个用户身份执行,读操作都将获取到同样的数据, - 写操作将对所有用户都生效。但是,如果对应的配置存储目录不存在或无权限写入,则忽略此标志. +@~english + @enum DConfigFile::Flag + + \value NoOverride When this flag exists , it indicates that this configuration item can't be overwritten (see the override mechanism below for details). + Otherwise, the absence of this flag indicates that this configuration item is allowed to be overwritten, + If it has a screen setting entry, hide or disable the screen setting entry when this entry is not writable. + \value Global When reading or writing such a configuration, the user identity is ignored and the same data is obtained regardless of which user identity the program executes. + The write operation will take effect for all users. However, if the corresponding configuration storage directory does not exist or has no write permission, this flag is ignored. */ /*! - \enum DConfigFile::Permissions +@~english + @enum DConfigFile::Permissions - \value ReadOnly 将配置项覆盖为只读, - \value ReadWrite 将配置项覆盖为可读可写. + \value ReadOnly Overwrite the configuration item as readonly. + \value ReadWrite Overwrite the configuration item as readable and writable. */ /*! - \enum DConfigFile::Visibility - - \value Private 仅限程序内部使用, - 对外不可见。此类配置项完全由程序自己读写,可随意增删改写其含义,无需做兼容性考虑, - \value Public 外部程序可使用。 - 此类配置项一旦发布,在兼容性版本的升级中,要保障此配置项向下兼容, - 简而言之,只允许在程序/库的大版本升级时才允许删除或修改此类配置项, - 当配置项的 permissions、visibility、flags 任意一个属性被修改则认为此配置项被修改, - 除此之外修改 value、name、description 属性时则不需要考虑兼容性. +@~english + @enum DConfigFile::Visibility + + \value Private For internal program use only, + Not visible to the outside world. Such configuration items are completely read and written by the program itself, and can be added, deleted and rewritten at will without compatibility consideration, + \value Public External programs are available. + Once this type of configuration item is released, ensure that the configuration item is backward compatible during the upgrade of the compatible version. + In short, this type of configuration item is only allowed to be deleted or modified when a major version of the program/library is upgraded. + The configuration item is changed if any of its permissions, visibility, or flags properties are changed. + In addition, you do not need to consider compatibility when modifying the value, name, and description attributes. */ /*! - \struct Dtk::Core::DConfigFile::Version +@~english + @struct Dtk::Core::DConfigFile::Version \inmodule dtkcore - \brief 版本信息 - - 此文件的内容格式的版本。版本号使用两位数字描述, - 首位数字不同的描述文件相互之间不兼容,第二位数字不同的描述文件需满足向下兼容。 - 读取此描述文件的程序要根据版本进行内容分析,当遇到不兼容的版本时,需要立即终止解析,忽略此文件, - 并在程序日志中写入警告信息,如 “1.0” 和 “2.0” 版本之间不兼容, - 如果解析程序最高只支持 1.0 版本,则遇到 2.0 版本的描述文件时应该终止解析, - 但是如果遇到 1.1 版本,则可以继续执行。 - 写入此描述文件时,遇到不兼容的版本时,需要先清空当前内容再写入,每次写入皆需更新此字段。 + @brief Version Information + + The content format version of this file. The version number is described by two digits, + Profiles with different first digits are incompatible with each other, and profiles with different second digits need to be compatible with each other. + A program that reads this profile needs to perform content analysis by version, and when it encounters an incompatible version, it needs to terminate parsing immediately and ignore the file. + And write a warning message to the program log, such as "1.0" and "2.0" versions are not compatible, + If the parser only supports version 1.0, it should stop parsing when it encounters a 2.0 profile. + But if version 1.1 is encountered, execution can continue. + When writing to this profile, if an incompatible version is encountered, the current contents need to be cleared before writing, and this field needs to be updated with each write */ DConfigMeta::~DConfigMeta() {} +QStringList DConfigMeta::genericMetaDirs(const QString &localPrefix) +{ + QStringList paths; + // lower priority is higher. + for (auto item: DStandardPaths::paths(DStandardPaths::DSG::DataDir)) { + paths.prepend(QDir::cleanPath(QString("%1/%2/configs").arg(localPrefix, item))); + } + return paths; +} + +QStringList DConfigMeta::applicationMetaDirs(const QString &localPrefix, const QString &appId) +{ + QStringList paths; + const auto &dataPaths = genericMetaDirs(localPrefix); + paths.reserve(dataPaths.size()); + for (auto item : dataPaths) { + paths << QString("%1/%2").arg(item, appId); + } + return paths; +} + Dtk::Core::DConfigCache::~DConfigCache() {} struct DConfigKey { @@ -296,6 +350,8 @@ public: flags |= DConfigFile::NoOverride; } else if (flag == QLatin1String("global")) { flags |= DConfigFile::Global; + } else if (flag == QLatin1String("user-public")) { + flags |= DConfigFile::UserPublic; } } @@ -365,6 +421,11 @@ public: return values.keys(); } + inline bool contains(const QString &key) const + { + return values.contains(key); + } + inline void remove(const QString &key) { values.remove(key); @@ -419,127 +480,143 @@ private: /*! - \class Dtk::Core::DConfigMeta +@~english + @class Dtk::Core::DConfigMeta \inmodule dtkcore - \brief 提供配置文件的原型和覆盖机制的访问接口. + @brief Provides a prototype of the configuration file and an access interface to the override mechanism. */ /*! - \fn DConfigFile::Version DConfigMeta::version() const = 0; +@~english + @fn DConfigFile::Version DConfigMeta::version() const = 0; - \brief 返回配置版本信息. - \return + @brief Returns configuration version information. + @return */ /*! - \fn void DConfigMeta::setVersion(quint16 major, quint16 minor) = 0; +@~english + @fn void DConfigMeta::setVersion(quint16 major, quint16 minor) = 0; - \brief 设置配置版本信息 - \a major 主板本号 - \a minor 次版本号 + @brief Sets configuration version information + \a major Major version number + \a minor Minor version number */ /*! - \fn bool DConfigMeta::load(const QString &localPrefix = QString()) = 0; +@~english + @fn bool DConfigMeta::load(const QString &localPrefix = QString()) = 0; - \brief 解析配置文件 - \a localPrefix 为目录前缀 - \return + @brief Parsing configuration files + \a localPrefix Directory prefix + @return */ /*! - \fn bool DConfigMeta::load(QIODevice *meta, const QList &overrides) = 0; +@~english + @fn bool DConfigMeta::load(QIODevice *meta, const QList &overrides) = 0; - \brief 解析配置文件流 - \a meta 为原型流 - \a overrides 为覆盖机制查找的文件流 - \return + @brief Parse the configuration file stream + \a meta Prototype stream + \a overrides The file stream to find for the override mechanism + @return */ /*! - \fn QStringList DConfigMeta::keyList() const = 0; +@~english + @fn QStringList DConfigMeta::keyList() const = 0; - \brief 返回配置内容的所有配置项 - \return + @brief Returns all configuration items for the configuration content + @return */ /*! - \fn DConfigFile::Flags DConfigMeta::flags(const QString &key) const = 0; +@~english + @fn DConfigFile::Flags DConfigMeta::flags(const QString &key) const = 0; - \brief 返回指定配置项的特性 - \a key 配置项名称, NoOverride为此配置项不可被覆盖, Global为忽略用户身份 - \return + @brief Returns the attribute of the specified configuration item + \a key Configure the name of the option, NoOverride This option can't be overridden, and Global ignores the user identity + @return */ /*! - \fn DConfigFile::Permissions DConfigMeta::permissions(const QString &key) const = 0; +@~english + @fn DConfigFile::Permissions DConfigMeta::permissions(const QString &key) const = 0; - \brief 返回指定配置项的权限 - \a key 配置项名称 - \return + @brief Returns the permission for the specified configuration item + \a key Configuration name + @return */ /*! - \fn DConfigFile::Visibility DConfigMeta::visibility(const QString &key) const = 0; +@~english + @fn DConfigFile::Visibility DConfigMeta::visibility(const QString &key) const = 0; - \brief 返回指定配置项的可见性 - \a key 配置项名称 - \return + @brief Returns the visibility of the specified configuration item + \a key Configuration name + @return */ /*! - \fn int DConfigMeta::serial(const QString &key) const = 0; +@~english + @fn int DConfigMeta::serial(const QString &key) const = 0; + + @brief Returns a monotonically increasing value of a configuration item + \a key Configuration name + @return An invalid value of -1 indicates that the entry is not configured - \brief 返回配置项的单调递增值 - \a key 配置项名称 - \return -1为无效值,表明没有配置此项 */ /*! - \fn QString DConfigMeta::displayName(const QString &key, const QLocale &locale) = 0; +@~english + @fn QString DConfigMeta::displayName(const QString &key, const QLocale &locale) = 0; - \brief 返回指定配置项的显示名 - \a key 配置项名称 - \a locale 为语言版本 - \return + @brief Returns the display name of the specified configuration + \a key Configuration name + \a locale Language version + @return */ /*! - \fn QString DConfigMeta::description(const QString &key, const QLocale &locale) = 0; +@~english + @fn QString DConfigMeta::description(const QString &key, const QLocale &locale) = 0; - \brief 返回指定配置项的描述信息 - \a key 配置项名称 - \a locale 为语言版本 - \return + @brief Returns a description of the specified configuration item + \a key Configuration name + \a locale Language version + @return */ /*! - \fn QString DConfigMeta::metaPath(const QString &localPrefix = QString(), bool *useAppId = nullptr) const = 0; +@~english + @fn QString DConfigMeta::metaPath(const QString &localPrefix = QString(), bool *useAppId = nullptr) const = 0; - \brief 返回描述文件的路径 - \a localPrefix 目录的所有需要查找的覆盖机制目录 - \return + @brief Returns the path to the profile + \a localPrefix Directory of all override mechanisms that need to be searched + @return */ /*! - \fn QStringList DConfigMeta::allOverrideDirs(const bool useAppId, const QString &prefix = QString()) const = 0; +@~english + @fn QStringList DConfigMeta::allOverrideDirs(const bool useAppId, const QString &prefix = QString()) const = 0; - \brief 获得前缀为 \a prefix 目录的所有需要查找的覆盖机制目录 - \a userAppId 是否不使用通用目录 - \return + @brief Gets all the override mechanism directories to look for for the \a prefix directory + \a useAppId Whether not to use the generic directory + @return */ /*! - \fn QVariant DConfigMeta::value(const QString &key) const = 0; +@~english + @fn QVariant DConfigMeta::value(const QString &key) const = 0; - \brief meta初始值经过覆盖机制覆盖后的原始值 - \a key 配置项名称 - \return + @brief Original value of meta overwritten by the overwriting mechanism + \a key Configuration name + @return */ class Q_DECL_HIDDEN DConfigMetaImpl : public DConfigMeta { @@ -590,32 +667,12 @@ public: return values.value(key); } - inline QStringList applicationMetaDirs(const QString &prefix) const - { - QStringList paths; - // lower priority is higher. - const auto &dataPaths = DStandardPaths::paths(DStandardPaths::DSG::DataDir); - paths.reserve(dataPaths.size()); - for (auto item : dataPaths) { - paths.prepend(QString("%1/%2/configs/%3").arg(prefix, item, configKey.appId)); - } - return paths; - } - - inline static QStringList genericMetaDirs(const QString &prefix) { - QStringList paths; - for (auto item: DStandardPaths::paths(DStandardPaths::DSG::DataDir)) { - paths.prepend(QString("%1/%2/configs").arg(prefix, item)); - } - return paths; - } - QString metaPath(const QString &localPrefix, bool *useAppId) const override { bool useAppIdForOverride = true; QString path; - const QStringList &applicationMetas = applicationMetaDirs(localPrefix); + const QStringList &applicationMetas = applicationMetaDirs(localPrefix, configKey.appId); for (auto iter = applicationMetas.rbegin(); iter != applicationMetas.rend(); iter++) { path = getFile(*iter, configKey.subpath, configKey.fileName + FILE_SUFFIX); if (!path.isEmpty()) @@ -639,6 +696,14 @@ public: bool load(const QString &localPrefix) override { + if (!isValidAppId(configKey.appId)) { + qCWarning(cfLog, "AppId is invalid, appId=%s", qPrintable(configKey.appId)); + return false; + } + if (!isValidFilename(configKey.fileName)) { + qCWarning(cfLog, "Name is invalid, filename=%s", qPrintable(configKey.fileName)); + return false; + } bool useAppIdForOverride = true; QString path = metaPath(localPrefix, &useAppIdForOverride); if (path.isEmpty()) { @@ -723,6 +788,10 @@ public: auto i = contents.constBegin(); for (; i != contents.constEnd(); ++i) { + if (!values.contains(i.key())) { + qCWarning(cfLog, "The meta doesn't contain the override key: \"%s\".", qPrintable(i.key())); + continue; + } // 检查是否允许 override if (values.flags(i.key()) & DConfigFile::NoOverride) continue; @@ -740,9 +809,10 @@ public: return true; } /*! + @~english \internal - \brief 获得前缀为\a prefix目录的应用或公共库的所有覆盖机制目录,越后优先级越高 + @brief 获得前缀为 \a prefix 目录的应用或公共库的所有覆盖机制目录,越后优先级越高 */ inline QStringList overrideDirs(const QString & prefix, bool useAppId) const { const QString &path2 = QString("%1/etc/dsg/configs/overrides/%2/%3") @@ -774,9 +844,10 @@ public: return dirs; } /*! + @~english \internal - \brief 获得所有遵守覆盖机制的文件流 + @brief 获得所有遵守覆盖机制的文件流 在override文件放置路径下按优先级查找覆盖文件,支持子目录查找机制, 使用自然排序(如“a2”在“a11”之前)规则按文件名进行排序 @@ -800,6 +871,9 @@ public: if (!base_dir.exists()) continue; + if (!subpathIsValid(configKey.subpath, base_dir)) + continue; + QDir target_dir = base_dir; target_dir.setFilter(filters); target_dir.setNameFilters(nameFilters); @@ -852,75 +926,93 @@ DConfigMetaImpl::~DConfigMetaImpl() } /*! - \class Dtk::Core::DConfigCache +@~english + @class Dtk::Core::DConfigCache \inmodule dtkcore - \brief 提供配置文件的用户和全局运行缓存访问接口. + @brief Provides user and global runtime cache access interfaces for Configuration file. */ /*! - \fn bool DConfigCache::load(const QString &localPrefix = QString()) = 0; - \brief 解析缓存配置文件 - \return +@~english + @fn bool DConfigCache::load(const QString &localPrefix = QString()) = 0; + @brief Parse the cache configuration file + @return */ /*! - \fn bool DConfigCache::save(const QString &localPrefix = QString(), QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool sync = false) = 0; - \brief 保存缓存的值到磁盘中 - \a localPrefix 为目录前缀 - \a format 保存格式 - \a sync 是否立即刷新 - \return +@~english + @fn bool DConfigCache::save(const QString &localPrefix = QString(), QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool sync = false) = 0; + @brief Save the cached value to disk + \a localPrefix Directory prefix + \a format Save format + \a sync Whether to refresh immediately + @return */ /*! - \fn bool DConfigCache::isGlobal() const = 0; - \brief 是否是全局缓存 - \return +@~english + @fn bool DConfigCache::isGlobal() const = 0; + @brief Whether to cache globally + @return */ /*! - \fn void DConfigCache::remove(const QString &key) = 0; - \brief 删除缓存中的配置项 - \a key 配置项名称 - \return +@~english + @fn void DConfigCache::remove(const QString &key) = 0; + @brief Delete a configuration entry from the cache + \a key Configuration name + @return */ /*! - \fn QStringList DConfigCache::keyList() const = 0; - \brief 返回配置内容的所有配置项 - \return +@~english + @fn QStringList DConfigCache::keyList() const = 0; + @brief Returns all configuration items for the configuration content + @return */ /*! - \fn bool DConfigCache::setValue(const QString &key, const QVariant &value, const int serial, const uint uid, const QString &callerAppid) = 0; - \brief 设置缓存中的值 - \a key 配置项名称 - \a value 需要设置的值 - \a uid 设置时的用户id - \a callerAppid 设置时的应用id - \return 为true时表示重新设置了新值,false表示没有设置 +@~english + @fn bool DConfigCache::setValue(const QString &key, const QVariant &value, const int serial, const uint uid, const QString &callerAppid) = 0; + @brief Sets the value in the cache + \a key Configuration name + \a value Configuration name + \a uid User Id at setup time + \a callerAppid Application id at setup time + @return A value of true indicates that the new value has been reset, and false indicates that it has not been set */ /*! - \fn QVariant DConfigCache::value(const QString &key) const = 0; - \brief 获取缓存中的值 - \a key 配置项名称 - \return +@~english + @fn QVariant DConfigCache::value(const QString &key) const = 0; + @brief Get the value in the cache + \a key Configuration name + @return */ /*! - \fn int DConfigCache::serial(const QString &key) const = 0; - \brief 返回配置项的单调递增值 - \a key 配置项名称 - \return -1为无效值,表明没有配置此项 +@~english + @fn int DConfigCache::serial(const QString &key) const = 0; + @brief Returns a monotonically increasing value of a configuration item + \a key Configuration name + @return An invalid value of -1 indicates that the entry is not configured */ /*! - \fn uint DConfigCache::uid() const = 0; - \brief 用户标识,为全局缓存时,uid为非用户标识的特定值 - \return +@~english + @fn uint DConfigCache::uid() const = 0; + @brief User identification, when used in the global cache, uid is a specific value for non-user identification + @return +*/ + +/*! +@~english + @fn void setCachePathPrefix(const QString &prefix) = 0; + @brief Set cache's prefix path, it's access permissions is considered by caller, +and it needs to distinguish the paths of different caches by caller. + @param prefix cache's prefix path. */ class Q_DECL_HIDDEN DConfigCacheImpl : public DConfigCache { @@ -945,20 +1037,30 @@ public: return values.keyList(); } - inline static QString applicationCacheDir(const QString &prefix, const QString &suffix, - uint userid, const QString &appId) { - // If target user is current user, then get the home path by environment variable first. - const QString &homePath = (getuid() == userid) ? DStandardPaths::homePath() - : DStandardPaths::homePath(userid); - if (homePath.isEmpty()) { - return QString(); + inline QString applicationCacheDir(const QString &localPrefix, const QString &suffix) const + { + QString prefix(cachePrefix); + if (prefix.isEmpty()) { + // If target user is current user or system user, then get the home path by environment variable first. + QString homePath; + if (userid == InvalidUID || (getuid() == userid)) { + homePath = DStandardPaths::homePath(); + } else { + homePath = DStandardPaths::homePath(getuid()); + } + + if (homePath.isEmpty()) + return QString(); + + // fallback to default application cache directory. + prefix = homePath + QStringLiteral("/.config/dsg/configs"); } - const QString userHomeConfigDir = homePath + QStringLiteral("/.config/dsg/configs") + suffix; - return prefix + userHomeConfigDir + QDir::separator() + appId; + return QDir::cleanPath(QString("%1/%2/%3").arg(localPrefix, prefix + suffix, configKey.appId)); } - inline QString applicationCacheDir(const QString &prefix) const { - return applicationCacheDir(prefix, QString(), userid, configKey.appId); + inline QString applicationCacheDir(const QString &localPrefix) const + { + return applicationCacheDir(localPrefix, QString()); } inline QString cacheDir(const QString &basePath) { @@ -966,23 +1068,28 @@ public: return dir.filePath(configKey.fileName + FILE_SUFFIX); } - inline QString globalCacheDir(const QString &prefix) const { - // TODO `DSG_APP_DATA` is not set and `appid` is not captured in `DStandardPaths::path`. - QString appDataDir = DStandardPaths::path(DStandardPaths::DSG::AppData); - if (appDataDir.isEmpty()) { + inline QString globalCacheDir(const QString &localPrefix) const { + QString prefix(cachePrefix); + if (prefix.isEmpty()) { + // TODO `DSG_APP_DATA` is not set and `appid` is not captured in `DStandardPaths::path`. + QString appDataDir = DStandardPaths::path(DStandardPaths::DSG::AppData); + if (appDataDir.isEmpty()) { #ifdef D_DSG_APP_DATA_FALLBACK - appDataDir = QStringLiteral(D_DSG_APP_DATA_FALLBACK); - QFileInfo tmp(appDataDir); - if (!tmp.exists() && !tmp.isSymLink() && !QDir::current().mkpath(appDataDir)) { - qCDebug(cfLog, "Not found a valid DSG_APP_DATA directory"); - return QString(); - } + appDataDir = QStringLiteral(D_DSG_APP_DATA_FALLBACK); + QFileInfo tmp(appDataDir); + if (!tmp.exists() && !tmp.isSymLink() && !QDir::current().mkpath(appDataDir)) { + qCDebug(cfLog, "Not found a valid DSG_APP_DATA directory"); + return QString(); + } #else - return QString(); + return QString(); #endif + } + // fallback to default global cache directory. + prefix = QString("%1/configs").arg(appDataDir); } - return QString("%1/%2/configs/%3").arg(prefix, appDataDir, configKey.appId); + return QDir::cleanPath(QString("%1/%2/%3").arg(localPrefix, prefix, configKey.appId)); } QString getCacheDir(const QString &localPrefix = QString()) @@ -993,7 +1100,7 @@ public: return dir; // Not supported the global config, fallback the config cache data to user directory. - return applicationCacheDir(localPrefix, "-fake-global", getuid(), configKey.appId); + return applicationCacheDir(localPrefix, "-fake-global"); } else { return applicationCacheDir(localPrefix); } @@ -1009,6 +1116,7 @@ public: inline void remove(const QString &key) override { values.remove(key); + cacheChanged = true; } bool setValue(const QString &key, const QVariant &value, const int serial, const uint uid, const QString &appid) override { @@ -1031,8 +1139,14 @@ public: bool save(const QString &localPrefix, QJsonDocument::JsonFormat format, bool sync) override; + virtual void setCachePathPrefix(const QString &prefix) override + { + cachePrefix = prefix; + } + DConfigKey configKey; DConfigInfo values; + QString cachePrefix; uint userid; bool global; bool cacheChanged = false; @@ -1090,6 +1204,7 @@ bool DConfigCacheImpl::save(const QString &localPrefix, QJsonDocument::JsonForma if (!cacheChanged) return true; + cacheChanged = false; const QString &dir = getCacheDir(localPrefix); if (dir.isEmpty()) { qCWarning(cfLog, "Falied on saveing, the config cache directory is empty for the user[%d], " @@ -1168,16 +1283,28 @@ public: } else { const auto &metaValue = configMeta->value(key); // sample judgement to reduce a copy of convert. - if (metaValue.type() == value.type()) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (metaValue.typeId() == value.typeId()) return cache->setValue(key, value, configMeta->serial(key), cache->uid(), appid); // convert copy to meta's type, it promises `setValue` don't change meta's type. + auto copy = value; + if (!copy.convert(metaValue.metaType())) { + qCWarning(cfLog) << "check type error, meta type is " << metaValue.metaType().name() + << ", and now type is " << value.metaType().name(); + return false; + } +#else + if (metaValue.type() == value.type()) + return cache->setValue(key, value, configMeta->serial(key), cache->uid(), appid); + auto copy = value; if (!copy.convert(metaValue.userType())) { qCWarning(cfLog) << "check type error, meta type is " << metaValue.type() << ", and now type is " << value.type(); return false; } +#endif return cache->setValue(key, copy, configMeta->serial(key), cache->uid(), appid); } @@ -1191,7 +1318,7 @@ public: } return userCache; } - QVariant value(const QString &key, DConfigCache *userCache) const + QVariant cacheValue(DConfigCache *userCache, const QString &key) const { // 检查权限 if (configMeta->permissions(key) != DConfigFile::ReadOnly) { @@ -1203,7 +1330,13 @@ public: } } } - + return QVariant(); + } + QVariant value(const QString &key, DConfigCache *userCache) const + { + const QVariant &v = cacheValue(userCache, key); + if (v.isValid()) + return v; return configMeta->value(key); } @@ -1228,8 +1361,9 @@ DConfigFilePrivate::~DConfigFilePrivate() } /*! - \brief 支持的版本 - \return +@~english + @brief Supported versions + @return */ constexpr DConfigFile::Version DConfigFile::supportedVersion() { @@ -1237,16 +1371,15 @@ constexpr DConfigFile::Version DConfigFile::supportedVersion() } /*! - \brief 构造配置文件管理对象 - \a appId 应用程序唯一标识 - \a name 配置文件名 - \a subpath 子目录 +@~english + @brief 构造配置文件管理对象 + \a appId Application unique identification + \a name Config filename + \a subpath Subdirectories */ DConfigFile::DConfigFile(const QString &appId, const QString &name, const QString &subpath) : DObject(*new DConfigFilePrivate(this, appId, name, subpath)) { - Q_ASSERT(!name.isEmpty()); - D_D(DConfigFile); d->globalCache = new DConfigCacheImpl(d->configKey, InvalidUID, true); } @@ -1261,9 +1394,10 @@ DConfigFile::DConfigFile(const DConfigFile &other) } /*! - \brief 解析配置文件 - \a localPrefix 为目录前缀 - \return +@~english + @brief Parse configuration files + \a localPrefix Directory prefix + @return */ bool DConfigFile::load(const QString &localPrefix) { @@ -1272,10 +1406,11 @@ bool DConfigFile::load(const QString &localPrefix) } /*! - \brief 解析配置文件流 - \a meta 为原型流 - \a overrides 为覆盖机制查找的文件流 - \return +@~english + @brief Parse the profile stream + \a meta Prototype stream + \a overrides File stream to find for the override mechanism + @return */ bool DConfigFile::load(QIODevice *meta, const QList &overrides) { @@ -1283,10 +1418,11 @@ bool DConfigFile::load(QIODevice *meta, const QList &overrides) } /*! - \brief 保存缓存的值到磁盘中 - \a format 保存格式 - \a sync 是否立即刷新 - \return +@~english + @brief Save the cached value to disk + \a format Save format + \a sync Whether to refresh immediately + @return */ bool DConfigFile::save(const QString &localPrefix, QJsonDocument::JsonFormat format, bool sync) const { @@ -1298,10 +1434,11 @@ bool DConfigFile::save(const QString &localPrefix, QJsonDocument::JsonFormat for } /*! - * \brief DConfigFile::value - * \param key 配置项名称 - * \param uid 用户id,当key为全局项时,uid无效 - * \return +@~english + * @brief DConfigFile::value + * @param key Configuration name + * @param userCache Specific user cache, \a userCache is unused when the key is global + * @return */ QVariant DConfigFile::value(const QString &key, DConfigCache *userCache) const { @@ -1310,12 +1447,25 @@ QVariant DConfigFile::value(const QString &key, DConfigCache *userCache) const } /*! - \brief 设置缓存中的值 - \a key 配置项名称 - \a value 需要设置的值 - \a uid 设置时的用户id - \a appid 设置时的应用id - \return 为true时表示重新设置了新值,false表示没有设置 + * \brief DConfigFile::cacheValue Get a specific user cache's value + * \param userCache Specific user cache, it is unused if the \a key is global configuration item + * \param key Configuration name + * \return + */ +QVariant DConfigFile::cacheValue(DConfigCache *userCache, const QString &key) const +{ + D_DC(DConfigFile); + return d->cacheValue(userCache, key); +} + +/*! +@~english + @brief Sets the value in the cache + \a key Configuration name + \a value The value to set + \a userCache Specific user cache at setup time + \a appid Application id at setup time + @return A value of true indicates that the new value has been reset, and false indicates that it has not been set */ bool DConfigFile::setValue(const QString &key, const QVariant &value, const QString &callerAppid, DConfigCache *userCache) { @@ -1331,8 +1481,9 @@ DConfigCache *DConfigFile::createUserCache(const uint uid) /*! - \brief 返回全局缓存 - \return +@~english + @brief Return to the global cache + @return */ DConfigCache *DConfigFile::globalCache() const { @@ -1341,8 +1492,9 @@ DConfigCache *DConfigFile::globalCache() const } /*! - \brief 返回原型对象 - \return +@~english + @brief Return the prototype object + @return */ DConfigMeta *DConfigFile::meta() { @@ -1351,8 +1503,9 @@ DConfigMeta *DConfigFile::meta() } /*! - \brief 检测配置文件是否有效 - \return +@~english + @brief Checks whether the configuration file is valid + @return */ bool DConfigFile::isValid() const { diff --git a/src/ddesktopentry.cpp b/src/ddesktopentry.cpp index 87941e6..f844f0a 100644 --- a/src/ddesktopentry.cpp +++ b/src/ddesktopentry.cpp @@ -154,11 +154,11 @@ public: // construct data and return QByteArray data; - data.append(QString("[%1]\n").arg(name)); + data.append(QString("[%1]\n").arg(name).toLocal8Bit()); QMap::const_iterator i; for (i = valuesMap.begin(); i != valuesMap.end(); i++) { - data.append(QString("%1=%2\n").arg(i.key(), i.value())); + data.append(QString("%1=%2\n").arg(i.key(), i.value()).toLocal8Bit()); } return data; @@ -479,9 +479,10 @@ bool DDesktopEntryPrivate::remove(const QString §ionName, const QString &key } /*! - \class Dtk::Core::DDesktopEntry +@~english + @class Dtk::Core::DDesktopEntry \inmodule dtkcore - \brief Handling desktop entry files. + @brief Handling desktop entry files. DDesktopEntry provide method for handling XDG desktop entry read and write. The interface of this class is similar to QSettings. @@ -502,8 +503,9 @@ DDesktopEntry::~DDesktopEntry() } /*! - \brief Write back data to the desktop entry file. - \return true if write success; otherwise returns false. +@~english + @brief Write back data to the desktop entry file. + @return true if write success; otherwise returns false. */ bool DDesktopEntry::save() const { @@ -552,9 +554,10 @@ bool DDesktopEntry::save() const } /*! - \brief Get data parse status +@~english + @brief Get data parse status - \return Returns a status code indicating the first error that was met by DDesktopEntry, or QSettings::NoError if no error occurred. + @return Returns a status code indicating the first error that was met by DDesktopEntry, or QSettings::NoError if no error occurred. Be aware that DDesktopEntry delays performing some operations. */ @@ -565,9 +568,10 @@ DDesktopEntry::Status DDesktopEntry::status() const } /*! - \brief Get a list of all section keys inside the given \a section. +@~english + @brief Get a list of all section keys inside the given \a section. - \return all available section keys. + @return all available section keys. */ QStringList DDesktopEntry::keys(const QString §ion) const { @@ -582,11 +586,12 @@ QStringList DDesktopEntry::keys(const QString §ion) const } /*! - \brief Get a list of all section groups inside the desktop entry. +@~english + @brief Get a list of all section groups inside the desktop entry. If \a sorted is set to true, the returned result will keep the order as-is when reading the entry file. - \return all available section groups. + @return all available section groups. */ QStringList DDesktopEntry::allGroups(bool sorted) const { @@ -619,9 +624,10 @@ QStringList DDesktopEntry::allGroups(bool sorted) const } /*! - \brief Check if the desktop entry file have the given \a section contains the given \a key +@~english + @brief Check if the desktop entry file have the given \a section contains the given \a key - \return true if the desktop entry contains the \a key in \a section; otherwise returns false. + @return true if the desktop entry contains the \a key in \a section; otherwise returns false. */ bool DDesktopEntry::contains(const QString &key, const QString §ion) const { @@ -636,13 +642,14 @@ bool DDesktopEntry::contains(const QString &key, const QString §ion) const } /*! - \brief Returns the localized string value of the "Name" key under "Desktop Entry" section. +@~english + @brief Returns the localized string value of the "Name" key under "Desktop Entry" section. It's equivalent to calling localizedValue("Name"). - \return Returns the localized string value of the "Name" key under "Desktop Entry" section. + @return Returns the localized string value of the "Name" key under "Desktop Entry" section. - \sa localizedValue(), genericName(), ddeDisplayName() + @sa localizedValue(), genericName(), ddeDisplayName() */ QString DDesktopEntry::name() const { @@ -650,14 +657,15 @@ QString DDesktopEntry::name() const } /*! - \brief Returns the localized string value of the "GenericName" key under "Desktop Entry" section. +@~english + @brief Returns the localized string value of the "GenericName" key under "Desktop Entry" section. It's equivalent to calling localizedValue("GenericName"). It will NOT fallback to "Name" if "GenericName" is not existed. - \return Returns the localized string value of the "GenericName" key under "Desktop Entry" section. + @return Returns the localized string value of the "GenericName" key under "Desktop Entry" section. - \sa localizedValue(), name(), ddeDisplayName() + @sa localizedValue(), name(), ddeDisplayName() */ QString DDesktopEntry::genericName() const { @@ -665,14 +673,15 @@ QString DDesktopEntry::genericName() const } /*! - \brief Display name specially for DDE applications. +@~english + @brief Display name specially for DDE applications. This will check "X-Deepin-Vendor" and will return the localized string value of "GenericName" if "X-Deepin-Vendor" is "deepin", or it will return the localized string value of "Name". - \return Returns the display name specially for DDE applications. + @return Returns the display name specially for DDE applications. - \sa localizedValue(), name(), genericName() + @sa localizedValue(), name(), genericName() */ QString DDesktopEntry::ddeDisplayName() const { @@ -686,13 +695,14 @@ QString DDesktopEntry::ddeDisplayName() const } /*! - \brief Returns the localized string value of the "Comment" key under "Desktop Entry" section. +@~english + @brief Returns the localized string value of the "Comment" key under "Desktop Entry" section. It's equivalent to calling localizedValue("Comment"). - \return Returns the localized string value of the "Comment" key under "Desktop Entry" section. + @return Returns the localized string value of the "Comment" key under "Desktop Entry" section. - \sa localizedValue() + @sa localizedValue() */ QString DDesktopEntry::comment() const { @@ -700,13 +710,14 @@ QString DDesktopEntry::comment() const } /*! - \brief Returns the raw string value associated with the given \a key in \a section. +@~english + @brief Returns the raw string value associated with the given \a key in \a section. If the entry contains no item with the key, the function returns a constructed \a defaultValue. - \return Returns the raw string value associated with the given \a key in \a section. + @return Returns the raw string value associated with the given \a key in \a section. - \sa stringValue() localizedValue() stringListValue() + @sa stringValue() localizedValue() stringListValue() */ QString DDesktopEntry::rawValue(const QString &key, const QString §ion, const QString &defaultValue) const { @@ -721,13 +732,14 @@ QString DDesktopEntry::rawValue(const QString &key, const QString §ion, cons } /*! - \brief Returns the unescaped string value associated with the given \a key in \a section. +@~english + @brief Returns the unescaped string value associated with the given \a key in \a section. If the entry contains no item with the key, the function returns a constructed \a defaultValue. - \return Returns the unescaped string value associated with the given \a key in \a section. + @return Returns the unescaped string value associated with the given \a key in \a section. - \sa rawValue() localizedValue() stringListValue() + @sa rawValue() localizedValue() stringListValue() */ QString DDesktopEntry::stringValue(const QString &key, const QString §ion, const QString &defaultValue) const { @@ -737,16 +749,17 @@ QString DDesktopEntry::stringValue(const QString &key, const QString §ion, c } /*! - \brief Returns the localized string value associated with the given \a key and \a localeKey in \a section. +@~english + @brief Returns the localized string value associated with the given \a key and \a localeKey in \a section. If the given \a localeKey can't be found, it will fallback to "C", if still cannot found, will fallback to the key without localeKey. If the entry contains no item with the key, the function returns a constructed \a defaultValue. - \return Returns the localized string value associated with the given \a key and \a localeKey in \a section. + @return Returns the localized string value associated with the given \a key and \a localeKey in \a section. - \sa rawValue() stringValue() stringListValue() + @sa rawValue() stringValue() stringListValue() */ QString DDesktopEntry::localizedValue(const QString &key, const QString &localeKey, const QString §ion, const QString &defaultValue) const { @@ -793,16 +806,17 @@ QString DDesktopEntry::localizedValue(const QString &key, const QString &localeK } /*! - \brief Returns the localized string value associated with the given \a key and \a locale in \a section. +@~english + @brief Returns the localized string value associated with the given \a key and \a locale in \a section. If the given \a locale can't be found, it will fallback to "C", if still cannot found, will fallback to the key without a locale key. If the entry contains no item with the key, the function returns a default-constructed value. - \return Returns the localized string value associated with the given \a key and \a locale in \a section. + @return Returns the localized string value associated with the given \a key and \a locale in \a section. - \sa rawValue() stringValue() stringListValue() + @sa rawValue() stringValue() stringListValue() */ QString DDesktopEntry::localizedValue(const QString &key, const QLocale &locale, const QString §ion, const QString &defaultValue) const { @@ -810,13 +824,14 @@ QString DDesktopEntry::localizedValue(const QString &key, const QLocale &locale, } /*! - \brief Returns a list of strings associated with the given \a key in the given \a section. +@~english + @brief Returns a list of strings associated with the given \a key in the given \a section. If the entry contains no item with the key, the function returns a empty string list. - \return Returns a list of strings associated with the given \a key in the given \a section. + @return Returns a list of strings associated with the given \a key in the given \a section. - \sa rawValue() stringValue() localizedValue() + @sa rawValue() stringValue() localizedValue() */ QStringList DDesktopEntry::stringListValue(const QString &key, const QString §ion) const { @@ -1014,9 +1029,9 @@ QString &DDesktopEntry::unescapeExec(QString &str) // The parseCombinedArgString() splits the string by the space symbols, // we temporarily replace them on the special characters. // Replacement will reverse after the splitting. - repl.insert(QLatin1Char(' '), 01); // space - repl.insert(QLatin1Char('\t'), 02); // tab - repl.insert(QLatin1Char('\n'), 03); // newline, + repl.insert(QLatin1Char(' '), QChar::fromLatin1(01)); // space + repl.insert(QLatin1Char('\t'), QChar::fromLatin1(02)); // tab + repl.insert(QLatin1Char('\n'), QChar::fromLatin1(03)); // newline, repl.insert(QLatin1Char('"'), QLatin1Char('"')); // double quote, repl.insert(QLatin1Char('\''), QLatin1Char('\'')); // single quote ("'"), diff --git a/src/dlicenseinfo.cpp b/src/dlicenseinfo.cpp new file mode 100644 index 0000000..dbc56a6 --- /dev/null +++ b/src/dlicenseinfo.cpp @@ -0,0 +1,205 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dlicenseinfo.h" + +#include + +#include +#include +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DLicenseInfo::DComponentInfoPrivate : public DObjectPrivate +{ +public: + QString name; + QString version; + QString copyRight; + QString licenseName; + +protected: + explicit DComponentInfoPrivate(DLicenseInfo::DComponentInfo *qq) + : DObjectPrivate(qq) + { + } + +private: + Q_DECLARE_PUBLIC(DLicenseInfo::DComponentInfo) + friend class DLicenseInfoPrivate; +}; + +DLicenseInfo::DComponentInfo::DComponentInfo(DObject * parent) + : DObject(*new DLicenseInfo::DComponentInfoPrivate(this), parent) +{ + +} + +DLicenseInfo::DComponentInfo::~DComponentInfo() +{ +} + +QString DLicenseInfo::DComponentInfo::name() const +{ + return d_func()->name; +} + +QString DLicenseInfo::DComponentInfo::version() const +{ + return d_func()->version; +} + +QString DLicenseInfo::DComponentInfo::copyRight() const +{ + return d_func()->copyRight; +} + +QString DLicenseInfo::DComponentInfo::licenseName() const +{ + return d_func()->licenseName; +} + +class Q_DECL_HIDDEN DLicenseInfoPrivate : public DObjectPrivate +{ +public: + explicit DLicenseInfoPrivate(DLicenseInfo *qq); + ~DLicenseInfoPrivate() override; + + bool loadFile(const QString &file); + bool loadContent(const QByteArray &content); + QByteArray licenseContent(const QString &licenseName); + void clear(); + + QString licenseSearchPath; + DLicenseInfo::DComponentInfos componentInfos; +}; + +DLicenseInfoPrivate::DLicenseInfoPrivate(DLicenseInfo *qq) + : DObjectPrivate(qq) +{ +} + +DLicenseInfoPrivate::~DLicenseInfoPrivate() +{ + clear(); +} + +bool DLicenseInfoPrivate::loadFile(const QString &file) +{ + QFile jsonFile(file); + if (!jsonFile.open(QIODevice::ReadOnly)) { + qWarning() << QString("Failed on open file: \"%1\", error message: \"%2\"").arg( + qPrintable(jsonFile.fileName()), qPrintable(jsonFile.errorString())); + return false; + } + return loadContent(jsonFile.readAll()); +} + +bool DLicenseInfoPrivate::loadContent(const QByteArray &content) +{ + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(content, &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << "When loading the license, parseJson failed:" << qPrintable(error.errorString()); + return false; + } + if (!jsonDoc.isArray()) { + qWarning() << "When loading the license, parseJson failed: it is not a JSON array"; + return false; + } + + clear(); + QJsonArray array = jsonDoc.array(); + for (const QJsonValue &value : array) { + if (!value.isObject()) { + qWarning() << "When loading the license, parseJson failed: it is not a JSON object!"; + return false; + } + DLicenseInfo::DComponentInfo *componentInfo = new DLicenseInfo::DComponentInfo; + QJsonObject obj = value.toObject(); + QJsonValue name = obj.value("name"); + QJsonValue version = obj.value("version"); + QJsonValue copyright = obj.value("copyright"); + QJsonValue license = obj.value("license"); + if (!name.isString() || !version.isString() + || !copyright.isString() || !license.isString()) { + qWarning() << "When loading the license, parseJson failed: it is not a string!"; + return false; + } + componentInfo->d_func()->name = name.toString(); + componentInfo->d_func()->version = version.toString(); + componentInfo->d_func()->copyRight = copyright.toString(); + componentInfo->d_func()->licenseName = license.toString(); + componentInfos.append(componentInfo); + } + return true; +} + +QByteArray DLicenseInfoPrivate::licenseContent(const QString &licenseName) +{ + QByteArray content; + QStringList dirs{"/usr/share/spdx-license"}; + if (!licenseSearchPath.isEmpty()) + dirs.prepend(licenseSearchPath); + for (const QString &dir : dirs) { + QFile file(QString("%1/%2.txt").arg(dir).arg(licenseName)); + if (!file.exists()) + continue; + if (file.open(QIODevice::ReadOnly)) { + content = file.readAll(); + file.close(); + break; + } + } + if (content.isEmpty()) { + qWarning() << QString("License content is empty when getting license content!"); + } + return content; +} + +void DLicenseInfoPrivate::clear() +{ + qDeleteAll(componentInfos); + componentInfos.clear(); +} + +DLicenseInfo::DLicenseInfo(DObject *parent) + : DObject(*new DLicenseInfoPrivate(this), parent) +{ +} + +bool DLicenseInfo::loadContent(const QByteArray &content) +{ + D_D(DLicenseInfo); + return d->loadContent(content); +} + +bool DLicenseInfo::loadFile(const QString &file) +{ + D_D(DLicenseInfo); + return d->loadFile(file); +} + +void DLicenseInfo::setLicenseSearchPath(const QString &path) +{ + D_D(DLicenseInfo); + d->licenseSearchPath = path; +} + +QByteArray DLicenseInfo::licenseContent(const QString &licenseName) +{ + D_D(DLicenseInfo); + return d->licenseContent(licenseName); +} + +DLicenseInfo::DComponentInfos DLicenseInfo::componentInfos() const +{ + D_DC(DLicenseInfo); + return d->componentInfos; +} + +DCORE_END_NAMESPACE diff --git a/src/dsecurestring.cpp b/src/dsecurestring.cpp index 6469be9..0332033 100644 --- a/src/dsecurestring.cpp +++ b/src/dsecurestring.cpp @@ -4,6 +4,7 @@ #include "dsecurestring.h" #include "dutil.h" +#include DCORE_BEGIN_NAMESPACE diff --git a/src/dsgapplication.cpp b/src/dsgapplication.cpp index c00d355..2c8a20c 100644 --- a/src/dsgapplication.cpp +++ b/src/dsgapplication.cpp @@ -1,11 +1,30 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dsgapplication.h" +#include +#include + +#include +#include #include #include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef QT_DEBUG +Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg") +#else +Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg", QtInfoMsg) +#endif DCORE_BEGIN_NAMESPACE @@ -14,27 +33,91 @@ static inline QByteArray getSelfAppId() { QByteArray selfId = qgetenv("DSG_APP_ID"); if (!selfId.isEmpty()) return selfId; - selfId = DSGApplication::getId(QCoreApplication::applicationPid()); - if (selfId.isEmpty() && !qEnvironmentVariableIsSet("DTK_DISABLED_FALLBACK_APPID")) { - selfId = QCoreApplication::applicationName().toLocal8Bit(); - } - Q_ASSERT(!selfId.isEmpty()); - if (selfId.isEmpty()) { - qt_assert("The application ID is empty", __FILE__, __LINE__); - } - return selfId; + return DSGApplication::getId(QCoreApplication::applicationPid()); +} + +static bool isServiceActivatable(const QString &service) +{ + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(service)) + return false; + + const QDBusReply activatableNames = QDBusConnection::sessionBus().interface()-> + callWithArgumentList(QDBus::AutoDetect, + QLatin1String("ListActivatableNames"), + QList()); + + return activatableNames.value().contains(service); +} + +// Format appId to valid. +static QByteArray formatAppId(const QByteArray &appId) +{ + static const QRegularExpression regex("[^\\w\\-\\.]"); + QString format(appId); + format.replace(QDir::separator(), "."); + format = format.replace(regex, QStringLiteral("-")); + const QString InvalidPrefix{"."}; + if (format.startsWith(InvalidPrefix)) + format = format.mid(InvalidPrefix.size()); + return format.toLocal8Bit(); } QByteArray DSGApplication::id() { static QByteArray selfId = getSelfAppId(); - return selfId; + if (!selfId.isEmpty()) + return selfId; + QByteArray result = selfId; + if (!qEnvironmentVariableIsSet("DTK_DISABLED_FALLBACK_APPID")) { + result = QCoreApplication::applicationName().toLocal8Bit(); + if (result.isEmpty()) { + QFile file("/proc/self/cmdline"); + if (file.open(QIODevice::ReadOnly)) + result = file.readLine(); + } + if (result.isEmpty()) { + const QFileInfo file(QFile::symLinkTarget("/proc/self/exe")); + if (file.exists()) + result = file.absoluteFilePath().toLocal8Bit(); + } + if (!result.isEmpty()) { + result = formatAppId(result); + qCDebug(dsgApp) << "The applicatiion ID is fallback to " << result; + } + } + if (result.isEmpty()) + qCWarning(dsgApp) << "The application ID is empty."; + + return result; } -QByteArray DSGApplication::getId(qint64) +QByteArray DSGApplication::getId(qint64 pid) { - // TODO(zccrs): Call the org.desktopspec.ApplicationManager DBus service - return nullptr; + if (!isServiceActivatable("org.desktopspec.ApplicationManager1")) { + qCInfo(dsgApp) << "Can't getId from AM for the " << pid << ", because AM is unavailable."; + return QByteArray(); + } + + int pidfd = syscall(SYS_pidfd_open, pid, 0); + if (pidfd < 0) { + qCWarning(dsgApp) << "pidfd open failed:" << strerror(errno); + return QByteArray(); + } + + DDBusInterface infc("org.desktopspec.ApplicationManager1", + "/org/desktopspec/ApplicationManager1", + "org.desktopspec.ApplicationManager1"); + + QDBusReply reply = infc.call("Identify", QVariant::fromValue(QDBusUnixFileDescriptor(pidfd))); + + if (!reply.isValid()) { + qCWarning(dsgApp) << "Identify from AM failed." << reply.error().message(); + return QByteArray(); + } + + const QByteArray appId = reply.value().toLatin1(); + qCInfo(dsgApp) << "AppId is fetched from AM, and value is " << appId; + return appId; } DCORE_END_NAMESPACE diff --git a/src/dsysinfo.cpp b/src/dsysinfo.cpp index fd3fe6d..052ffa5 100644 --- a/src/dsysinfo.cpp +++ b/src/dsysinfo.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #ifdef Q_OS_LINUX @@ -24,14 +26,24 @@ #include #endif -#ifndef OS_VERSION_TEST_FILE -#define OS_VERSION_FILE "/etc/os-version" -#else -#define OS_VERSION_FILE OS_VERSION_TEST_FILE -#endif +#define OS_VERSION_FILE DSYSINFO_PREFIX"/etc/os-version" +#define LSB_RELEASE_FILE DSYSINFO_PREFIX"/etc/lsb-release" +#define OS_RELEASE_FILE DSYSINFO_PREFIX"/etc/os-release" +#define DEEPIN_VERSION_FILE DSYSINFO_PREFIX"/etc/deepin-version" + +static inline bool inTest() +{ + return !QLatin1String(DSYSINFO_PREFIX).isEmpty(); +} DCORE_BEGIN_NAMESPACE +#ifdef QT_DEBUG +Q_LOGGING_CATEGORY(logSysInfo, "dtk.dsysinfo") +#else +Q_LOGGING_CATEGORY(logSysInfo, "dtk.dsysinfo", QtInfoMsg) +#endif + class Q_DECL_HIDDEN DSysInfoPrivate { public: @@ -46,7 +58,7 @@ public: void ensureReleaseInfo(); void ensureComputerInfo(); QMap parseInfoFile(QFile &file); - + QMap parseInfoContent(const QString &content); #ifdef Q_OS_LINUX DSysInfo::DeepinType deepinType = DSysInfo::DeepinType(-1); QMap deepinTypeMap; //Type Name with Language @@ -127,7 +139,7 @@ bool DSysInfoPrivate::splitA_BC_DMode() minVersion.D = minv % 10; } else if (minorVersion.length() > 0) { const QString D = minorVersion.right(1); - if (D.contains(QRegExp("[0-9A-Z]"))) { + if (D.contains(QRegularExpression("[0-9A-Z]"))) { // 0-9...A-Z minVersion.D = 10 + static_cast(D.data()->toLatin1() - 'A'); } else { @@ -145,10 +157,13 @@ bool DSysInfoPrivate::splitA_BC_DMode() void DSysInfoPrivate::ensureDeepinInfo() { - if (static_cast(deepinType) >= 0) + if (static_cast(deepinType) > 0 && !inTest()) return; - QFile file("/etc/deepin-version"); + if (inTest()) + deepinTypeMap.clear(); // clear cache for test + + QFile file(DEEPIN_VERSION_FILE); if (!file.open(QFile::ReadOnly)) { deepinType = DSysInfo::UnknownDeepin; @@ -192,9 +207,10 @@ void DSysInfoPrivate::ensureDeepinInfo() deepinCopyright = QString::fromUtf8(key_value.second); } - if (!deepinTypeMap.isEmpty() && !deepinEdition.isEmpty() && !deepinCopyright.isEmpty()) { - break; - } + // deepinTypeMap may not parse finished(multi language) but !deepinTypeMap.isEmpty() +// if (!deepinTypeMap.isEmpty() && !deepinEdition.isEmpty() && !deepinCopyright.isEmpty()) { +// break; +// } } file.close(); @@ -211,6 +227,8 @@ void DSysInfoPrivate::ensureDeepinInfo() deepinType = DSysInfo::DeepinServer; } else if (deepin_type == "Personal") { deepinType = DSysInfo::DeepinPersonal; + } else if (deepin_type == "Military") { + deepinType = DSysInfo::DeepinMilitary; } else { deepinType = DSysInfo::UnknownDeepin; } @@ -218,10 +236,8 @@ void DSysInfoPrivate::ensureDeepinInfo() bool DSysInfoPrivate::ensureOsVersion() { -#ifndef OS_VERSION_TEST_FILE // Always re-read the file when testing - if (osBuild.A > 0) + if (osBuild.A > 0 && !inTest()) return true; -#endif DDesktopEntry entry(OS_VERSION_FILE); bool ok = false; @@ -242,7 +258,11 @@ bool DSysInfoPrivate::ensureOsVersion() ok = (osbs.size() >= 2 && osbs.value(0).size() == 5); D_ASSET_EXIT(ok, "OsBuild version invalid!"); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + const QStringList &left = osbs.value(0).split(QString(), Qt::SkipEmptyParts); +#else const QStringList &left = osbs.value(0).split(QString(), QString::SkipEmptyParts); +#endif D_ASSET_EXIT(left.size() == 5, "OsBuild version(ls) invalid!"); int idx = 0; @@ -354,6 +374,13 @@ static bool readEtcFile(DSysInfoPrivate *info, const char *filename, quint8 valid_data_count = 0; char buf[1024]; + + if (inTest()) { + // for test clear cache + info->productTypeString.clear(); + info->productType = DSysInfo::UnknownType; + } + while (valid_data_count < 3) { int buf_length = file.readLine(buf, sizeof(buf)); @@ -391,21 +418,21 @@ static bool readEtcFile(DSysInfoPrivate *info, const char *filename, static bool readOsRelease(DSysInfoPrivate *info) { - if (!readEtcFile(info, "/etc/os-release", "ID=", "VERSION_ID=", "PRETTY_NAME=")) - return readEtcFile(info, "/usr/lib/os-release", "ID=", "VERSION_ID=", "PRETTY_NAME="); + if (!readEtcFile(info, OS_RELEASE_FILE, "ID=", "VERSION_ID=", "PRETTY_NAME=")) + return readEtcFile(info, DSYSINFO_PREFIX"/usr/lib/os-release", "ID=", "VERSION_ID=", "PRETTY_NAME="); return true; } static bool readLsbRelease(DSysInfoPrivate *info) { - return readEtcFile(info, "/etc/lsb-release", "DISTRIB_ID=", "DISTRIB_RELEASE=", "DISTRIB_DESCRIPTION="); + return readEtcFile(info, LSB_RELEASE_FILE, "DISTRIB_ID=", "DISTRIB_RELEASE=", "DISTRIB_DESCRIPTION="); } #endif void DSysInfoPrivate::ensureReleaseInfo() { - if (productType >= 0) { + if (productType > 0 && !inTest()) { return; } @@ -511,6 +538,21 @@ QMap DSysInfoPrivate::parseInfoFile(QFile &file) return map; } +QMap DSysInfoPrivate::parseInfoContent(const QString &content) +{ + QMap map; + QStringList lineContents = content.split("\n"); + for (auto lineContent : lineContents) { + if (lineContent.contains(':')) { + QStringList list = lineContent.split(':'); + if (list.size() == 2) { + map.insert(list.first().trimmed(), list.back().trimmed()); + } + } + } + return map; +} + Q_GLOBAL_STATIC(DSysInfoPrivate, siGlobal) QString DSysInfo::operatingSystemName() @@ -534,6 +576,12 @@ bool DSysInfo::isDeepin() bool DSysInfo::isDDE() { + if (!DSysInfo::isDeepin()) { + const QByteArray &xsd = qgetenv("XDG_SESSION_DESKTOP"); + return !xsd.compare("deepin", Qt::CaseInsensitive) || + !xsd.compare("DDE", Qt::CaseInsensitive); + } + siGlobal->ensureDeepinInfo(); return siGlobal->deepinType != UnknownDeepin; @@ -582,6 +630,9 @@ QString DSysInfo::deepinCopyright() */ DSysInfo::UosType DSysInfo::uosType() { + if (!DSysInfo::isDeepin() && !inTest()) + return UosTypeUnknown; + siGlobal->ensureOsVersion(); UosType ost = UosTypeUnknown; @@ -643,6 +694,7 @@ DSysInfo::UosEdition DSysInfo::uosEditionType() return ospt; } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! @~english \brief Architecture information (using bit flags of a byte) @@ -654,6 +706,7 @@ DSysInfo::UosArch DSysInfo::uosArch() return static_cast(siGlobal->osBuild.E); } +#endif static QString getUosVersionValue(const QString &key, const QLocale &locale) { @@ -815,15 +868,18 @@ QString DSysInfo::buildVersion() } #endif +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QString DSysInfo::deepinDistributionInfoPath() { return distributionInfoPath(); } +#endif QString DSysInfo::distributionInfoPath() { #ifdef Q_OS_LINUX - return "/usr/share/deepin/distribution.info"; + // return "/usr/share/deepin/distribution.info"; + return QStandardPaths::locate(QStandardPaths::GenericDataLocation, "deepin/distribution.info"); #else return QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).filePath("deepin-distribution.info"); #endif // Q_OS_LINUX @@ -862,11 +918,12 @@ QString DSysInfo::distributionOrgName(DSysInfo::OrgType type, const QLocale &loc return siGlobal->distributionInfo->localizedValue("Name", locale, distributionInfoSectionName(type), fallback); } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QString DSysInfo::deepinDistributorName() { return distributionOrgName(Distributor); } - +#endif /*! @~english \return the organization website name and url. @@ -890,10 +947,12 @@ QPair DSysInfo::distributionOrgWebsite(DSysInfo::OrgType type) }; } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QPair DSysInfo::deepinDistributorWebsite() { return distributionOrgWebsite(Distributor); } +#endif /*! @~english @@ -922,10 +981,12 @@ QString DSysInfo::distributionOrgLogo(DSysInfo::OrgType orgType, DSysInfo::LogoT return QString(); } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QString DSysInfo::deepinDistributorLogo(DSysInfo::LogoType type, const QString &fallback) { return distributionOrgLogo(Distributor, type, fallback); } +#endif DSysInfo::ProductType DSysInfo::productType() { @@ -995,6 +1056,9 @@ QString DSysInfo::computerName() QString DSysInfo::cpuModelName() { + if (!siGlobal->cpuModelName.isEmpty()) + return siGlobal->cpuModelName; + #ifdef Q_OS_LINUX static QFile file("/proc/cpuinfo"); @@ -1009,10 +1073,37 @@ QString DSysInfo::cpuModelName() } else if (map.contains("cpu model")) { // loonson3-cpuinfo sw-cpuinfo siGlobal->cpuModelName = map.value("cpu model"); + } else if (map.contains("Hardware")) { + // "HardWare" field contains cpu info on huawei kirin machine (e.g. klv or klu) + siGlobal->cpuModelName = map.value("Hardware"); } file.close(); } + + // Get the cpu info by executing lscpu command + if (siGlobal->cpuModelName.isEmpty()) { + const auto &lscpu_command = QStandardPaths::findExecutable("lscpu"); + if (lscpu_command.isEmpty()) { + qWarning() << "lscpu not found"; + return QString(); + } + QProcess lscpu; + QStringList env = QProcess::systemEnvironment(); + env << "LC_ALL=C"; // Add an environment variable + lscpu.setEnvironment(env); + lscpu.setProgram(lscpu_command); + lscpu.start(); + if (lscpu.waitForFinished(3000)) { + const QMap map = siGlobal->parseInfoContent(lscpu.readAll()); + if (map.contains("Model name")) { + siGlobal->cpuModelName = map.value("Model name"); + } + } else { + qWarning() << "lscpu:" << lscpu.errorString(); + } + } + return siGlobal->cpuModelName; #endif return QString(); @@ -1027,6 +1118,9 @@ qint64 DSysInfo::memoryInstalledSize() #ifdef Q_OS_LINUX // Getting Memory Installed Size // TODO: way to not dept on lshw? + if (siGlobal->memoryInstalledSize >= 0) { + return siGlobal->memoryInstalledSize; + } if (!QStandardPaths::findExecutable("lshw").isEmpty()) { QProcess lshw; @@ -1037,18 +1131,35 @@ qint64 DSysInfo::memoryInstalledSize() } const QByteArray &lshwInfoJson = lshw.readAllStandardOutput(); - QJsonArray lshwResultArray = QJsonDocument::fromJson(lshwInfoJson).array(); - if (!lshwResultArray.isEmpty()) { - QJsonValue memoryHwInfo = lshwResultArray.first(); - QString id = memoryHwInfo.toObject().value("id").toString(); - Q_ASSERT(id == "memory"); - siGlobal->memoryInstalledSize = memoryHwInfo.toObject().value("size").toDouble(); // TODO: check "units" is "bytes" ? + + QJsonParseError error; + auto doc = QJsonDocument::fromJson(lshwInfoJson, &error); + if (error.error != QJsonParseError::NoError) { + qCWarning(logSysInfo(), "parse failed, expect json doc from lshw command"); + return -1; + } + + if (!doc.isArray()) { + qCWarning(logSysInfo(), "parse failed, expect array"); + return -1; + } + + QJsonArray lshwResultArray = doc.array(); + for (const QJsonValue value : lshwResultArray) { + QJsonObject obj = value.toObject(); + if (obj.contains("id") && obj.value("id").toString() == "memory") { + siGlobal->memoryInstalledSize = obj.value("size").toDouble(); // TODO: check "units" is "bytes" ? + break; + } } } + Q_ASSERT(siGlobal->memoryInstalledSize > 0); + return siGlobal->memoryInstalledSize; -#endif +#else return -1; +#endif } /*! @@ -1068,10 +1179,10 @@ qint64 DSysInfo::systemDiskSize() { #ifdef Q_OS_LINUX // Getting Disk Size - const QString &deviceName = QStorageInfo::root().device(); + QString deviceName; QProcess lsblk; - lsblk.start("lsblk", {"-Jlpb", "-oNAME,KNAME,PKNAME,SIZE"}, QIODevice::ReadOnly); + lsblk.start("lsblk", {"-Jlpb", "-oNAME,KNAME,PKNAME,SIZE,MOUNTPOINT"}, QIODevice::ReadOnly); if (!lsblk.waitForFinished()) { return -1; @@ -1091,6 +1202,11 @@ qint64 DSysInfo::systemDiskSize() QString kname = oneValue.toObject().value("kname").toString(); QString pkname = oneValue.toObject().value("pkname").toString(); qulonglong size = oneValue.toObject().value("size").toVariant().toULongLong(); + QString deviceNameMP = oneValue.toObject().value("mountpoint").toString(); + + if ("/" == deviceNameMP){ + deviceName = name; + } if (keyName.isNull() && deviceName == name) { keyName = kname; @@ -1141,7 +1257,11 @@ QDateTime DSysInfo::shutdownTime() const QByteArray data = lastx.readLine(1024); //shutdown system down 4.19.0-amd64-des Fri Sep 30 17:53:17 2022 - Sat Oct 8 08:32:47 2022 (7+14:39) if (data.startsWith("shutdown")) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + QString timeFmt = QString(data).split(' ', Qt::SkipEmptyParts).mid(4, 5).join(' '); +#else QString timeFmt = QString(data).split(' ', QString::SkipEmptyParts).mid(4, 5).join(' '); +#endif dt = QDateTime::fromString(timeFmt); break; } diff --git a/src/dtkcore_global.cpp b/src/dtkcore_global.cpp index c22d020..8a65eb3 100644 --- a/src/dtkcore_global.cpp +++ b/src/dtkcore_global.cpp @@ -10,43 +10,6 @@ #error "DTK_VERSION or DTK_VERSION_STR not defined!" #endif -void doubleLoadCheck() -{ - QFile f("/proc/self/maps"); - if (!f.open(QIODevice::ReadOnly)) - qFatal("%s", f.errorString().toLocal8Bit().data()); - - const QByteArray &data = f.readAll(); - QTextStream ts(data); - QString modulePath; - while (Q_UNLIKELY(!ts.atEnd())) { - const QString line = ts.readLine(); - const QStringList &maps = line.split(' ', QString::SplitBehavior::SkipEmptyParts); - if (Q_UNLIKELY(maps.size() < 6)) - continue; - - QFileInfo info(maps.value(5)); - const QString &infoAbPath = info.absoluteFilePath(); - if (modulePath == infoAbPath || !info.fileName().contains("dtkcore") || info.fileName().contains("dtkcore.so.2")) - continue; - - if (modulePath.isEmpty()) { - modulePath = infoAbPath; - } else { - // modulePath != infoAbPath - QByteArray msg; - msg += modulePath + " and " + info.absoluteFilePath() + " both loaded"; - qFatal("%s", msg.data()); - } - } -} - -// 在库被加载时就执行此函数 -__attribute__((constructor)) void init() -{ - doubleLoadCheck(); -} - int dtkVersion() { return DTK_VERSION; @@ -57,5 +20,5 @@ const char *dtkVersionString() #ifdef QT_DEBUG qWarning() << "Use DTK_VERSION_STR instead."; #endif - return "";//DTK_VERSION_STR; + return ""; // DTK_VERSION_STR; } diff --git a/src/filesystem/dbasefilewatcher.cpp b/src/filesystem/dbasefilewatcher.cpp index f626a24..d277d13 100644 --- a/src/filesystem/dbasefilewatcher.cpp +++ b/src/filesystem/dbasefilewatcher.cpp @@ -18,11 +18,11 @@ DBaseFileWatcherPrivate::DBaseFileWatcherPrivate(DBaseFileWatcher *qq) } /*! - \class Dtk::Core::DBaseFileWatcher - \inmodule dtkcore +@~english + @class Dtk::Core::DBaseFileWatcher + @ingroup dtkcore - \brief The DBaseFileWatcher class provides an interface for monitoring files and directories for modifications. - \brief DBaseFileWatcher 类提供了一系列接口可供监视文件和目录的变动。 + @brief The DBaseFileWatcher class provides an interface for monitoring files and directories for modifications. */ DBaseFileWatcher::~DBaseFileWatcher() @@ -39,11 +39,9 @@ QUrl DBaseFileWatcher::fileUrl() const } /*! - \brief 开始文件变动监视 - \brief Let file watcher start watching file changes. - \return 成功开始返回 true ,否则返回 false. - - \sa stopWatcher(), restartWatcher() +@~english + @brief Let file watcher start watching file changes. + @sa stopWatcher(), restartWatcher() */ bool DBaseFileWatcher::startWatcher() { @@ -62,11 +60,9 @@ bool DBaseFileWatcher::startWatcher() } /*! - \brief 停止文件变动监视. - \brief Stop watching file changes. - \return 成功停止返回 true ,否则返回 false. - - \sa startWatcher(), restartWatcher() +@~english + @brief Stop watching file changes. + @sa startWatcher(), restartWatcher() */ bool DBaseFileWatcher::stopWatcher() { @@ -85,11 +81,9 @@ bool DBaseFileWatcher::stopWatcher() } /*! - \brief 重新开始文件变动监视. - \brief Stop file watcher and then restart it to watching file changes. - \return 成功开启返回 true,否则返回 false. - - \sa startWatcher(), stopWatcher() +@~english + @brief Stop file watcher and then restart it to watching file changes. + @sa startWatcher(), stopWatcher() */ bool DBaseFileWatcher::restartWatcher() { @@ -98,14 +92,10 @@ bool DBaseFileWatcher::restartWatcher() } /*! - \brief 设置是否对 \a subfileUrl 目录启用文件监视 - \brief Set enable file watcher for \a subfileUrl or not - - \a subfileUrl 设置所针对的 Url - \a subfileUrl The given url - - \a enabled 是否启用文件变动监视 - \a enabled Enable file change watching or not. +@~english + @brief Set enable file watcher for \a subfileUrl or not + @param[in] subfileUrl The given url + @param[in] enabled Enable file change watching or not. */ void DBaseFileWatcher::setEnabledSubfileWatcher(const QUrl &subfileUrl, bool enabled) { @@ -114,17 +104,15 @@ void DBaseFileWatcher::setEnabledSubfileWatcher(const QUrl &subfileUrl, bool ena } /*! - \brief 发送一个信号表示目标目录 \a targetUrl 得到了一个 \a signal 信号,包含参数 \a arg1 。 - \brief Emit a signal about \a targetUrl got a \a signal with \a arg1 - - 示例用法: +@~english + @brief Emit a signal about \a targetUrl got a \a signal with \a arg1 Example usage: - - \code + + @code DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileDeleted, QUrl("bookmark:///bookmarkFile1")); - \endcode + @endcode - \return 成功发送返回 true,否则返回 false. + @return 成功发送返回 true,否则返回 false. */ bool DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::SignalType1 signal, const QUrl &arg1) { @@ -144,15 +132,12 @@ bool DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::Sign } /*! - \brief 发送一个信号表示目标目录 \a targetUrl 得到了一个 \a signal 信号,包含参数 \a arg1 和 arg2。 - \brief Emit a signal about \a targetUrl got a \a signal with \a arg1 and \a arg2 - - 示例用法: +@~english + @brief Emit a signal about \a targetUrl got a \a signal with \a arg1 and \a arg2 Example usage: - - \code + @code DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileMoved, QUrl("bookmark:///bookmarkFile1"), QUrl("bookmark:///NewNameFile1")); - \endcode + @endcode */ bool DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::SignalType2 signal, const QUrl &arg1, const QUrl &arg2) { diff --git a/src/filesystem/dcapfile.cpp b/src/filesystem/dcapfile.cpp index e1cafea..0b37e33 100644 --- a/src/filesystem/dcapfile.cpp +++ b/src/filesystem/dcapfile.cpp @@ -4,7 +4,6 @@ #include "dcapfile.h" #include "dobject_p.h" -#include "dcapmanager.h" #include "private/dcapfsfileengine_p.h" #include @@ -75,19 +74,21 @@ bool DCapFile::exists(const QString &fileName) return DCapFile(fileName).exists(); } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QString DCapFile::readLink() const { D_DC(DCapFile); if (!d->canReadWrite(d->fileName)) return {}; - return QFile::readLink(); + return QFile::symLinkTarget(); } +#endif #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) QString DCapFile::symLinkTarget() const { - return readLink(); + return QFile::symLinkTarget(); } #endif diff --git a/src/filesystem/dcapfsfileengine.cpp b/src/filesystem/dcapfsfileengine.cpp index 09df413..ee826bf 100644 --- a/src/filesystem/dcapfsfileengine.cpp +++ b/src/filesystem/dcapfsfileengine.cpp @@ -14,13 +14,14 @@ DCORE_BEGIN_NAMESPACE extern QString _d_cleanPath(const QString &path); extern bool _d_isSubFileOf(const QString &filePath, const QString &directoryPath); +#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) static bool capDirIteraterHasNext(QAbstractFileEngineIterator *it) { const QStringList &paths = DCapManager::instance()->paths(); QString path = it->path(); QFileInfo info(path); if (info.isSymLink()) - info = info.symLinkTarget(); + info = QFileInfo{info.symLinkTarget()}; bool ret = std::any_of(paths.cbegin(), paths.cend(), std::bind(_d_isSubFileOf, path, std::placeholders::_1)); @@ -28,10 +29,19 @@ static bool capDirIteraterHasNext(QAbstractFileEngineIterator *it) return ret; return DVtableHook::callOriginalFun(it, &QAbstractFileEngineIterator::hasNext); } +#endif +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +std::unique_ptr DCapFSFileEngineHandler::create(const QString &fileName) const +#else QAbstractFileEngine *DCapFSFileEngineHandler::create(const QString &fileName) const +#endif { +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + return std::unique_ptr(new DCapFSFileEngine(fileName)); +#else return new DCapFSFileEngine(fileName); +#endif } @@ -83,12 +93,20 @@ DCapFSFileEngine::~DCapFSFileEngine() { } +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) +bool DCapFSFileEngine::open(QIODevice::OpenMode openMode, std::optional permissions) +#else bool DCapFSFileEngine::open(QIODevice::OpenMode openMode) +#endif { D_D(DCapFSFileEngine); if (!d->canReadWrite(d->file)) return false; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + return QFSFileEngine::open(openMode, permissions); +#else return QFSFileEngine::open(openMode); +#endif } bool DCapFSFileEngine::remove() @@ -138,12 +156,22 @@ bool DCapFSFileEngine::link(const QString &newName) return QFSFileEngine::link(newName); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) +bool DCapFSFileEngine::mkdir(const QString &dirName, + bool createParentDirectories, + std::optional permissions) const +#else bool DCapFSFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const +#endif { D_DC(DCapFSFileEngine); if (!d->canReadWrite(dirName)) return false; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + return QFSFileEngine::mkdir(dirName, createParentDirectories, permissions); +#else return QFSFileEngine::mkdir(dirName, createParentDirectories); +#endif } bool DCapFSFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const @@ -191,11 +219,20 @@ QStringList DCapFSFileEngine::entryList(QDir::Filters filters, const QStringList return {}; return QFSFileEngine::entryList(filters, filterNames); } - +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) +QAbstractFileEngine::IteratorUniquePtr DCapFSFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) +#elif QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +QAbstractFileEngine::IteratorUniquePtr DCapFSFileEngine::beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) +#else QAbstractFileEngine::Iterator *DCapFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames) +#endif { +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + auto ret = QFSFileEngine::beginEntryList(path, filters, filterNames); +#else auto ret = QFSFileEngine::beginEntryList(filters, filterNames); DVtableHook::overrideVfptrFun(ret, &QAbstractFileEngineIterator::hasNext, &capDirIteraterHasNext); +#endif return ret; } diff --git a/src/filesystem/dcapmanager.cpp b/src/filesystem/dcapmanager.cpp index 5a4729f..9e8ed34 100644 --- a/src/filesystem/dcapmanager.cpp +++ b/src/filesystem/dcapmanager.cpp @@ -25,14 +25,20 @@ bool _d_isSubFileOf(const QString &filePath, const QString &directoryPath) static QStringList defaultWriteablePaths() { QStringList paths; - int list[] = { - QStandardPaths::AppConfigLocation, QStandardPaths::AppDataLocation, - QStandardPaths::CacheLocation, QStandardPaths::TempLocation, - QStandardPaths::DataLocation, QStandardPaths::GenericConfigLocation, - QStandardPaths::HomeLocation, QStandardPaths::MusicLocation, - QStandardPaths::DocumentsLocation, QStandardPaths::MoviesLocation, - QStandardPaths::PicturesLocation, QStandardPaths::DownloadLocation - }; + int list[] = {QStandardPaths::AppConfigLocation, + QStandardPaths::AppDataLocation, + QStandardPaths::CacheLocation, + QStandardPaths::TempLocation, +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QStandardPaths::DataLocation, +#endif + QStandardPaths::GenericConfigLocation, + QStandardPaths::HomeLocation, + QStandardPaths::MusicLocation, + QStandardPaths::DocumentsLocation, + QStandardPaths::MoviesLocation, + QStandardPaths::PicturesLocation, + QStandardPaths::DownloadLocation}; for (uint i = 0; i < sizeof (list) / sizeof (int); ++i) { const QString &path = QStandardPaths::writableLocation(QStandardPaths::StandardLocation(list[i])); @@ -42,7 +48,7 @@ static QStringList defaultWriteablePaths() { paths.append(path); } - for (int i = 0; i <= static_cast(DStandardPaths::XDG::RuntimeTime); ++i) { + for (int i = 0; i <= static_cast(DStandardPaths::XDG::RuntimeDir); ++i) { const QString &path = DStandardPaths::path(DStandardPaths::XDG(i)); if (path.isEmpty()) continue; @@ -65,8 +71,6 @@ static QStringList defaultWriteablePaths() { return paths; } -static DCapFSFileEngineHandler *globalHandler = nullptr; - class DCapManagerPrivate : public DObjectPrivate { D_DECLARE_PUBLIC(DCapManager) @@ -96,20 +100,15 @@ DCapManager *DCapManager::instance() return capManager; } +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void DCapManager::registerFileEngine() { - if (globalHandler) - return; - globalHandler = new DCapFSFileEngineHandler; } void DCapManager::unregisterFileEngine() { - if (!globalHandler) - return; - delete globalHandler; - globalHandler = nullptr; } +#endif void DCapManager::appendPath(const QString &path) { diff --git a/src/filesystem/dfilesystemwatcher_dummy.cpp b/src/filesystem/dfilesystemwatcher_dummy.cpp index bb3f5f1..1a0c418 100644 --- a/src/filesystem/dfilesystemwatcher_dummy.cpp +++ b/src/filesystem/dfilesystemwatcher_dummy.cpp @@ -19,7 +19,8 @@ DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() } /*! - \class Dtk::Core::DFileSystemWatcher +@~english + @class Dtk::Core::DFileSystemWatcher \inmodule dtkcore \brief The DFileSystemWatcher class provides an interface for monitoring files and directories for modifications. @@ -41,13 +42,13 @@ DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() they have been renamed or removed from disk, and directories once they have been removed from disk. - \note On systems running a Linux kernel without inotify support, + @note On systems running a Linux kernel without inotify support, file systems that contain watched paths cannot be unmounted. - \note Windows CE does not support directory monitoring by + @note Windows CE does not support directory monitoring by default as this depends on the file system driver installed. - \note The act of monitoring files and directories for + @note The act of monitoring files and directories for modifications consumes system resources. This implies there is a limit to the number of files and directories your process can monitor simultaneously. On all BSD variants, for @@ -64,6 +65,7 @@ DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() /*! +@~english Constructs a new file system watcher object with the given \a parent. */ DFileSystemWatcher::DFileSystemWatcher(QObject *parent) @@ -74,6 +76,7 @@ DFileSystemWatcher::DFileSystemWatcher(QObject *parent) } /*! +@~english Constructs a new file system watcher object with the given \a parent which monitors the specified \a paths list. */ @@ -84,12 +87,14 @@ DFileSystemWatcher::DFileSystemWatcher(const QStringList &paths, QObject *parent } /*! +@~english Destroys the file system watcher. */ DFileSystemWatcher::~DFileSystemWatcher() { } /*! +@~english Adds \a path to the file system watcher if \a path exists. The path is not added if it does not exist, or if it is already being monitored by the file system watcher. @@ -105,12 +110,12 @@ DFileSystemWatcher::~DFileSystemWatcher() may include the resource not existing, access failures, or the total watch count limit, if the platform has one. - \note There may be a system dependent limit to the number of + @note There may be a system dependent limit to the number of files and directories that can be monitored simultaneously. If this limit is been reached, \a path will not be monitored, and false is returned. - \sa addPaths(), removePath() + @sa addPaths(), removePath() */ bool DFileSystemWatcher::addPath(const QString &path) { @@ -118,6 +123,7 @@ bool DFileSystemWatcher::addPath(const QString &path) } /*! +@~english Adds each path in \a paths to the file system watcher. Paths are not added if they not exist, or if they are already being monitored by the file system watcher. @@ -133,12 +139,12 @@ bool DFileSystemWatcher::addPath(const QString &path) may include the resource not existing, access failures, or the total watch count limit, if the platform has one. - \note There may be a system dependent limit to the number of + @note There may be a system dependent limit to the number of files and directories that can be monitored simultaneously. If this limit has been reached, the excess \a paths will not be monitored, and they will be added to the returned QStringList. - \sa addPath(), removePaths() + @sa addPath(), removePaths() */ QStringList DFileSystemWatcher::addPaths(const QStringList &paths) { @@ -146,6 +152,7 @@ QStringList DFileSystemWatcher::addPaths(const QStringList &paths) } /*! +@~english Removes the specified \a path from the file system watcher. If the watch is successfully removed, true is returned. @@ -153,7 +160,7 @@ QStringList DFileSystemWatcher::addPaths(const QStringList &paths) Reasons for watch removal failing are generally system-dependent, but may be due to the path having already been deleted, for example. - \sa removePaths(), addPath() + @sa removePaths(), addPath() */ bool DFileSystemWatcher::removePath(const QString &path) { @@ -161,6 +168,7 @@ bool DFileSystemWatcher::removePath(const QString &path) } /*! +@~english Removes the specified \a paths from the file system watcher. The return value is a list of paths which were not able to be @@ -169,7 +177,7 @@ bool DFileSystemWatcher::removePath(const QString &path) Reasons for watch removal failing are generally system-dependent, but may be due to the path having already been deleted, for example. - \sa removePath(), addPaths() + @sa removePath(), addPaths() */ QStringList DFileSystemWatcher::removePaths(const QStringList &paths) { @@ -177,16 +185,18 @@ QStringList DFileSystemWatcher::removePaths(const QStringList &paths) } /*! - \fn void DFileSystemWatcher::fileChanged(const QString &path) +@~english + @fn void DFileSystemWatcher::fileChanged(const QString &path) This signal is emitted when the file at the specified \a path is modified, renamed or removed from disk. - \sa directoryChanged() + @sa directoryChanged() */ /*! - \fn void DFileSystemWatcher::directoryChanged(const QString &path) +@~english + @fn void DFileSystemWatcher::directoryChanged(const QString &path) This signal is emitted when the directory at a specified \a path is modified (e.g., when a file is added or deleted) or removed @@ -195,23 +205,25 @@ QStringList DFileSystemWatcher::removePaths(const QStringList &paths) However, the last change in the sequence of changes will always generate this signal. - \sa fileChanged() + @sa fileChanged() */ /*! - \fn QStringList DFileSystemWatcher::directories() const +@~english + @fn QStringList DFileSystemWatcher::directories() const Returns a list of paths to directories that are being watched. - \sa files() + @sa files() */ /*! - \fn QStringList DFileSystemWatcher::files() const +@~english + @fn QStringList DFileSystemWatcher::files() const Returns a list of paths to files that are being watched. - \sa directories() + @sa directories() */ QStringList DFileSystemWatcher::directories() const diff --git a/src/filesystem/dfilesystemwatcher_linux.cpp b/src/filesystem/dfilesystemwatcher_linux.cpp index 32ce28c..de5140f 100644 --- a/src/filesystem/dfilesystemwatcher_linux.cpp +++ b/src/filesystem/dfilesystemwatcher_linux.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -232,7 +233,7 @@ void DFileSystemWatcherPrivate::_q_readFromInotify() if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) { do { if (event.mask & IN_MOVE_SELF) { - QMap::const_iterator iterator = cookieToFilePath.constBegin(); + QMultiMap::const_iterator iterator = cookieToFilePath.constBegin(); bool isMove = false; diff --git a/src/filesystem/dfilewatcher.cpp b/src/filesystem/dfilewatcher.cpp index 00b5039..3a054e5 100644 --- a/src/filesystem/dfilewatcher.cpp +++ b/src/filesystem/dfilewatcher.cpp @@ -203,11 +203,11 @@ QString DFileWatcherPrivate::formatPath(const QString &path) } /*! +@~english \class Dtk::Core::DFileWatcher \inmodule dtkcore \brief The DFileWatcher class provides an implementation of DBaseFileWatcher for monitoring files and directories for modifications. - \brief DFileWatcher 类提供了对 DBaseFileWatcher 接口的实现,可供监视文件和目录的变动。 */ DFileWatcher::DFileWatcher(const QString &filePath, QObject *parent) diff --git a/src/filesystem/dfilewatchermanager.cpp b/src/filesystem/dfilewatchermanager.cpp index 8ac0530..2c3bbbd 100644 --- a/src/filesystem/dfilewatchermanager.cpp +++ b/src/filesystem/dfilewatchermanager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -24,33 +24,26 @@ public: DFileWatcherManagerPrivate::DFileWatcherManagerPrivate(DFileWatcherManager *qq) : DObjectPrivate(qq) { - } /*! +@~english \class Dtk::Core::DFileWatcherManager \inmodule dtkcore \brief The DFileWatcherManager class can help you manage file watchers and get signal when file got changed. - \brief DFileWatcherManager 类可以帮助管理一系列 DFileWatcher 文件监视器,并在文件变动时发送信号通知. */ DFileWatcherManager::DFileWatcherManager(QObject *parent) : QObject(parent) , DObject(*new DFileWatcherManagerPrivate(this)) { - } -DFileWatcherManager::~DFileWatcherManager() -{ - -} +DFileWatcherManager::~DFileWatcherManager() {} /*! - \brief 为路径 \a filePath 创建 DFileWatcher 并将其添加到 DFileWatcherManager 中. +@~english \brief Add file watcher for \a filePath to the file watcher manager. - - \return 被创建并添加到 DFileWatcherManager 的 DFileWatcher \return The file watcher which got created and added into the file watcher manager. */ DFileWatcher *DFileWatcherManager::add(const QString &filePath) @@ -65,24 +58,16 @@ DFileWatcher *DFileWatcherManager::add(const QString &filePath) watcher = new DFileWatcher(filePath, this); - connect(watcher, &DFileWatcher::fileAttributeChanged, this, [this](const QUrl & url) { + connect(watcher, &DFileWatcher::fileAttributeChanged, this, [this](const QUrl &url) { Q_EMIT fileAttributeChanged(url.toLocalFile()); }); - connect(watcher, &DFileWatcher::fileClosed, this, [this](const QUrl & url) { - Q_EMIT fileClosed(url.toLocalFile()); - }); - connect(watcher, &DFileWatcher::fileDeleted, this, [this](const QUrl & url) { - Q_EMIT fileDeleted(url.toLocalFile()); - }); - connect(watcher, &DFileWatcher::fileModified, this, [this](const QUrl & url) { - Q_EMIT fileModified(url.toLocalFile()); - }); - connect(watcher, &DFileWatcher::fileMoved, this, [this](const QUrl & fromUrl, const QUrl & toUrl) { + connect(watcher, &DFileWatcher::fileClosed, this, [this](const QUrl &url) { Q_EMIT fileClosed(url.toLocalFile()); }); + connect(watcher, &DFileWatcher::fileDeleted, this, [this](const QUrl &url) { Q_EMIT fileDeleted(url.toLocalFile()); }); + connect(watcher, &DFileWatcher::fileModified, this, [this](const QUrl &url) { Q_EMIT fileModified(url.toLocalFile()); }); + connect(watcher, &DFileWatcher::fileMoved, this, [this](const QUrl &fromUrl, const QUrl &toUrl) { Q_EMIT fileMoved(fromUrl.toLocalFile(), toUrl.toLocalFile()); }); - connect(watcher, &DFileWatcher::subfileCreated, this, [this](const QUrl & url) { - Q_EMIT subfileCreated(url.toLocalFile()); - }); + connect(watcher, &DFileWatcher::subfileCreated, this, [this](const QUrl &url) { Q_EMIT subfileCreated(url.toLocalFile()); }); d->watchersMap[filePath] = watcher; watcher->startWatcher(); @@ -91,7 +76,7 @@ DFileWatcher *DFileWatcherManager::add(const QString &filePath) } /*! - \brief 从当前 DFileWatcherManager 中移除监视 \a filePath 的 DFileWatcher. +@~english \brief Remove file watcher for \a filePath from the file watcher manager. */ void DFileWatcherManager::remove(const QString &filePath) @@ -105,4 +90,27 @@ void DFileWatcherManager::remove(const QString &filePath) } } +/*! +@~english + @brief Remove all file watcher +*/ +void DFileWatcherManager::removeAll() +{ + Q_D(DFileWatcherManager); + for (auto it : d->watchersMap) { + it->deleteLater(); + } + d->watchersMap.clear(); +} + +/*! +@~english + @brief Show all file watcher +*/ +QStringList DFileWatcherManager::watchedFiles() const +{ + Q_D(const DFileWatcherManager); + return d->watchersMap.keys(); +} + DCORE_END_NAMESPACE diff --git a/src/filesystem/dstandardpaths.cpp b/src/filesystem/dstandardpaths.cpp index 6348b7c..a749207 100644 --- a/src/filesystem/dstandardpaths.cpp +++ b/src/filesystem/dstandardpaths.cpp @@ -118,9 +118,7 @@ QString DStandardPaths::homePath() if (!home.isEmpty()) return QString::fromLocal8Bit(home); - struct passwd *pw = getpwuid(getuid()); - const char *homedir = pw->pw_dir; - return QString::fromLocal8Bit(homedir); + return homePath(getuid()); } QString DStandardPaths::path(DStandardPaths::XDG type) @@ -144,12 +142,23 @@ QString DStandardPaths::path(DStandardPaths::XDG type) return QString::fromLocal8Bit(path); return homePath() + QStringLiteral("/.config"); } - case XDG::RuntimeTime: { + case XDG::RuntimeDir: { const QByteArray &path = qgetenv("XDG_RUNTIME_DIR"); if (!path.isEmpty()) return QString::fromLocal8Bit(path); return QStringLiteral("/run/user/") + QString::number(getuid()); } + case XDG::StateHome: { + const QByteArray &path = qgetenv("XDG_STATE_HOME"); + if (!path.isEmpty()) + return QString::fromLocal8Bit(path); +#ifdef Q_OS_LINUX + return homePath() + QStringLiteral("/.local/state"); +#else + // TODO: handle it on mac + return QString(); +#endif + } } return QString(); } diff --git a/src/filesystem/dtrashmanager_linux.cpp b/src/filesystem/dtrashmanager_linux.cpp index 80a6dc2..8d0fc81 100644 --- a/src/filesystem/dtrashmanager_linux.cpp +++ b/src/filesystem/dtrashmanager_linux.cpp @@ -71,7 +71,7 @@ static bool writeTrashInfo(const QString &fileBaseName, const QString &sourceFil data.append("[Trash Info]\n"); data.append("Path=").append(sourceFilePath.toUtf8().toPercentEncoding("/")).append("\n"); - data.append("DeletionDate=").append(datetime.toString(Qt::ISODate)).append("\n"); + data.append("DeletionDate=").append(datetime.toString(Qt::ISODate).toLatin1()).append("\n"); qint64 size = metadata.write(data); metadata.close(); diff --git a/src/filesystem/private/dcapfsfileengine_p.h b/src/filesystem/private/dcapfsfileengine_p.h index b032405..ea9d593 100644 --- a/src/filesystem/private/dcapfsfileengine_p.h +++ b/src/filesystem/private/dcapfsfileengine_p.h @@ -14,7 +14,11 @@ DCORE_BEGIN_NAMESPACE class DCapFSFileEngineHandler : public QAbstractFileEngineHandler { public: +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + std::unique_ptr create(const QString &fileName) const override; +#else QAbstractFileEngine *create(const QString &fileName) const override; +#endif }; class DCapFSFileEnginePrivate; @@ -25,19 +29,35 @@ public: DCapFSFileEngine(const QString &file); ~DCapFSFileEngine() override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + bool open(QIODevice::OpenMode openMode, std::optional permissions = std::nullopt) override; +#else bool open(QIODevice::OpenMode openMode) override; +#endif bool remove() override; bool copy(const QString &newName) override; bool rename(const QString &newName) override; bool renameOverwrite(const QString &newName) override; bool link(const QString &newName) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + bool mkdir(const QString &dirName, + bool createParentDirectories, + std::optional permissions = std::nullopt) const override; +#else bool mkdir(const QString &dirName, bool createParentDirectories) const override; +#endif bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; FileFlags fileFlags(FileFlags type) const override; bool cloneTo(QAbstractFileEngine *target) override; bool setSize(qint64 size) override; QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) + IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) override; +#elif QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) override; +#else Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override; +#endif bool canReadWrite(const QString &path) const; }; diff --git a/src/glob.cmake b/src/glob.cmake index 9703bbd..83bcdb8 100644 --- a/src/glob.cmake +++ b/src/glob.cmake @@ -1,29 +1,48 @@ +set(OUTER_SOURCE + ${CMAKE_CURRENT_LIST_DIR}/dconfig.cpp + ${CMAKE_CURRENT_LIST_DIR}/dsgapplication.cpp + ${CMAKE_CURRENT_LIST_DIR}/dsysinfo.cpp + ${CMAKE_CURRENT_LIST_DIR}/dlicenseinfo.cpp + ${CMAKE_CURRENT_LIST_DIR}/dsecurestring.cpp + ${CMAKE_CURRENT_LIST_DIR}/ddesktopentry.cpp +) + +if (NOT DTK_VERSION_MAJOR) + list(APPEND OUTER_SOURCE ${CMAKE_CURRENT_LIST_DIR}/dtkcore_global.cpp) +endif() + +set(OUTER_HEADER + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dtkcore_global.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dconfig.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dsgapplication.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dsysinfo.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dlicenseinfo.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dsecurestring.h + ${CMAKE_CURRENT_LIST_DIR}/../include/global/ddesktopentry.h +) + if(LINUX) - file(GLOB OUTER_SOURCE - ${CMAKE_CURRENT_LIST_DIR}/*.cpp + if(DEFINED D_DSG_APP_DATA_FALLBACK) + add_definitions(-DD_DSG_APP_DATA_FALLBACK="${D_DSG_APP_DATA_FALLBACK}") + endif() + list(APPEND OUTER_SOURCE + ${CMAKE_CURRENT_LIST_DIR}/dconfigfile.cpp ) - file(GLOB OUTER_HEADER - ${CMAKE_CURRENT_LIST_DIR}/../include/global/*.h + list(APPEND OUTER_HEADER + ${CMAKE_CURRENT_LIST_DIR}/../include/global/dconfigfile.h ) +# generic dbus interfaces + if(NOT DEFINED DTK_DISABLE_DBUS_CONFIG) + include(${CMAKE_CURRENT_LIST_DIR}/dbus/dbus.cmake) + list(APPEND glob_SRC ${dbus_SRCS}) + else() + add_definitions(-DD_DISABLE_DBUS_CONFIG) + endif() else() - set(OUTER_SOURCE - ${CMAKE_CURRENT_LIST_DIR}/dconfig.cpp - ${CMAKE_CURRENT_LIST_DIR}/dsgapplication.cpp - ${CMAKE_CURRENT_LIST_DIR}/dsysinfo.cpp - ${CMAKE_CURRENT_LIST_DIR}/dsecurestring.cpp - ${CMAKE_CURRENT_LIST_DIR}/ddesktopentry.cpp - ${CMAKE_CURRENT_LIST_DIR}/dtkcore_global.cpp - ) - set(OUTER_HEADER - ${CMAKE_CURRENT_LIST_DIR}/../include/global/dtkcore_global.h - ${CMAKE_CURRENT_LIST_DIR}/../include/dconfig.h - ${CMAKE_CURRENT_LIST_DIR}/../include/dsgapplication.h - ${CMAKE_CURRENT_LIST_DIR}/../include/dsysinfo.h - ${CMAKE_CURRENT_LIST_DIR}/../include/dsecurestring.h - ${CMAKE_CURRENT_LIST_DIR}/../include/ddesktopentry.h - ) + add_definitions(-DD_DISABLE_DCONFIG) endif() -set(glob_SRC + +list(APPEND glob_SRC ${OUTER_HEADER} ${OUTER_SOURCE} ) diff --git a/src/log/AbstractAppender.cpp b/src/log/AbstractAppender.cpp deleted file mode 100644 index 5ac16eb..0000000 --- a/src/log/AbstractAppender.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "AbstractAppender.h" - -DCORE_BEGIN_NAMESPACE - -/*! - \class Dtk::Core::AbstractAppender - \inmodule dtkcore - - \brief The AbstractAppender class provides an abstract base class for writing a log entries. - - The AbstractAppender class is the base interface class for all log appenders that could be used with Logger. - - AbstractAppender provides a common implementation for the thread safe, mutex-protected logging of application - messages, such as ConsoleAppender, FileAppender or something else. AbstractAppender is abstract and can not be - instantiated, but you can use any of its subclasses or create a custom log appender at your choice. - - Appenders are the logical devices that is aimed to be attached to Logger object by calling - Logger::registerAppender(). On each log record call from the application Logger object sequentially calls write() - function on all the appenders registered in it. - - You can subclass AbstractAppender to implement a logging target of any kind you like. It may be the external logging - subsystem (for example, syslog in *nix), XML file, SQL database entries, D-Bus messages or anything else you can - imagine. - - For the simple non-structured plain text logging (for example, to a plain text file or to the console output) you may - like to subclass the AbstractStringAppender instead of AbstractAppender, which will give you a more convenient way to - control the format of the log output. - - \sa AbstractStringAppender - \sa Logger::registerAppender() - */ - - -/*! - \brief Constructs a AbstractAppender object. - */ -AbstractAppender::AbstractAppender() - :m_detailsLevel(Logger::Debug) -{ - -} - -/*! - \brief Destructs the AbstractAppender object. - */ -AbstractAppender::~AbstractAppender() -{ - -} - -/*! - \brief Returns the current details level of appender. - - Log records with a log level lower than a current detailsLevel() will be silently ignored by appender and would not - be sent to its append() function. - - It provides additional logging flexibility, allowing you to set the different severity levels for different types - of logs. - - \note This function is thread safe. - - \return The log level. - - \sa setDetailsLevel() - \sa Logger::LogLevel - */ -Logger::LogLevel AbstractAppender::detailsLevel() const -{ - QMutexLocker locker(&m_detailsLevelMutex); - return m_detailsLevel; -} - -/*! - \brief Sets the current details level of appender. - - Default details \a level is Logger::Debug - - \note This function is thread safe. - - \sa detailsLevel() - \sa Logger::LogLevel - */ -void Dtk::Core::AbstractAppender::setDetailsLevel(Logger::LogLevel level) -{ - QMutexLocker locker(&m_detailsLevelMutex); - m_detailsLevel = level; -} - -/*! - \brief Sets the current details \a level of appender. - - This function is provided for convenience, it behaves like an above function. - - \sa detailsLevel() - \sa Logger::LogLevel - */ -void AbstractAppender::setDetailsLevel(const QString &level) -{ - setDetailsLevel(Logger::levelFromString(level)); -} - -/*! - \brief Tries to write the log record to this logger. - - This is the function called by Logger object to write a log \a message to the appender. - - The \a time parameter indicates the time stamp. - The \a level parameter describes the LogLevel. - The \a file parameter is the current file name. - The \a line parameter indicates the number of lines to output. - The \a func parameter indicates the function name to output. - The \a category parameter indicates the log category. - The \a msg parameter indicates the output message. - - \note This function is thread safe. - - \sa Logger::write() - \sa detailsLevel() - */ -void AbstractAppender::write(const QDateTime &time, Logger::LogLevel level, const char *file, int line, const char *func, const QString &category, const QString &msg) -{ - if (level < detailsLevel()) - return; - - QMutexLocker locker(&m_writeMutex); - append(time, level, file, line, func, category, msg); -} - -/*! - \fn virtual void AbstractAppender::append(const QDateTime &timeStamp, Logger::LogLevel level, const char *file, int line, - const char *function, const QString &category, const QString &message) = 0 - - \brief Writes the log record to the logger instance - - This function is called every time when user tries to write a message to this AbstractAppender instance using - the write() function. Write function works as proxy and transfers only the messages with log level more or equal - to the current logLevel(). - - Overload this function when you are implementing a custom appender. - - The \a time parameter indicates the time stamp. - The \a level parameter describes the LogLevel. - The \a file parameter is the current file name. - The \a line parameter indicates the number of lines to output. - The \a func parameter indicates the function name to output. - The \a category parameter indicates the log category. - The \a msg parameter indicates the output message. - - \note This function is not needed to be thread safe because it is never called directly by Logger object. The - write() function works as a proxy and protects this function from concurrent access. - - \sa Logger::write() - */ - -DCORE_END_NAMESPACE diff --git a/src/log/AbstractStringAppender.cpp b/src/log/AbstractStringAppender.cpp deleted file mode 100644 index dcf4c37..0000000 --- a/src/log/AbstractStringAppender.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "AbstractStringAppender.h" - -#include -#include -#include - -DCORE_BEGIN_NAMESPACE - -/*! - \class Dtk::Core::AbstractStringAppender - \inmodule dtkcore - - \brief The AbstractStringAppender class provides a convenient base for appenders working with plain text formatted - logs. - - AbstractSringAppender is the simple extension of the AbstractAppender class providing the convenient way to create - custom log appenders working with a plain text formatted log targets. - - It have the formattedString() protected function that formats the logging arguments according to a format set with - setFormat(). - - This class can not be directly instantiated because it contains pure virtual function inherited from AbstractAppender - class. - - For more detailed description of customizing the log output format see the documentation on the setFormat() function. - */ - -const char formattingMarker = '%'; - -/*! - \brief Constructs a new string appender object. - */ -AbstractStringAppender::AbstractStringAppender() - : m_format(QLatin1String("%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n")) -{ - -} - -/*! - \brief Returns the current log format string. - - The default format is set to "%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n". You can set a different log record - format using the setFormat() function. - - \sa setFormat(const QString&) - */ -QString AbstractStringAppender::format() const -{ - QReadLocker locker(&m_formatLock); - return m_format; -} - -/*! - \brief Sets the logging format for writing strings to the log target with this appender. - - The string format seems to be very common to those developers who have used a standard sprintf function. - - Log output format is a simple QString with the special markers (starting with % sign) which will be replaced with - it's internal meaning when writing a log record. - - Controlling marker begins with the percent sign (%) which is followed by the command inside {} brackets - (the command describes, what will be put to log record instead of marker). - Optional field width argument may be specified right after the command (through the colon symbol before the closing bracket) - Some commands requires an additional formatting argument (in the second {} brackets). - - Field width argument works almost identically to the QString::arg() fieldWidth argument (and uses it - internally). For example, "%{type:-7}" will be replaced with the left padded debug level of the message - ("Debug ") or something. For the more detailed description of it you may consider to look to the Qt - Reference Documentation. - - Supported marker commands are: - \list - \li %{time} - timestamp. You may specify your custom timestamp \a format using the second {} brackets after the marker, - \li timestamp \a format here will be similar to those used in QDateTime::toString() function. For example, - \li "%{time}{dd-MM-yyyy, HH:mm}" may be replaced with "17-12-2010, 20:17" depending on current date and time. - \li The default \a format used here is "HH:mm:ss.zzz". - \li %{type} - Log level. Possible log levels are shown in the Logger::LogLevel enumerator. - \li %{Type} - Uppercased log level. - \li %{typeOne} - One letter log level. - \li %{TypeOne} - One uppercase letter log level. - \li %{File} - Full source file name (with path) of the file that requested log recording. Uses the __FILE__ - \li preprocessor macro. - \li %{file} - Short file name (with stripped path). - \li %{line} - Line number in the source file. Uses the __LINE__ preprocessor macro. - \li %{Function} - Name of function that called on of the LOG_* macros. Uses the Q_FUNC_INFO macro provided with - \li Qt. - \li %{function} - Similar to the %{Function}, but the function name is stripped using stripFunctionName - \li %{message} - The log message sent by the caller. - \li %{category} - The log category. - \li %{appname} - Application name (returned by QCoreApplication::applicationName() function). - \li %{pid} - Application pid (returned by QCoreApplication::applicationPid() function). - \li %{threadid} - ID of current thread. - \li %% - Convinient marker that is replaced with the single % mark. - \endlist - - \note Format doesn't add '\\n' to the end of the \a format line. Please consider adding it manually. - - \sa format() - \sa stripFunctionName() - \sa Logger::LogLevel - */ -void AbstractStringAppender::setFormat(const QString &format) -{ - QWriteLocker locker(&m_formatLock); - m_format = format; -} - -/*! - \brief Strips the long function signature (as added by Q_FUNC_INFO macro). - - The string processing drops the returning type, arguments and template parameters of function. It is definitely - useful for enchancing the log output readability. - - The \a name parameter is the function name. - - \return stripped function name - */ -QString AbstractStringAppender::stripFunctionName(const char *name) -{ - return QString::fromLatin1(qCleanupFuncinfo(name)); -} - -// The function was backported from Qt5 sources (qlogging.h) -QByteArray AbstractStringAppender::qCleanupFuncinfo(const char *name) -{ - QByteArray info(name); - - // Strip the function info down to the base function name - // note that this throws away the template definitions, - // the parameter types (overloads) and any const/volatile qualifiers. - if (info.isEmpty()) - return info; - - int pos; - - // skip trailing [with XXX] for templates (gcc) - pos = info.size() - 1; - if (info.endsWith(']')) { - while (--pos) { - if (info.at(pos) == '[') - info.truncate(pos); - } - } - - bool hasLambda = false; - QRegExp lambdaRegex("::"); - int lambdaIndex = lambdaRegex.indexIn(QString::fromLatin1(info)); - if (lambdaIndex != -1) - { - hasLambda = true; - info.remove(lambdaIndex, lambdaRegex.matchedLength()); - } - - // operator names with '(', ')', '<', '>' in it - static const char operator_call[] = "operator()"; - static const char operator_lessThan[] = "operator<"; - static const char operator_greaterThan[] = "operator>"; - static const char operator_lessThanEqual[] = "operator<="; - static const char operator_greaterThanEqual[] = "operator>="; - - // canonize operator names - info.replace("operator ", "operator"); - - // remove argument list - Q_FOREVER { - int parencount = 0; - pos = info.lastIndexOf(')'); - if (pos == -1) { - // Don't know how to parse this function name - return info; - } - - // find the beginning of the argument list - --pos; - ++parencount; - while (pos && parencount) { - if (info.at(pos) == ')') - ++parencount; - else if (info.at(pos) == '(') - --parencount; - --pos; - } - if (parencount != 0) - return info; - - info.truncate(++pos); - - if (info.at(pos - 1) == ')') { - if (info.indexOf(operator_call) == pos - (int)strlen(operator_call)) - break; - - // this function returns a pointer to a function - // and we matched the arguments of the return type's parameter list - // try again - info.remove(0, info.indexOf('(')); - info.chop(1); - continue; - } else { - break; - } - } - - if (hasLambda) - info.append("::lambda"); - - // find the beginning of the function name - int parencount = 0; - int templatecount = 0; - --pos; - - // make sure special characters in operator names are kept - if (pos > -1) { - switch (info.at(pos)) { - case ')': - if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1) - pos -= 2; - break; - case '<': - if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1) - --pos; - break; - case '>': - if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1) - --pos; - break; - case '=': { - int operatorLength = (int)strlen(operator_lessThanEqual); - if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1) - pos -= 2; - else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1) - pos -= 2; - break; - } - default: - break; - } - } - - while (pos > -1) { - if (parencount < 0 || templatecount < 0) - return info; - - char c = info.at(pos); - if (c == ')') - ++parencount; - else if (c == '(') - --parencount; - else if (c == '>') - ++templatecount; - else if (c == '<') - --templatecount; - else if (c == ' ' && templatecount == 0 && parencount == 0) - break; - - --pos; - } - info = info.mid(pos + 1); - - // remove trailing '*', '&' that are part of the return argument - while ((info.at(0) == '*') - || (info.at(0) == '&')) - info = info.mid(1); - - // we have the full function name now. - // clean up the templates - while ((pos = info.lastIndexOf('>')) != -1) { - if (!info.contains('<')) - break; - - // find the matching close - int end = pos; - templatecount = 1; - --pos; - while (pos && templatecount) { - register char c = info.at(pos); - if (c == '>') - ++templatecount; - else if (c == '<') - --templatecount; - --pos; - } - ++pos; - info.remove(pos, end - pos + 1); - } - - return info; -} - -/*! - \brief Returns the string to record to the logging target, formatted according to the format(). - - \a time The time stamp. - The \a level parameter describes the LogLevel, and the \a file parameter is the current file name, - and the \a line parameter indicates the number of lines to output. - The \a func parameter indicates the function name to output. - The \a category parameter indicates the log category. - The \a msg parameter indicates the output message. - - \sa format() - \sa setFormat(const QString&) - */ -QString AbstractStringAppender::formattedString(const QDateTime &time, Logger::LogLevel level, - const char *file, int line, const char *func, - const QString &category, const QString &msg) const -{ - QString f = format(); - const int size = f.size(); - - QString result; - - int i = 0; - while (i < f.size()) { - QChar c = f.at(i); - - // We will silently ignore the broken % marker at the end of string - if (c != QLatin1Char(formattingMarker) || (i + 2) >= size) { - result.append(c); - } else { - i += 2; - QChar currentChar = f.at(i); - QString command; - int fieldWidth = 0; - - if (currentChar.isLetter()) { - command.append(currentChar); - int j = 1; - while ((i + j) < size && f.at(i + j).isLetter()) { - command.append(f.at(i+j)); - j++; - } - - i+=j; - currentChar = f.at(i); - - // Check for the padding instruction - if (currentChar == QLatin1Char(':')) { - currentChar = f.at(++i); - if (currentChar.isDigit() || currentChar.category() == QChar::Punctuation_Dash) { - int j = 1; - while ((i + j) < size && f.at(i + j).isDigit()) j++; - - fieldWidth = f.mid(i, j).toInt(); - i += j; - } - } - } - - // Log record chunk to insert instead of formatting instruction - QString chunk; - - // Time stamp - if (command == QLatin1String("time")) { - if (f.at(i + 1) == QLatin1Char('{')) { - int j = 1; - while ((i + 2 + j) < size && f.at(i + 2 + j) != QLatin1Char('}')) j++; - - if ((i + 2 + j) < size) { - chunk = time.toString(f.mid(i + 2, j)); - - i += j; - i += 2; - } - } - - if (chunk.isNull()) - chunk = time.toString(QLatin1String("HH:mm:ss.zzz")); - - } else if (command == QLatin1String("type")) { - // Log level - chunk = Logger::levelToString(level); - } else if (command == QLatin1String("Type")) { - // Uppercased log level - chunk = Logger::levelToString(level).toUpper(); - } else if (command == QLatin1String("typeOne")) { - // One letter log level - chunk = Logger::levelToString(level).left(1).toLower(); - } else if (command == QLatin1String("TypeOne")) { - // One uppercase letter log level - chunk = Logger::levelToString(level).left(1).toUpper(); - } else if (command == QLatin1String("File")) { - // Filename - chunk = QLatin1String(file); - } else if (command == QLatin1String("file")) { - // Filename without a path - chunk = QString(QLatin1String(file)).section('/', -1); - } else if (command == QLatin1String("line")) { - // Source line number - chunk = QString::number(line); - } else if (command == QLatin1String("Function")) { - // Function name, as returned by Q_FUNC_INFO - chunk = QString::fromLatin1(func); - } else if (command == QLatin1String("function")) { - // Stripped function name - chunk = stripFunctionName(func); - } else if (command == QLatin1String("message")) { - // Log message - chunk = msg; - } else if (command == QLatin1String("category")) { - // Log message - chunk = category; - } else if (command == QLatin1String("pid")) { - // Application pid - chunk = QString::number(QCoreApplication::applicationPid()); - } else if (command == QLatin1String("appname")) { - // Application name - chunk = QCoreApplication::applicationName(); - } else if (command == QLatin1String("threadid")) { - // Thread ID (duplicates Qt5 threadid debbuging way) - chunk = QLatin1String("0x") + QString::number(qlonglong(QThread::currentThread()->currentThread()), 16); - } else if (command == QString(formattingMarker)) { - // We simply replace the double formatting marker (%) with one - chunk = QLatin1Char(formattingMarker); - } else { - // Do not process any unknown commands - chunk = QString(formattingMarker); - chunk.append(command); - } - - if (!chunk.isEmpty() && chunk != "0") { - result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth)); - } - } - ++i; - } - - return result; -} - -DCORE_END_NAMESPACE diff --git a/src/log/ConsoleAppender.cpp b/src/log/ConsoleAppender.cpp deleted file mode 100644 index b3bc852..0000000 --- a/src/log/ConsoleAppender.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -// Local -#include "ConsoleAppender.h" - -// STL -#include - -DCORE_BEGIN_NAMESPACE - -/*! - \class Dtk::Core::ConsoleAppender - \inmodule dtkcore - - \brief ConsoleAppender is the simple appender that writes the log records to the std::cerr output stream. - - ConsoleAppender uses "[%{type:-7}] <%{function}> %{message}\n" as a default output format. It is similar to the - AbstractStringAppender but doesn't show a time. - - You can modify ConsoleAppender output format without modifying your code by using \c QT_MESSAGE_PATTERN environment - variable. If you need your application to ignore this environment variable you can call - ConsoleAppender::ignoreEnvironmentPattern(true) - */ - - -ConsoleAppender::ConsoleAppender() - : AbstractStringAppender() - ,m_ignoreEnvPattern(false) -{ - setFormat("[%{type:-7}] <%{function}> %{message}\n"); -} - - -QString ConsoleAppender::format() const -{ - const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN")); - return (m_ignoreEnvPattern || envPattern.isEmpty()) ? AbstractStringAppender::format() : (envPattern + "\n"); -} - - -void ConsoleAppender::ignoreEnvironmentPattern(bool ignore) -{ - m_ignoreEnvPattern = ignore; -} - -/*! - \brief Writes the log record to the std::cerr stream. - \reimp - - The \a time parameter indicates the time stamp. - The \a level parameter describes the LogLevel. - The \a file parameter is the current file name. - The \a line parameter indicates the number of lines to output. - The \a func parameter indicates the function name to output. - The \a category parameter indicates the log category. - The \a msg parameter indicates the output message. - - \sa AbstractStringAppender::format() - */ -void ConsoleAppender::append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg) -{ - std::cerr << qPrintable(formattedString(time, level, file, line, func, category, msg)); -} - -DCORE_END_NAMESPACE diff --git a/src/log/FileAppender.cpp b/src/log/FileAppender.cpp deleted file mode 100644 index 971ca23..0000000 --- a/src/log/FileAppender.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "FileAppender.h" - -#include - -DCORE_BEGIN_NAMESPACE - -/*! - \class Dtk::Core::FileAppender - \inmodule dtkcore - - \brief Simple appender that writes the log records to the plain text file. - */ - - -/*! - \brief Constructs the new file appender assigned to file with the given \a fileName. - */ -FileAppender::FileAppender(const QString &fileName) -{ - setFileName(fileName); -} - - -FileAppender::~FileAppender() -{ - closeFile(); -} - -/*! - \brief Returns the name set by setFileName() or to the FileAppender constructor. - - \sa setFileName() - */ -QString FileAppender::fileName() const -{ - QMutexLocker locker(&m_logFileMutex); - return m_logFile.fileName(); -} - -/*! - \brief Sets the \a s name of the file. The name can have no path, a relative path, or an absolute path. - - \sa fileName() - */ -void FileAppender::setFileName(const QString &s) -{ - QMutexLocker locker(&m_logFileMutex); - if (m_logFile.isOpen()) - m_logFile.close(); - - m_logFile.setFileName(s); -} - -qint64 FileAppender::size() const -{ - return m_logFile.size(); -} - - -bool FileAppender::openFile() -{ - bool isOpen = m_logFile.isOpen(); - if (!isOpen) { - isOpen = m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); - if (isOpen) - m_logStream.setDevice(&m_logFile); - else - std::cerr << " Cannot open the log file " << qPrintable(m_logFile.fileName()) << std::endl; - } - return isOpen; -} - -/*! - \brief Write the log record to the file. - \reimp - - The \a time parameter indicates the time stamp. - The \a level parameter describes the LogLevel. - The \a file parameter is the current file name. - The \a line parameter indicates the number of lines to output. - The \a func parameter indicates the func name to output. - The \a category parameter indicates the log category. - The \a msg parameter indicates the output message. - - \sa fileName() - \sa AbstractStringAppender::format() - */ -void FileAppender::append(const QDateTime &time, Logger::LogLevel level, const char *file, int line, - const char *func, const QString &category, const QString &msg) -{ - QMutexLocker locker(&m_logFileMutex); - - if (openFile()) - { - m_logStream << formattedString(time, level, file, line, func, category, msg); - m_logStream.flush(); - m_logFile.flush(); - } -} - - -void FileAppender::closeFile() -{ - QMutexLocker locker(&m_logFileMutex); - m_logFile.close(); -} - -DCORE_END_NAMESPACE diff --git a/src/log/LogManager.cpp b/src/log/LogManager.cpp index 6749f72..5ff0c19 100644 --- a/src/log/LogManager.cpp +++ b/src/log/LogManager.cpp @@ -2,44 +2,160 @@ // // SPDX-License-Identifier: LGPL-3.0-or-later +#include #include "LogManager.h" +#include "dconfig.h" +#include #include #include #include +#include +#include "dstandardpaths.h" DCORE_BEGIN_NAMESPACE +#define RULES_KEY ("rules") +// Courtesy qstandardpaths_unix.cpp +static void appendOrganizationAndApp(QString &path) +{ +#ifndef QT_BOOTSTRAPPED + const QString org = QCoreApplication::organizationName(); + if (!org.isEmpty()) + path += QLatin1Char('/') + org; + const QString appName = QCoreApplication::applicationName(); + if (!appName.isEmpty()) + path += QLatin1Char('/') + appName; +#else + Q_UNUSED(path); +#endif +} + +#define DEFAULT_FMT "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}" + +class DLogManagerPrivate { +public: + explicit DLogManagerPrivate(DLogManager *q) + : m_format(DEFAULT_FMT) + , q_ptr(q) + { + } + + DConfig *createDConfig(const QString &appId); + void initLoggingRules(); + void updateLoggingRules(); + + QString m_format; + QString m_logPath; + ConsoleAppender* m_consoleAppender = nullptr; + RollingFileAppender* m_rollingFileAppender = nullptr; + JournalAppender* m_journalAppender = nullptr; + QScopedPointer m_dsgConfig; + QScopedPointer m_fallbackConfig; + + DLogManager *q_ptr = nullptr; + Q_DECLARE_PUBLIC(DLogManager) + +}; + +DConfig *DLogManagerPrivate::createDConfig(const QString &appId) +{ + if (appId.isEmpty()) + return nullptr; + + DConfig *config = DConfig::create(appId, "org.deepin.dtk.preference"); + if (!config->isValid()) { + qWarning() << "Logging rules config is invalid, please check `appId` [" << appId << "]arg is correct"; + delete config; + config = nullptr; + return nullptr; + } + + QObject::connect(config, &DConfig::valueChanged, config, [this](const QString &key) { + if (key != RULES_KEY) + return; + + updateLoggingRules(); + }); + + return config; +} + +void DLogManagerPrivate::initLoggingRules() +{ + if (qEnvironmentVariableIsSet("DTK_DISABLED_LOGGING_RULES")) + return; + + // 1. 未指定 fallbackId 时,以 dsgAppId 为准 + QString dsgAppId = DSGApplication::id(); + m_dsgConfig.reset(createDConfig(dsgAppId)); + + QString fallbackId = qgetenv("DTK_LOGGING_FALLBACK_APPID"); + // 2. fallbackId 和 dsgAppId 非空且不等时,都创建和监听变化 + if (!fallbackId.isEmpty() && fallbackId != dsgAppId) + m_fallbackConfig.reset(createDConfig(fallbackId)); + + // 3. 默认值和非默认值时,非默认值优先 + updateLoggingRules(); +} + +void DLogManagerPrivate::updateLoggingRules() +{ + QVariant var; + // 4. 优先看 dsgConfig 是否默认值,其次 fallback 是否默认值 + if (m_dsgConfig && !m_dsgConfig->isDefaultValue(RULES_KEY)) { + var = m_dsgConfig->value(RULES_KEY); + } else if (m_fallbackConfig && !m_fallbackConfig->isDefaultValue(RULES_KEY)) { + var = m_fallbackConfig->value(RULES_KEY); + } else if (m_dsgConfig) { + var = m_dsgConfig->value(RULES_KEY); + } + + if (var.isValid()) + QLoggingCategory::setFilterRules(var.toString().replace(";", "\n")); +} /*! +@~english \class Dtk::Core::DLogManager \inmodule dtkcore - + \brief DLogManager is the deepin user application log manager. */ DLogManager::DLogManager() + :d_ptr(new DLogManagerPrivate(this)) { -#if !defined(QT_DEBUG) && !defined(QT_MESSAGELOGCONTEXT) - m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] %{message}\n"; -#else - m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n"; -#endif + d_ptr->initLoggingRules(); } void DLogManager::initConsoleAppender(){ - m_consoleAppender = new ConsoleAppender; - m_consoleAppender->setFormat(m_format); - logger->registerAppender(m_consoleAppender); + Q_D(DLogManager); + d->m_consoleAppender = new ConsoleAppender; + d->m_consoleAppender->setFormat(d->m_format); + dlogger->registerAppender(d->m_consoleAppender); } void DLogManager::initRollingFileAppender(){ - m_rollingFileAppender = new RollingFileAppender(getlogFilePath()); - m_rollingFileAppender->setFormat(m_format); - m_rollingFileAppender->setLogFilesLimit(5); - m_rollingFileAppender->setDatePattern(RollingFileAppender::DailyRollover); - logger->registerAppender(m_rollingFileAppender); + Q_D(DLogManager); + d->m_rollingFileAppender = new RollingFileAppender(getlogFilePath()); + d->m_rollingFileAppender->setFormat(d->m_format); + d->m_rollingFileAppender->setLogFilesLimit(5); + d->m_rollingFileAppender->setDatePattern(RollingFileAppender::DailyRollover); + dlogger->registerAppender(d->m_rollingFileAppender); +} + +void DLogManager::initJournalAppender() +{ +#if (defined BUILD_WITH_SYSTEMD && defined Q_OS_LINUX) + Q_D(DLogManager); + d->m_journalAppender = new JournalAppender(); + dlogger->registerAppender(d->m_journalAppender); +#else + qWarning() << "BUILD_WITH_SYSTEMD not defined or OS not support!!"; +#endif } /*! +@~english \brief Registers the appender to write the log records to the Console. \sa registerFileAppender @@ -49,6 +165,7 @@ void DLogManager::registerConsoleAppender(){ } /*! +@~english \brief Registers the appender to write the log records to the file. \sa getlogFilePath @@ -58,40 +175,47 @@ void DLogManager::registerFileAppender() { DLogManager::instance()->initRollingFileAppender(); } +void DLogManager::registerJournalAppender() +{ + DLogManager::instance()->initJournalAppender(); +} + /*! +@~english \brief Return the path file log storage. - \brief DLogManager::getlogFilePath 获取日志文件路径 - \brief 默认日志路径是 ~/.cache/organizationName/applicationName.log - \brief 如果获取 HOME 环境变量失败将不写日志 + \brief DLogManager::getlogFilePath Get the log file path + \brief The default log path is ~/.cache//.log + \brief If the environment variable $HOME cannot be acquired, DLogManager will not log anything \sa registerFileAppender */ QString DLogManager::getlogFilePath() { - // 不再构造时去设置默认logpath(且mkdir), 而在getlogPath时再去判断是否设置默认值 - // 修复设置了日志路径还是会在默认的位置创建目录的问题 - if (DLogManager::instance()->m_logPath.isEmpty()) { - if (QDir::homePath() == QDir::rootPath()) { - qWarning() << "unable to locate the cache directory." - << "logfile path is empty, the log will not be written.\r\n" - << (qgetenv("HOME").isEmpty() ? "the HOME environment variable not set" : ""); + //No longer set the default log path (and mkdir) when constructing now, instead set the default value if it's empty when getlogFilePath is called. + //Fix the problem that the log file is still created in the default path when the log path is set manually. + if (DLogManager::instance()->d_func()->m_logPath.isEmpty()) { + if (DStandardPaths::homePath().isEmpty()) { + qWarning() << "Unable to locate the cache directory, cannot acquire home directory, and the log will not be written to file.."; return QString(); } - QString cachePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).at(0); + QString cachePath(DStandardPaths::path(DStandardPaths::XDG::CacheHome)); + appendOrganizationAndApp(cachePath); + if (!QDir(cachePath).exists()) { QDir(cachePath).mkpath(cachePath); } - DLogManager::instance()->m_logPath = DLogManager::instance()->joinPath(cachePath, QString("%1.log").arg(qApp->applicationName())); + instance()->d_func()->m_logPath = instance()->joinPath(cachePath, QString("%1.log").arg(qApp->applicationName())); } - return QDir::toNativeSeparators(DLogManager::instance()->m_logPath); + return QDir::toNativeSeparators(DLogManager::instance()->d_func()->m_logPath); } /*! - \brief DLogManager::setlogFilePath 设置日志文件路径 - \a logFilePath 日志文件路径 - \brief 如果设置的文件路进不是文件路径将什么都不做,输出一条警告 +@~english + \brief DLogManager::setlogFilePath Set the log file path + \a logFilePath Log file path + \brief If the file path set is not the file path, nothing will do, and an output warning */ void DLogManager::setlogFilePath(const QString &logFilePath) { @@ -99,13 +223,13 @@ void DLogManager::setlogFilePath(const QString &logFilePath) if (info.exists() && !info.isFile()) qWarning() << "invalid file path:" << logFilePath << " is not a file"; else - DLogManager::instance()->m_logPath = logFilePath; + DLogManager::instance()->d_func()->m_logPath = logFilePath; } void DLogManager::setLogFormat(const QString &format) { //m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n"; - DLogManager::instance()->m_format = format; + DLogManager::instance()->d_func()->m_format = format; } QString DLogManager::joinPath(const QString &path, const QString &fileName){ @@ -115,7 +239,6 @@ QString DLogManager::joinPath(const QString &path, const QString &fileName){ DLogManager::~DLogManager() { - } DCORE_END_NAMESPACE diff --git a/src/log/Logger.cpp b/src/log/Logger.cpp deleted file mode 100644 index 5529760..0000000 --- a/src/log/Logger.cpp +++ /dev/null @@ -1,1050 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "Logger.h" -#include "AbstractAppender.h" -#include "AbstractStringAppender.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -DCORE_BEGIN_NAMESPACE - -/*! - \headerfile - \inmodule dtkcore - \brief A file containing the description of Logger class and and additional useful macros for logging. - */ - -/*! - \macro Dtk::Core::logger - \relates Dtk::Core::Logger - \keyword Dtk::Core::logger - - \brief Macro returning the current instance of Logger object - - If you haven't created a local Logger object it returns the same value as the Logger::globalInstance() functions. - This macro is a recommended way to get an access to the Logger instance used in current class. - - Example: - \code - ConsoleAppender* consoleAppender = new ConsoleAppender; - logger->registerAppender(consoleAppender); - \endcode - - \sa Dtk::Core::Logger::globalInstance() - */ - -/*! - \macro Dtk::Core::dTrace - \relates Dtk::Core::Logger - \keyword Dtk::Core::dTrace - - \brief Writes the trace log record - - This macro is the convenient way to call Logger::write(). It uses the common preprocessor macros \c __FILE__, - \c __LINE__ and the standard Qt \c Q_FUNC_INFO macros to automatically determine the needed parameters to call - Logger::write(). - - \note This and other (dInfo() etc...) macros uses the variadic macro arguments to give convenient usage form for - the different versions of Logger::write() (using the QString or const char *argument or returning the QDebug class - instance). Not all compilers will support this. Please, consider reviewing your compiler documentation to ensure - it support __VA_ARGS__ macro. - - \sa Dtk::Core::dInfo Dtk::Core::dDebug Dtk::Core::dWarning Dtk::Core::dError - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dDebug - \relates Dtk::Core::Logger - \keyword Dtk::Core::dDebug - - \brief Writes the debug log record - - This macro records the debug log record using the Logger::write() function. It works similar to the dTrace() - macro. - - \sa Dtk::Core::dTrace Dtk::Core::dInfo Dtk::Core::dWarning Dtk::Core::dError - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dInfo - \relates Dtk::Core::Logger - \keyword Dtk::Core::dInfo - - \brief Writes the info log record - - This macro records the info log record using the Logger::write() function. It works similar to the dTrace() - macro. - - \sa Dtk::Core::dTrace Dtk::Core::dDebug Dtk::Core::dWarning Dtk::Core::dError - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dWarning - \relates Dtk::Core::Logger - \keyword Dtk::Core::dWarning - - \brief Write the warning log record - - This macro records the warning log record using the Logger::write() function. It works similar to the dTrace() - macro. - - \sa Dtk::Core::dTrace Dtk::Core::dInfo Dtk::Core::dDebug Dtk::Core::dError - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dError - \relates Dtk::Core::Logger - \keyword Dtk::Core::dError - - \brief Write the error log record - This macro records the error log record using the Logger::write() function. It works similar to the dTrace() - macro. - - \sa Dtk::Core::dTrace - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dFatal - \relates Dtk::Core::Logger - \keyword Dtk::Core::dFatal - - \brief Write the fatal log record - - This macro records the fatal log record using the Logger::write() function. It works similar to the dTrace() - macro. - - \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort() - function, which will interrupt the running of your software and begin the writing of the core dump. - - \sa Dtk::Core::dTrace - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dCTrace(category) - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCTrace() - - \brief Writes the trace log record to the specific category - - This macro is the similar to the dTrace() macro, but has a category parameter - to write only to the category appenders (registered using Logger::registerCategoryAppender() method). - - \a category category name string - - \sa Dtk::Core::dTrace - \sa Dtk::Core::Logger::LogLevel - \sa Dtk::Core::Logger::registerCategoryAppender() - \sa Dtk::Core::Logger::write() - \sa Dtk::Core::dCategory(), Dtk::Core::dGlobalCategory() - */ - - -/*! - \macro Dtk::Core::dCDebug - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCDebug - - \brief Writes the debug log record to the specific category - - This macro records the debug log record using the Logger::write() function. It works similar to the dCTrace() - macro. - - \sa Dtk::Core::dCTrace() - */ - -/*! - \macro Dtk::Core::dCInfo - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCInfo - - \brief Writes the info log record to the specific category - - This macro records the info log record using the Logger::write() function. It works similar to the dCTrace() - macro. - - \sa Dtk::Core::dCTrace() - */ - -/*! - \macro Dtk::Core::dCWarning - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCWarning - - \brief Writes the warning log record to the specific category - - This macro records the warning log record using the Logger::write() function. It works similar to the dCTrace() - macro. - - \sa Dtk::Core::dCTrace() - */ - -/*! - \macro Dtk::Core::dCError - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCError - - \brief Writes the error log record to the specific category - - This macro records the error log record using the Logger::write() function. It works similar to the dCTrace() - macro. - - \sa Dtk::Core::dCTrace() - */ - -/*! - \macro Dtk::Core::dCFatal - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCFatal - - \brief Write the fatal log record to the specific category - - This macro records the fatal log record using the Logger::write() function. It works similar to the dCTrace() - macro. - - \note Recording of the log record using the Logger::Fatal log level will lead to calling the STL abort() - function, which will interrupt the running of your software and begin the writing of the core dump. - - \sa Dtk::Core::dCTrace() - */ - -/*! - \macro Dtk::Core::dCategory(category) - \relates Dtk::Core::Logger - \keyword Dtk::Core::dCategory() - - \brief Create logger instance inside your custom class to log all messages to the specified \a category - - This macro is used to pass all log messages inside your custom class to the specific \a category. - You must include this macro inside your class declaration (similarly to the Q_OBJECT macro). - Internally, this macro redefines loggerInstance() function, creates the local Logger object inside your class and - sets the default category to the specified parameter. - - Thus, any call to loggerInstance() (for example, inside dTrace() macro) will return the local Logger object, - so any logging message will be directed to the default category. - - \note This macro does not register any appender to the newly created logger instance. You should register - logger appenders manually, inside your class. - - Usage example: - \code - class CustomClass : public QObject - { - Q_OBJECT - dCategory("custom_category") - ... - }; - - CustomClass::CustomClass(QObject* parent) : QObject(parent) - { - logger->registerAppender(new FileAppender("custom_category_log")); - dTrace() << "Trace to the custom category log"; - } - \endcode - - \sa Dtk::Core::Logger::write() - \sa Dtk::Core::dTrace() - \sa Dtk::Core::Logger::registerCategoryAppender() - \sa Dtk::Core::Logger::setDefaultCategory() - */ - -/*! - \macro Dtk::Core::dGlobalCategory(category) - \relates Dtk::Core::Logger - \keyword Dtk::Core::dGlobalCategory() - - \brief Create logger instance inside your custom class to log all messages both to the specified \a category and to - the global logger instance. - - This macro is similar to dCategory(), but also passes all log messages to the global logger instance appenders. - It is equal to defining the local \a category logger using dCategory macro and calling: - \code - logger->logToGlobalInstance(logger->defaultCategory(), true); - \endcode - - \sa Dtk::Core::dCategory - \sa Dtk::Core::Logger::logToGlobalInstance() - \sa Dtk::Core::Logger::defaultCategory() - \sa Dtk::Core::Logger::registerCategoryAppender() - \sa Dtk::Core::Logger::write() - */ - -/*! - \macro Dtk::Core::dAssert - \relates Dtk::Core::Logger - \keyword Dtk::Core::dAssert - - \brief Check the assertion - - This macro is a convenient and recommended to use way to call Logger::writeAssert() function. It uses the - preprocessor macros (as the dDebug() does) to fill the necessary arguments of the Logger::writeAssert() call. It - also uses undocumented but rather mature and stable \c qt_noop() function (which does nothing) when the assertion - is true. - - Example: - \code - bool b = checkSomething(); - ... - dAssert(b == true); - \endcode - - \sa Dtk::Core::Logger::writeAssert() - */ - -/*! - \macro Dtk::Core::dTraceTime - \relates Dtk::Core::Logger - \keyword Dtk::Core::dTraceTime - - \brief Logs the processing time of current function / code block - - This macro automagically measures the function or code of block execution time and outputs it as a Logger::Trace - level log record. - - Example: - \code - int foo() - { - dTraceTime(); - ... // Do some long operations - return 0; - } // Outputs: Function foo finished in
    ()); - ASSERT_TRUE(a->test(4)); + ASSERT_EQ(a->test(4), 'b'); delete a; delete b; } @@ -148,7 +119,7 @@ TEST_F(ut_DVtableHook, fun2Fun) { ASSERT_TRUE(DVtableHook::overrideVfptrFun(&A::test, &test)); A *a = new A(); - ASSERT_TRUE(a->test(5)); + ASSERT_EQ(a->test(5), 'x'); delete a; } @@ -156,7 +127,7 @@ TEST_F(ut_DVtableHook, fun2StdFun) { A *a = new A(); ASSERT_TRUE(DVtableHook::overrideVfptrFun(&A::test, std::bind(&test2, std::placeholders::_1, std::placeholders::_2, true))); - ASSERT_TRUE(a->test(6)); + ASSERT_EQ(a->test(6), 'y'); DVtableHook::resetVtable(a); ASSERT_TRUE(!DVtableHook::hasVtable(a)); delete a; @@ -165,13 +136,27 @@ TEST_F(ut_DVtableHook, fun2StdFun) TEST_F(ut_DVtableHook, fun2LambdaFun) { A *a = new A(); - auto lambda = [a](A *obj, int v) { + auto lambda = [](A *obj, int v) { qDebug() << Q_FUNC_INFO << obj << v; - return a == obj; + return 'z'; }; ASSERT_TRUE(DVtableHook::overrideVfptrFun(&A::test, lambda)); - ASSERT_TRUE(a->test(7)); + ASSERT_EQ(a->test(7), 'z'); DVtableHook::resetVtable(a); ASSERT_TRUE(!DVtableHook::hasVtable(a)); delete a; } + +TEST_F(ut_DVtableHook, testRTTI) +{ + A *c1 = new C(); + auto original = typeid(*c1).name(); + auto lambda3 = [](C *obj, int v) { + qDebug() << Q_FUNC_INFO << obj << v; + return '3'; + }; + ASSERT_TRUE(DVtableHook::overrideVfptrFun(dynamic_cast(c1), &C::test, lambda3)); + ASSERT_EQ(c1->test(0), '3'); + ASSERT_EQ(typeid(*c1).name(), original); + delete c1; +} diff --git a/tests/ut_gsettingsbackend.cpp b/tests/ut_gsettingsbackend.cpp index 101b6b7..d3f4f92 100644 --- a/tests/ut_gsettingsbackend.cpp +++ b/tests/ut_gsettingsbackend.cpp @@ -27,6 +27,7 @@ protected: void ut_GSettings::SetUp() { + GTEST_SKIP_("Do not test GSettingsBackend. schema was removed..."); QFile file("/tmp/test.json"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; diff --git a/tests/ut_logger.cpp b/tests/ut_logger.cpp deleted file mode 100644 index 7ce3a70..0000000 --- a/tests/ut_logger.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include -#include -#include -#include "log/Logger.h" -#include "log/FileAppender.h" -#include "log/ConsoleAppender.h" -#include "log/RollingFileAppender.h" - -DCORE_USE_NAMESPACE - -class ut_Logger: public testing::Test -{ -protected: - void SetUp() override; - void TearDown() override; - Logger *m_logger = nullptr; -}; - -void ut_Logger::SetUp() -{ - m_logger = new Logger; - QFile file("/tmp/log"); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - return; - file.close(); - QFile rollFile("/tmp/rollLog"); - if (!rollFile.open(QIODevice::WriteOnly | QIODevice::Text)) - return; - rollFile.close(); -} - -void ut_Logger::TearDown() -{ - if (m_logger) { - delete m_logger; - m_logger = nullptr; - } - QFile file("/tmp/log"); - if (file.exists()) - file.remove(); - QFile rollFile("/tmp/rollLog"); - if (rollFile.exists()) - rollFile.remove(); -} - -TEST_F(ut_Logger, testLevelToString) -{ - QString trace = Logger::levelToString(Logger::Trace); - ASSERT_EQ(trace, "Trace"); - QString debug = Logger::levelToString(Logger::Debug); - ASSERT_EQ(debug, "Debug"); - QString info = Logger::levelToString(Logger::Info); - ASSERT_EQ(info, "Info"); - QString warning = Logger::levelToString(Logger::Warning); - ASSERT_EQ(warning, "Warning"); - QString error = Logger::levelToString(Logger::Error); - ASSERT_EQ(error, "Error"); - QString fatal = Logger::levelToString(Logger::Fatal); - ASSERT_EQ(fatal, "Fatal"); -} - -TEST_F(ut_Logger, testLevelFromString) -{ - Logger::LogLevel trace = Logger::levelFromString("Trace"); - ASSERT_EQ(trace, Logger::Trace); - Logger::LogLevel debug = Logger::levelFromString("Debug"); - ASSERT_EQ(debug, Logger::Debug); - Logger::LogLevel info = Logger::levelFromString("Info"); - ASSERT_EQ(info, Logger::Info); - Logger::LogLevel warning = Logger::levelFromString("Warning"); - ASSERT_EQ(warning, Logger::Warning); - Logger::LogLevel error = Logger::levelFromString("Error"); - ASSERT_EQ(error, Logger::Error); - Logger::LogLevel fatal = Logger::levelFromString("Fatal"); - ASSERT_EQ(fatal, Logger::Fatal); -} - -TEST_F(ut_Logger, testGlobalInstance) -{ - ASSERT_TRUE(Logger::globalInstance()); -} - -TEST_F(ut_Logger, testRegisterAppender) -{ - Logger* gLogger = Logger::globalInstance(); - - FileAppender *fileAppener = new FileAppender("/tmp/log"); - if (fileAppener->detailsLevel() > Logger::Trace) - fileAppener->setDetailsLevel(Logger::Trace); - gLogger->registerAppender(fileAppener); - ASSERT_TRUE(fileAppener->size() == 0); - dTrace("testRegisterAppender"); - ASSERT_TRUE(fileAppener->size() != 0); - - ConsoleAppender *consoleAppener = new ConsoleAppender(); - if (consoleAppener->detailsLevel() > Logger::Trace) - consoleAppener->setDetailsLevel(Logger::Trace); - gLogger->registerAppender(consoleAppener); - consoleAppener->ignoreEnvironmentPattern(false); - QString format = consoleAppener->format(); - consoleAppener->setFormat("[%{file}: %{line} %{type:-7}] <%{function}> %{message}\n"); - dTrace("testRegisterAppender"); - - RollingFileAppender *rollingFileAppender = new RollingFileAppender("/tmp/rollLog"); - if (rollingFileAppender->detailsLevel() > Logger::Trace) - rollingFileAppender->setDetailsLevel(Logger::Trace); - gLogger->registerAppender(rollingFileAppender); - rollingFileAppender->setDatePattern("'.'yyyy-MM-dd-hh-mm"); - ASSERT_TRUE(rollingFileAppender->datePatternString() == "'.'yyyy-MM-dd-hh-mm"); - rollingFileAppender->setLogFilesLimit(2); - ASSERT_TRUE(rollingFileAppender->logFilesLimit() == 2); - rollingFileAppender->setDatePattern(RollingFileAppender::MinutelyRollover); - ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::MinutelyRollover); - dTrace("testRegisterAppender"); - rollingFileAppender->setDatePattern(RollingFileAppender::HourlyRollover); - ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::HourlyRollover); - dTrace("testRegisterAppender"); - rollingFileAppender->setDatePattern(RollingFileAppender::HalfDailyRollover); - ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::HalfDailyRollover); - dTrace("testRegisterAppender"); -} - -TEST_F(ut_Logger, testRegisterCategoryAppender) -{ - Logger* gLogger = Logger::globalInstance(); - FileAppender *fileAppener = new FileAppender("/tmp/log"); - if (fileAppener->detailsLevel() > Logger::Trace) - fileAppener->setDetailsLevel(Logger::Trace); - gLogger->registerCategoryAppender("test", fileAppener); - ASSERT_TRUE(fileAppener->size() == 0); - dCDebug("test") << "testRegisterAppender"; - ASSERT_TRUE(fileAppener->size() != 0); -} - -TEST_F(ut_Logger, testLogToGlobalInstance) -{ - Logger* gLogger = Logger::globalInstance(); - FileAppender *fileAppener = new FileAppender("/tmp/log"); - if (fileAppener->detailsLevel() > Logger::Trace) - fileAppener->setDetailsLevel(Logger::Trace); - gLogger->registerAppender(fileAppener); - m_logger->logToGlobalInstance("test", true); - - ASSERT_TRUE(fileAppener->size() == 0); - dTrace("testRegisterAppender"); - ASSERT_TRUE(fileAppener->size() != 0); -} - -TEST_F(ut_Logger, testSetDefaultCategory) -{ - m_logger->setDefaultCategory("test"); - ASSERT_EQ(m_logger->defaultCategory(), "test"); -} - -TEST_F(ut_Logger, testDefaultCategory) -{ - ASSERT_EQ(m_logger->defaultCategory(), ""); -} diff --git a/tests/ut_singleton.cpp b/tests/ut_singleton.cpp index 76687dd..a8c34eb 100644 --- a/tests/ut_singleton.cpp +++ b/tests/ut_singleton.cpp @@ -3,6 +3,9 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "ut_singleton.h" +#include +#include +#include Singleton::Singleton(QObject *parent) : QObject(parent), @@ -17,10 +20,53 @@ MultiSingletonTester::MultiSingletonTester(QObject *parent) void MultiSingletonTester::run() { - Singleton::instance()->count.ref(); + Singleton::ref().count.ref(); } int MultiSingletonTester::count() const { - return Singleton::instance()->count.load(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return Singleton::ref().count.loadRelaxed(); +#else + return Singleton::ref().count.load(); +#endif +} + +TEST(ut_DSingleton, testDSingleton) +{ + const int exampleCount = 5; + QVector threads; + QVector testers; + threads.reserve(exampleCount); + testers.reserve(exampleCount); + for (int i = 0; i < exampleCount; i++) { + auto thread = new QThread(); + auto tester = new MultiSingletonTester; + tester->moveToThread(thread); + QObject::connect(thread, &QThread::started, tester, &MultiSingletonTester::run); + + threads.push_back(thread); + testers.push_back(tester); + thread->start(); + } + + for (auto thread : threads) { + thread->quit(); + } + + ASSERT_TRUE(QTest::qWaitFor([threads] { + for (auto thread : threads) { + if (!thread->isFinished()) { + return false; + } + } + return true; + })); + + for (auto tester : testers) { + ASSERT_EQ(tester->count(), exampleCount); + } + + qDeleteAll(threads); + qDeleteAll(testers); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 23c8d02..f3ef2a5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(dci) add_subdirectory(deepin-os-release) add_subdirectory(qdbusxml2cpp) add_subdirectory(settings) +add_subdirectory(ch2py) diff --git a/tools/ch2py/CMakeLists.txt b/tools/ch2py/CMakeLists.txt new file mode 100644 index 0000000..599d180 --- /dev/null +++ b/tools/ch2py/CMakeLists.txt @@ -0,0 +1,21 @@ +set(TARGET_NAME ch2py) +set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) + +set(CMAKE_AUTORCC ON) +add_executable(${BIN_NAME} + ${PROJECT_SOURCE_DIR}/src/util/dpinyin.cpp + ${PROJECT_SOURCE_DIR}/src/util/util.qrc + main.cpp +) +target_link_libraries(${BIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::Core +) +target_include_directories(${BIN_NAME} PRIVATE + ${PROJECT_SOURCE_DIR}/include/util + ${PROJECT_SOURCE_DIR}/include/global +) +set_target_properties(${BIN_NAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME}) +install(TARGETS ${BIN_NAME} DESTINATION "${TOOL_INSTALL_DIR}") diff --git a/tools/ch2py/main.cpp b/tools/ch2py/main.cpp new file mode 100644 index 0000000..74e3535 --- /dev/null +++ b/tools/ch2py/main.cpp @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include +#include +#include + +#include "dpinyin.h" + +DCORE_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication a(argc, argv); + a.setOrganizationName("deepin"); + a.setApplicationName("ch2py"); + a.setApplicationVersion("0.0.1"); + + QCommandLineParser cp; + cp.setApplicationDescription("ch2py tool is a command tool that convert Chinese words to Pinyin.\n" + "The commands of DCI tools can be expressed as follows:\n" + "\t ch2py [chinese words]\n" + "\t ch2py --tonestyle notones [chinese words]\n" + "\t ch2py --letters [chinese words]\n" + ); + + + QCommandLineOption tonestyle = QCommandLineOption(QStringList() << "s" << "tonestyle", + "tone style value can be \"notones\",\"tones\",\"numtones\"", + "tonestyle", + "tones"); + QCommandLineOption letters = QCommandLineOption(QStringList() << "l" << "letters", + "convert Chinese words to Pinyin first letters"); + cp.addOption(tonestyle); + cp.addOption(letters); + cp.addPositionalArgument("words", "words to be converted to pinyin"); + cp.addHelpOption(); + + cp.process(a); + + QString words = cp.positionalArguments().join(" "); + + if (words.isEmpty()) { + cp.showHelp(); + } + + QString tones = cp.value("tonestyle"); + + ToneStyle ts = TS_Tone; + if (!tones.compare("notones")) + ts = TS_NoneTone; + else if (!tones.compare("numtones")) + ts = TS_ToneNum; + + QElapsedTimer timer; + timer.start(); + + qint64 size = -1; + if (cp.isSet(letters)) { + const auto &ls = firstLetters(words); + printf("%s\n", qPrintable(ls.join("\n"))); + size = ls.size(); + } else { + const auto &py = pinyin(words, ts); + printf("%s\n", qPrintable(py.join("\n"))); + size = py.size(); + } + + std:: cout << "Total size: " << size << ", time:" << timer.elapsed() << " ms" << std::endl; + return 0; +} diff --git a/tools/dci/CMakeLists.txt b/tools/dci/CMakeLists.txt index c35c9ed..652066e 100644 --- a/tools/dci/CMakeLists.txt +++ b/tools/dci/CMakeLists.txt @@ -1,6 +1,8 @@ -set(BIN_NAME dci) +set(TARGET_NAME dci) +set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -find_package(Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) add_definitions(-DDTK_NO_PROJECT) # start dci include(../../src/dci/dci.cmake) @@ -9,14 +11,17 @@ add_executable(${BIN_NAME} main.cpp ) target_link_libraries(${BIN_NAME} PRIVATE - Qt5::Core + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::CorePrivate ) target_include_directories(${BIN_NAME} PUBLIC - ${Qt5Core_PRIVATE_INCLUDE_DIRS} ../../include/ ../../include/dci/ ../../include/DtkCore/ ../../include/base/ ../../include/global/ ) +set_target_properties(${BIN_NAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME}) #end dci + +install(TARGETS ${BIN_NAME} DESTINATION "${TOOL_INSTALL_DIR}") diff --git a/tools/dci/dci.pro b/tools/dci/dci.pro deleted file mode 100644 index 934d632..0000000 --- a/tools/dci/dci.pro +++ /dev/null @@ -1,23 +0,0 @@ -QT -= gui - -CONFIG += c++11 console -CONFIG -= app_bundle - -# You can make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -DEFINES += DTK_NO_PROJECT - -# 支持从当前目录找到动态库 -mac { - QMAKE_RPATHDIR = "@executable_path" -} - -SOURCES += \ - main.cpp - -include($$PWD/../../src/dci/dci.pri) -INCLUDEPATH += $$PWD/../../src - -#不要依赖于 dtk 的其它任何文件,要确保能在 macox 上独立编译 diff --git a/tools/dci/main.cpp b/tools/dci/main.cpp index d336f13..0bf8225 100644 --- a/tools/dci/main.cpp +++ b/tools/dci/main.cpp @@ -81,16 +81,17 @@ bool createTo(const QString &sourceDir, const QString &targetDir) { return dci.writeToFile(newFile); } -static bool copyFilesFromDci(const DDciFile *dci, const QString &targetDir, const QString &sourceDir) { +static bool copyFilesFromDci(const DDciFile *dci, const QString &targetDir, const QString &sourceDir, QMap &pathMap) { QDir target(targetDir); for (const QString &file : dci->list(sourceDir)) { const QString &newFileName = QFileInfo(file).fileName(); const QString &newFilePath = target.filePath(newFileName); + pathMap.insert(file, newFilePath); const auto &type = dci->type(file); if (type == DDciFile::Directory) { if (!target.mkdir(newFileName)) return false; - if (!copyFilesFromDci(dci, newFilePath, file)) + if (!copyFilesFromDci(dci, newFilePath, file, pathMap)) return false; } else if (type == DDciFile::File) { QFile newFile(newFilePath); @@ -100,8 +101,7 @@ static bool copyFilesFromDci(const DDciFile *dci, const QString &targetDir, cons if (newFile.write(data) != data.size()) return false; } else if (type == DDciFile::Symlink) { - if (!QFile::link(dci->symlinkTarget(file, true), newFilePath)) - return false; + // link the real source later } else { return false; } @@ -124,7 +124,78 @@ bool exportTo(const QString &dciFile, const QString &targetDir) { if (!dci.isValid()) return false; - return copyFilesFromDci(&dci, newDir, "/"); + QMap pathMap; + if (!copyFilesFromDci(&dci, QDir(newDir).absolutePath(), "/", pathMap)) + return false; + + // link to real source + for (auto it = pathMap.begin(); it != pathMap.end(); it++) { + if (dci.type(it.key()) == DDciFile::Symlink) { + const QString &realSource = it.value(); + const QDir &dirInDci(QFileInfo(it.key()).path()); + const QDir &dirRealSrc(QFileInfo(realSource).path()); + const QString &target = dci.symlinkTarget(it.key(), true); + const QString &absoluteTarget = QDir::cleanPath(dirInDci.absoluteFilePath(target)); + const QString &realTarget = pathMap.value(absoluteTarget); + + // link to relative path(e.g. xx.webp -> ../../normal.light/x/xx.webp) + if (!QFile::link(dirRealSrc.relativeFilePath(realTarget), realSource)) { + qErrnoWarning(strerror(errno)); + return false; + } + } + } + return true; +} + +#define SPACE_CHAR " " +#define BEGINE_CHAR "├── " +#define MIDDLE_CHAR "│ " +#define END_CHAR "└── " +#define ARROW_CHAR " -> " + +static inline QString pathName(const QString &path) +{ + QDir dir(path); + return dir.dirName().isEmpty() ? path : dir.dirName(); +} + +void print(DDciFile &dci, const QString &dir = QString("/"), QString prefix = QString()) +{ + const auto &fileList = dci.list(dir); + QString dirName = pathName(dir); + + printf("%s\n", qPrintable(prefix + dirName)); + + prefix.replace(END_CHAR, SPACE_CHAR); + prefix.replace(BEGINE_CHAR, MIDDLE_CHAR); + + for (const auto &file : fileList) { + QString newPrefix = prefix; + newPrefix.append(file == fileList.last() ? END_CHAR : BEGINE_CHAR); + if (dci.type(file) == DDciFile::Directory) { + print(dci, file, newPrefix); + } else { + QString fileName = pathName(file); + QString symlinkTarget; + if (dci.type(file) == DDciFile::Symlink) { + symlinkTarget.append(ARROW_CHAR).append(dci.symlinkTarget(file)); + } + printf("%s\n", qPrintable(newPrefix + fileName + symlinkTarget)); + } + } +} + +bool tree(const QString &dciFile) +{ + QFileInfo info(dciFile); + DDciFile dci(dciFile); + if (!dci.isValid()) + return false; + + print(dci, "/"); + + return true; } int main(int argc, char *argv[]) @@ -142,13 +213,17 @@ int main(int argc, char *argv[]) "The commands of DCI tools can be expressed as follows:\n" "\t dci --create [target file path] [source directory path]\n" "\t dci --export [target directory path] [source file path]\n" + "\t dci --tree [target file path]\n" "For example, the tool is used in the following ways: \n" "\t dci --create ~/Desktop ~/Desktop/action_add\n" - "\t dci --export ~/Desktop ~/Desktop/action_add.dci\n"); + "\t dci --export ~/Desktop ~/Desktop/action_add.dci\n" + "\t dci --tree ~/Desktop/action_add.dci\n"); - auto options = QList { + auto options = QList + { QCommandLineOption("create", "Create the new dci files by the directorys", "targetDirectiry"), QCommandLineOption("export", "Export the dci files to the directorys", "targetDirectory"), + QCommandLineOption("tree", "tree view the dci file", "targetDciFile"), }; commandParser.addOptions(options); commandParser.addPositionalArgument("sources", "The directorys of create or the dci files of export", @@ -169,6 +244,11 @@ int main(int argc, char *argv[]) printf("Failed on export the \"%s\" dci file\n", qPrintable(dci)); } } + } else if (commandParser.isSet(options.at(2))) { + const QString &dci = commandParser.value(options.at(2)); + if (!tree(dci)) { + printf("Failed on view the \"%s\" dci file\n", qPrintable(dci)); + } } else { commandParser.showHelp(-1); } diff --git a/tools/deepin-os-release/CMakeLists.txt b/tools/deepin-os-release/CMakeLists.txt index 25cb0e8..9a13828 100644 --- a/tools/deepin-os-release/CMakeLists.txt +++ b/tools/deepin-os-release/CMakeLists.txt @@ -1,7 +1,9 @@ -set(BIN_NAME deepin-os-release) +set(TARGET_NAME deepin-os-release) +set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_AUTOMOC ON) -find_package(Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) add_definitions(-DDTK_NO_PROJECT) # start dci set(dci_SRCS @@ -14,17 +16,22 @@ add_executable(${BIN_NAME} ${dci_SRCS} main.cpp ) + +target_compile_definitions(${BIN_NAME} PUBLIC + DSYSINFO_PREFIX="${DSYSINFO_PREFIX}") + target_link_libraries(${BIN_NAME} PRIVATE - Qt5::Core + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::CorePrivate ) target_include_directories(${BIN_NAME} PUBLIC - ${Qt5Core_PRIVATE_INCLUDE_DIRS} ../../include/ ../../include/dci/ ../../include/DtkCore/ ../../include/base/ ../../include/global/ ) +set_target_properties(${BIN_NAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME}) install(TARGETS ${BIN_NAME} DESTINATION "${TOOL_INSTALL_DIR}") #end dci diff --git a/tools/deepin-os-release/deepin-os-release.pro b/tools/deepin-os-release/deepin-os-release.pro deleted file mode 100644 index d271388..0000000 --- a/tools/deepin-os-release/deepin-os-release.pro +++ /dev/null @@ -1,20 +0,0 @@ -QT -= gui -TEMPLATE = app -CONFIG += qt - -HEADERS += ../../src/dsysinfo.h \ - ../../src/ddesktopentry.h - -SOURCES += \ - main.cpp \ - ../../src/dsysinfo.cpp \ - ../../src/ddesktopentry.cpp - -INCLUDEPATH += ../../src -DESTDIR = $$_PRO_FILE_PWD_/../../bin - -DTK_MODULE_NAME=dtkcore -load(dtk_build_config) -target.path = $$TOOL_INSTALL_DIR - -INSTALLS += target diff --git a/tools/deepin-os-release/main.cpp b/tools/deepin-os-release/main.cpp index a7d0614..bdc0e48 100644 --- a/tools/deepin-os-release/main.cpp +++ b/tools/deepin-os-release/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) parser.addVersionOption(); parser.process(app); + if (argc < 2) + parser.showHelp(); + if (parser.isSet(option_all)) { printf("Computer Name: %s\n", qPrintable(DSysInfo::computerName())); printf("CPU Model: %s x %d\n", qPrintable(DSysInfo::cpuModelName()), QThread::idealThreadCount()); @@ -61,7 +64,7 @@ int main(int argc, char *argv[]) printf("Memory Size: %f GiB\n", DSysInfo::memoryTotalSize() / 1024.0 / 1024 / 1024); printf("Disk Size: %f GiB\n", DSysInfo::systemDiskSize() / 1024.0 / 1024 / 1024); - if (DSysInfo::isDDE()) { + if (DSysInfo::isDeepin() && DSysInfo::isDDE()) { printf("Deepin Type: %s\n", qPrintable(DSysInfo::deepinTypeDisplayName())); printf("Deepin Version: %s\n", qPrintable(DSysInfo::deepinVersion())); @@ -76,15 +79,16 @@ int main(int argc, char *argv[]) printf("Product Type: %s\n", qPrintable(DSysInfo::productTypeString())); printf("Product Version: %s\n", qPrintable(DSysInfo::productVersion())); - printf("Uos Product Name: %s\n", qPrintable(DSysInfo::uosProductTypeName())); - printf("Uos SystemName Name: %s\n", qPrintable(DSysInfo::uosSystemName())); - printf("Uos Edition Name: %s\n", qPrintable(DSysInfo::uosEditionName())); - printf("Uos SP Version: %s\n", qPrintable(DSysInfo::spVersion())); - printf("Uos update Version: %s\n", qPrintable(DSysInfo::udpateVersion())); - printf("Uos major Version: %s\n", qPrintable(DSysInfo::majorVersion())); - printf("Uos minor Version: %s\n", qPrintable(DSysInfo::minorVersion())); - printf("Uos build Version: %s\n", qPrintable(DSysInfo::buildVersion())); - + if (DSysInfo::isDeepin()) { + printf("Uos Product Name: %s\n", qPrintable(DSysInfo::uosProductTypeName())); + printf("Uos SystemName Name: %s\n", qPrintable(DSysInfo::uosSystemName())); + printf("Uos Edition Name: %s\n", qPrintable(DSysInfo::uosEditionName())); + printf("Uos SP Version: %s\n", qPrintable(DSysInfo::spVersion())); + printf("Uos update Version: %s\n", qPrintable(DSysInfo::udpateVersion())); + printf("Uos major Version: %s\n", qPrintable(DSysInfo::majorVersion())); + printf("Uos minor Version: %s\n", qPrintable(DSysInfo::minorVersion())); + printf("Uos build Version: %s\n", qPrintable(DSysInfo::buildVersion())); + } if (distributionInfoValid()) { printDistributionOrgInfo(DSysInfo::Distribution); printDistributionOrgInfo(DSysInfo::Distributor); diff --git a/tools/qdbusxml2cpp/CMakeLists.txt b/tools/qdbusxml2cpp/CMakeLists.txt index 1dda035..50ee0a0 100644 --- a/tools/qdbusxml2cpp/CMakeLists.txt +++ b/tools/qdbusxml2cpp/CMakeLists.txt @@ -1,19 +1,36 @@ -set(BIN_NAME qdbusxml2cpp-fix) +set(TARGET_NAME qdbusxml2cpp-fix) +set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -find_package(Qt5 REQUIRED COMPONENTS Core) -find_package(Qt5 REQUIRED COMPONENTS DBus) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) add_executable(${BIN_NAME} - qdbusxml2cpp.cpp + qdbusxml2cpp.cpp ) target_link_libraries( ${BIN_NAME} PRIVATE - Qt5::DBus - Qt5::Core + Qt${QT_VERSION_MAJOR}::DBus + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::DBusPrivate ) -target_include_directories(${BIN_NAME} PUBLIC - ${Qt5DBus_PRIVATE_INCLUDE_DIRS} + +set_target_properties( + ${BIN_NAME} PROPERTIES + OUTPUT_NAME ${TARGET_NAME} + EXPORT_NAME Xml2Cpp +) + +install( + TARGETS ${BIN_NAME} + EXPORT Dtk${DTK_VERSION_MAJOR}ToolsTargets + DESTINATION ${TOOL_INSTALL_DIR} +) + +install( + EXPORT Dtk${DTK_VERSION_MAJOR}ToolsTargets + FILE Dtk${DTK_VERSION_MAJOR}ToolsTargets.cmake + NAMESPACE Dtk${DTK_VERSION_MAJOR}:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools" ) -install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index 3f86649..d9fc3aa 100644 --- a/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -24,6 +25,11 @@ #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" +#if QT_VERSION >= QT_VERSION_CHECK(5,15,0) +#define endl Qt::endl +#else +#define endl endl +#endif static QString globalClassName; static QString parentClassName; static QString proxyFile; @@ -32,6 +38,7 @@ static QString inputFile; static bool skipNamespaces; static bool verbose; static bool includeMocs; +static bool skipIncludeAnnotations; static QString commandLine; static QStringList includes; static QStringList wantedInterfaces; @@ -50,6 +57,7 @@ static const char help[] = " -N Don't use namespaces\n" " -p Write the proxy code to \n" " -v Be verbose.\n" + " -S Skip include annotation headers from \"types/\".\n" " -V Show the program version and quit.\n" "\n" "If the file name given to the options -a and -p does not end in .cpp or .h, the\n" @@ -152,6 +160,9 @@ static void parseCmdLine(QStringList args) case 'N': skipNamespaces = true; break; + case 'S': + skipIncludeAnnotations = true; + break; case '?': case 'h': @@ -249,7 +260,11 @@ static QString moc(const QString &name) return retval; retval.truncate(retval.length() - 1); // drop the h in .h +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + retval = QString("moc_%1cpp").arg(retval); +#else retval += QLatin1String("moc"); +#endif return retval; } @@ -303,21 +318,34 @@ static QString classNameForInterface(const QString &interface, ClassType classTy return retval; } +static QString annotationValue(QDBusIntrospection::Annotations annotations, const QString &name) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) + return annotations.value(name).value; +#else + return annotations.value(name); +#endif +} + static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection::Annotations &annotations, int paramId = -1, const char *direction = "Out") { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const auto& type = QDBusMetaType::signatureToMetaType(signature.toLatin1()); + if (type.id() == QMetaType::Type::UnknownType) { +#else int type = QDBusMetaType::signatureToType(signature.toLatin1()); if (type == QVariant::Invalid) { +#endif QString annotationName = QString::fromLatin1("org.qtproject.QtDBus.QtTypeName"); if (paramId >= 0) annotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); - QString qttype = annotations.value(annotationName); + QString qttype = annotationValue(annotations, annotationName); if (!qttype.isEmpty()) return qttype.toLatin1(); QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); if (paramId >= 0) oldAnnotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); - qttype = annotations.value(oldAnnotationName); + qttype = annotationValue(annotations, oldAnnotationName); if (qttype.isEmpty()) { fprintf(stderr, "Got unknown type `%s'\n", qPrintable(signature)); @@ -331,7 +359,11 @@ static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection: return qttype.toLatin1(); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return type.name(); +#else return QVariant::typeToName(QVariant::Type(type)); +#endif } static QString nonConstRefArg(const QByteArray &arg) @@ -424,11 +456,11 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames, static QString propertyGetter(const QDBusIntrospection::Property &property) { - QString getter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyGetter")); + QString getter = annotationValue(property.annotations, "org.qtproject.QtDBus.PropertyGetter"); if (!getter.isEmpty()) return getter; - getter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertyGetter")); + getter = annotationValue(property.annotations, "com.trolltech.QtDBus.propertyGetter"); if (!getter.isEmpty()) { fprintf(stderr, "Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found;" " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n"); @@ -442,11 +474,11 @@ static QString propertyGetter(const QDBusIntrospection::Property &property) static QString propertySetter(const QDBusIntrospection::Property &property) { - QString setter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertySetter")); + QString setter = annotationValue(property.annotations, "org.qtproject.QtDBus.PropertySetter"); if (!setter.isEmpty()) return setter; - setter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertySetter")); + setter = annotationValue(property.annotations, "com.trolltech.QtDBus.propertySetter"); if (!setter.isEmpty()) { fprintf(stderr, "Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found;" " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n"); @@ -460,7 +492,7 @@ static QString propertySetter(const QDBusIntrospection::Property &property) static QString propertyNotifier(const QDBusIntrospection::Property &property) { - QString notifier = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyNotifier")); + QString notifier = annotationValue(property.annotations, "org.qtproject.QtDBus.PropertyNotifier"); if (!notifier.isEmpty()) return notifier; @@ -471,7 +503,7 @@ static QString propertyNotifier(const QDBusIntrospection::Property &property) static QString methodName(const QDBusIntrospection::Method &method) { - QString name = method.annotations.value(QStringLiteral("org.qtproject.QtDBus.MethodName")); + QString name = annotationValue(method.annotations, "org.qtproject.QtDBus.MethodName"); if (!name.isEmpty()) return name; @@ -568,10 +600,14 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QSet annotations; for (const QDBusIntrospection::Interface *interface : interfaces) { - for (const auto method : interface->methods) { + for (const auto &method : interface->methods) { for (int i(0); i != method.outputArgs.size(); ++i) { const QDBusIntrospection::Argument &arg = method.outputArgs[i]; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (QDBusMetaType::signatureToMetaType(arg.type.toLatin1()).id() != QMetaType::Type::UnknownType) +#else if (QDBusMetaType::signatureToType(arg.type.toLatin1()) != QVariant::Invalid) +#endif continue; annotations << qtTypeName(arg.type, method.annotations, i, "Out"); @@ -579,24 +615,34 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf for (int i(0); i != method.inputArgs.size(); ++i) { const QDBusIntrospection::Argument &arg = method.inputArgs[i]; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (QDBusMetaType::signatureToMetaType(arg.type.toLatin1()).id() != QMetaType::Type::UnknownType) +#else if (QDBusMetaType::signatureToType(arg.type.toLatin1()) != QVariant::Invalid) +#endif continue; annotations << qtTypeName(arg.type, method.annotations, i, "In"); } } - for (const auto property : interface->properties) { + for (const auto &property : interface->properties) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (QDBusMetaType::signatureToMetaType(property.type.toLatin1()).id() != QMetaType::Type::UnknownType) +#else if (QDBusMetaType::signatureToType(property.type.toLatin1()) != QVariant::Invalid) +#endif continue; annotations << qtTypeName(property.type, property.annotations); } } - for (const QString &annotation : annotations) { - if (annotation.indexOf('<') == -1) { - hs << "#include \"types/" << annotation.toLower() << ".h\"" << endl; + if (!skipIncludeAnnotations) { + for (const QString &annotation : annotations) { + if (annotation.indexOf('<') == -1) { + hs << "#include \"types/" << annotation.toLower() << ".h\"" << endl; + } } } hs << endl; @@ -604,6 +650,9 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf foreach (const QDBusIntrospection::Interface *interface, interfaces) { QString className = "__" + classNameForInterface(interface->name, Proxy); + // using namespace Dtk::Core in cpp + cs << "DCORE_USE_NAMESPACE" << endl; + // comment: hs << "/*" << endl << " * Proxy class for interface " << interface->name << endl @@ -615,8 +664,8 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // private class declare hs << "class " << className << "Private;" << endl; - // class header: - hs << "class " << className << " : public DBusExtendedAbstractInterface" << endl + // class header: add Dtk::Core + hs << "class " << className << " : public DTK_CORE_NAMESPACE::DDBusExtendedAbstractInterface" << endl << "{" << endl << " Q_OBJECT" << endl; hs << endl; @@ -630,7 +679,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // private class member cs << " // begin member variables" << endl; - for (const auto property : interface->properties) { + for (const auto &property : interface->properties) { QByteArray type = qtTypeName(property.type, property.annotations); cs << " " << type << " " << property.name << ';' << endl; } @@ -659,7 +708,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf << " ~" << className << "();" << endl << endl; cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl - << " : DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl + << " : DDBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl << " , d_ptr(new " << className << "Private)" << endl << "{" << endl; if (!interface->properties.isEmpty()) @@ -668,12 +717,20 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf for (const QString &annotation : annotations) { if (annotation.indexOf('<') != -1) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + cs << " if (QMetaType::fromName(\"" << annotation << "\").id() == QMetaType::UnknownType) {" << endl; +#else cs << " if (QMetaType::type(\"" << annotation << "\") == QMetaType::UnknownType) {" << endl; +#endif cs << " qRegisterMetaType< " << annotation << " >(\"" << annotation << "\");" << endl; cs << " qDBusRegisterMetaType< " << annotation << " >();" << endl; cs << " }" << endl; } else { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + cs << " if (QMetaType::fromName(\"" << annotation << "\").id() == QMetaType::UnknownType)" << endl; +#else cs << " if (QMetaType::type(\"" << annotation << "\") == QMetaType::UnknownType)" << endl; +#endif cs << " register" << annotation << "MetaType();" << endl; } } @@ -692,10 +749,10 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf cs << "void " << className << "::onPropertyChanged(const QString &propName, const QVariant &value)" << endl; cs << "{" << endl; - for (const auto property : interface->properties) { + for (const auto &property : interface->properties) { char first = property.name[0].toLatin1(); QString name = property.name; - name[0] = first & ~0x20; + name[0] = QChar(first & ~0x20); QByteArray type = qtTypeName(property.type, property.annotations); @@ -777,9 +834,9 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // methods: hs << "public Q_SLOTS: // METHODS" << endl; foreach (const QDBusIntrospection::Method &method, interface->methods) { - bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true"); + bool isDeprecated = annotationValue(method.annotations, "org.freedesktop.DBus.Deprecated") == QLatin1String("true"); bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); + annotationValue(method.annotations, QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); if (isNoReply && !method.outputArgs.isEmpty()) { fprintf(stderr, "warning: method %s in interface %s is marked 'no-reply' but has output arguments.\n", qPrintable(method.name), qPrintable(interface->name)); @@ -899,7 +956,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf hs << "Q_SIGNALS: // SIGNALS" << endl; foreach (const QDBusIntrospection::Signal &signal, interface->signals_) { hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) + if (annotationValue(signal.annotations, QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; @@ -1200,7 +1257,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "public Q_SLOTS: // METHODS" << endl; foreach (const QDBusIntrospection::Method &method, interface->methods) { bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); + annotationValue(method.annotations, QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); if (isNoReply && !method.outputArgs.isEmpty()) { fprintf(stderr, "warning: method %s in interface %s is marked 'no-reply' but has output arguments.\n", qPrintable(method.name), qPrintable(interface->name)); @@ -1208,7 +1265,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } hs << " "; - if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) + if (annotationValue(method.annotations, QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; QByteArray returnType; @@ -1308,7 +1365,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "Q_SIGNALS: // SIGNALS" << endl; foreach (const QDBusIntrospection::Signal &signal, interface->signals_) { hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) + if (annotationValue(signal.annotations, QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; diff --git a/tools/qdbusxml2cpp/qdbusxml2cpp.pro b/tools/qdbusxml2cpp/qdbusxml2cpp.pro deleted file mode 100644 index e1e2b71..0000000 --- a/tools/qdbusxml2cpp/qdbusxml2cpp.pro +++ /dev/null @@ -1,16 +0,0 @@ -TARGET = qdbusxml2cpp-fix - -TEMPLATE = app -QT += core dbus-private dbus -CONFIG += c++11 - -SOURCES += qdbusxml2cpp.cpp - -host_sw_64 { - QMAKE_CXXFLAGS += -mieee -} - -#target.path = $$TOOL_INSTALL_DIR -target.path = $$PREFIX/bin - -INSTALLS += target diff --git a/tools/settings/CMakeLists.txt b/tools/settings/CMakeLists.txt index 052eeaa..c56bbed 100644 --- a/tools/settings/CMakeLists.txt +++ b/tools/settings/CMakeLists.txt @@ -1,21 +1,32 @@ -set(BIN_NAME dtk-settings) +set(TARGET_NAME dtk-settings) +set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) + +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml) + +if(${QT_VERSION_MAJOR} STREQUAL "5") + find_package(PkgConfig REQUIRED) + pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) +endif() -find_package(Qt5 REQUIRED COMPONENTS Core) -find_package(Qt5 REQUIRED COMPONENTS Xml) -find_package(PkgConfig REQUIRED) -pkg_check_modules(QGSettings REQUIRED gsettings-qt) add_executable(${BIN_NAME} main.cpp ) target_link_libraries( ${BIN_NAME} PRIVATE - Qt5::Core - Qt5::Xml - dtkcore - ${QGSettings_LIBRARIES} + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Xml + ${LIB_NAME} ) + +if(${QT_VERSION_MAJOR} STREQUAL "5") +target_link_libraries( + ${BIN_NAME} PRIVATE + PkgConfig::QGSettings +) +endif() + target_include_directories( ${BIN_NAME} PUBLIC - ${QGSettings_INCLUDE_DIRS} ../../include/util/ ../../include/dci/ ../../include/log/ @@ -26,4 +37,5 @@ target_include_directories( ${BIN_NAME} PUBLIC ../../include/filesystem/ ../../include/ ) +set_target_properties(${BIN_NAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME}) install(TARGETS ${BIN_NAME} DESTINATION "${TOOL_INSTALL_DIR}") diff --git a/tools/settings/main.cpp b/tools/settings/main.cpp index 3fd0ea7..690d09f 100644 --- a/tools/settings/main.cpp +++ b/tools/settings/main.cpp @@ -52,6 +52,35 @@ static QString CppTemplate = * dictionary a{ss} QVariantMap QVariant::Map */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +QString gsettings_type_from_QVarint(const QMetaType::Type qtype) +{ + switch (qtype) { + case QMetaType::Type::Bool: + return "b"; + case QMetaType::Type::Int: + return "i"; + case QMetaType::Type::UInt: + return "u"; + case QMetaType::Type::LongLong: + return "x"; + case QMetaType::Type::ULongLong: + return "t"; + case QMetaType::Type::Double: + return "d"; + case QMetaType::Type::QString: + return "s"; + case QMetaType::Type::QStringList: + return "as"; + case QMetaType::Type::QByteArray: + return "ay"; + case QMetaType::Type::QVariantMap: + return "a{ss}"; + default: + return ""; + } +} +#else QString gsettings_type_from_QVarint(const QVariant::Type qtype) { switch (qtype) { @@ -79,9 +108,36 @@ QString gsettings_type_from_QVarint(const QVariant::Type qtype) return ""; } } +#endif QString gsettings_value_from_QVarint(const QVariant value) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + switch (value.typeId()) { + case QMetaType::Type::Bool: + return value.toString(); + case QMetaType::Type::Int: + return value.toString(); + case QMetaType::Type::UInt: + return value.toString(); + case QMetaType::Type::LongLong: + return value.toString(); + case QMetaType::Type::ULongLong: + return value.toString(); + case QMetaType::Type::Double: + return value.toString(); + case QMetaType::Type::QString: + return QString("\"%1\"").arg(value.toString()); + case QMetaType::Type::QStringList: + return value.toString(); + case QMetaType::Type::QByteArray: + return value.toString(); + case QMetaType::Type::QVariantMap: + return value.toString(); + default: + return ""; + } +#else switch (value.type()) { case QVariant::Bool: return value.toString(); @@ -106,6 +162,7 @@ QString gsettings_value_from_QVarint(const QVariant value) default: return ""; } +#endif } @@ -141,9 +198,17 @@ static bool writeGSettingXML(Dtk::Core::DSettings *settings, for (QString key : settings->keys()) { auto codeKey = QString(key).replace(".", "-").replace("_", "-"); auto value = settings->option(key)->value(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto gtype = gsettings_type_from_QVarint(static_cast(value.typeId())); +#else auto gtype = gsettings_type_from_QVarint(value.type()); +#endif if (gtype.isEmpty()) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qDebug() << "skip unsupported type:" << value.typeId() << key; +#else qDebug() << "skip unsupported type:" << value.type() << key; +#endif continue; } diff --git a/tools/settings/settings.pro b/tools/settings/settings.pro deleted file mode 100644 index 21784c1..0000000 --- a/tools/settings/settings.pro +++ /dev/null @@ -1,34 +0,0 @@ -QT += core xml -QT -= gui - -CONFIG += c++11 - -TARGET = dtk-settings -CONFIG += console link_pkgconfig -CONFIG -= app_bundle -PKGCONFIG += gsettings-qt - -TEMPLATE = app - -SOURCES += main.cpp - -!isEmpty(DTK_STATIC_LIB){ - DEFINES += DTK_STATIC_LIB -} - -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../src/release/ -ldtkcore -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../src/debug/ -ldtkcore -else:unix: LIBS += -L$$OUT_PWD/../../src/ -ldtkcore - -INCLUDEPATH += $$PWD/../../src -DEPENDPATH += $$PWD/../../src -DESTDIR = $$_PRO_FILE_PWD_/../../bin - -DTK_MODULE_NAME=dtkcore -load(dtk_build_config) -target.path = $$TOOL_INSTALL_DIR - -scripts.files += ../script/*.py -scripts.path = $$TOOL_INSTALL_DIR - -INSTALLS += target scripts -- 2.30.2