From ff370a0787f6d2517f236470f0c0b06790c07949 Mon Sep 17 00:00:00 2001 From: Arun Kumar Pariyar Date: Thu, 3 Sep 2020 06:56:38 +0100 Subject: [PATCH] Import dtkcore_5.2.2.5.orig.tar.gz [dgit import orig dtkcore_5.2.2.5.orig.tar.gz] --- .clog.toml | 5 + .gitignore | 29 + .gitlab-ci.yml | 5 + .qmake.conf | 2 + .release.json | 16 + CHANGELOG.md | 266 + LICENSE | 165 + README.md | 52 + cmake/Dtk/DtkConfig.cmake | 3 + cmake/DtkCMake/DtkCMakeConfig.cmake | 76 + cmake/DtkTools/DtkSettingsToolsMacros.cmake | 53 + cmake/DtkTools/DtkToolsConfig.cmake | 9 + conanfile.py | 87 + debian/api.json | 11 + debian/changelog | 23 + debian/compat | 1 + debian/control | 34 + debian/copyright | 22 + debian/libdtkcore-dev.install | 5 + debian/libdtkcore5-bin.install | 1 + debian/libdtkcore5.install | 2 + debian/rules | 31 + debian/source/format | 1 + debian/symbols.amd64 | 909 + doc/Specification.md | 81 + dtk_build_config.prf | 77 + dtkcore.pro | 1 + examples/examples.pro | 2 + examples/expintf-example/expintf-example.pro | 16 + examples/expintf-example/main.cpp | 72 + rpm/dtkcore.spec | 75 + src/DDesktopEntry | 1 + src/DSecureString | 1 + src/DSysInfo | 1 + src/base/DObject | 1 + src/base/DObjectPrivate | 1 + src/base/DSingleton | 1 + src/base/base.pri | 18 + src/base/dobject.cpp | 246 + src/base/dobject.h | 54 + src/base/dsingleton.h | 77 + src/base/private/dobject_p.h | 42 + src/base/private/private.pri | 2 + src/com.deepin.dtk.gschema.xml | 16 + src/ddesktopentry.cpp | 1043 + src/ddesktopentry.h | 113 + src/dsecurestring.cpp | 36 + src/dsecurestring.h | 36 + src/dsysinfo.cpp | 902 + src/dsysinfo.h | 152 + src/dtk_build.prf | 98 + src/dtk_cmake.prf | 44 + src/dtk_lib.prf | 7 + src/dtk_module.prf | 127 + src/dtk_qmake.prf | 121 + src/dtk_translation.prf | 63 + src/dtkcore_global.h | 69 + src/filesystem/DBaseFileWatcher | 1 + src/filesystem/DFileSystemWatcher | 1 + src/filesystem/DFileWatcher | 1 + src/filesystem/DFileWatcherManager | 1 + src/filesystem/DPathBuf | 1 + src/filesystem/DStandardPaths | 1 + src/filesystem/DTrashManager | 1 + src/filesystem/dbasefilewatcher.cpp | 197 + src/filesystem/dbasefilewatcher.h | 67 + src/filesystem/dfilesystemwatcher.h | 62 + src/filesystem/dfilesystemwatcher_dummy.cpp | 248 + src/filesystem/dfilesystemwatcher_linux.cpp | 671 + src/filesystem/dfilesystemwatcher_win.cpp | 248 + src/filesystem/dfilewatcher.cpp | 295 + src/filesystem/dfilewatcher.h | 48 + src/filesystem/dfilewatchermanager.cpp | 124 + src/filesystem/dfilewatchermanager.h | 59 + src/filesystem/dpathbuf.cpp | 36 + src/filesystem/dpathbuf.h | 99 + src/filesystem/dstandardpaths.cpp | 120 + src/filesystem/dstandardpaths.h | 53 + src/filesystem/dtrashmanager.h | 47 + src/filesystem/dtrashmanager_dummy.cpp | 156 + src/filesystem/dtrashmanager_linux.cpp | 260 + src/filesystem/filesystem.pri | 43 + src/filesystem/private/dbasefilewatcher_p.h | 45 + .../private/dfilesystemwatcher_dummy_p.h | 45 + .../private/dfilesystemwatcher_linux_p.h | 57 + .../private/dfilesystemwatcher_win_p.h | 45 + src/filesystem/private/private.pri | 10 + src/log/AbstractAppender.cpp | 153 + src/log/AbstractAppender.h | 52 + src/log/AbstractStringAppender.cpp | 462 + src/log/AbstractStringAppender.h | 49 + src/log/ConsoleAppender.cpp | 67 + src/log/ConsoleAppender.h | 39 + src/log/CuteLogger_global.h | 33 + src/log/DLog | 8 + src/log/FileAppender.cpp | 112 + src/log/FileAppender.h | 52 + src/log/LICENSE | 674 + src/log/LogManager.cpp | 101 + src/log/LogManager.h | 68 + src/log/Logger.cpp | 1060 + src/log/Logger.h | 207 + src/log/OutputDebugAppender.cpp | 45 + src/log/OutputDebugAppender.h | 32 + src/log/README.md | 63 + src/log/RollingFileAppender.cpp | 249 + src/log/RollingFileAppender.h | 102 + src/log/cutelogger.pri | 25 + src/log/log.pri | 5 + src/settings/DSettings | 1 + src/settings/DSettingsGroup | 1 + src/settings/DSettingsOption | 1 + src/settings/backend/gsettingsbackend.cpp | 127 + src/settings/backend/gsettingsbackend.h | 30 + src/settings/backend/qsettingbackend.cpp | 115 + src/settings/backend/qsettingbackend.h | 47 + src/settings/dsettings.cpp | 483 + src/settings/dsettings.h | 76 + src/settings/dsettingsbackend.h | 56 + src/settings/dsettingsgroup.cpp | 281 + src/settings/dsettingsgroup.h | 62 + src/settings/dsettingsoption.cpp | 370 + src/settings/dsettingsoption.h | 70 + src/settings/settings.pri | 31 + src/src.pro | 65 + src/util/DAbstractUnitFormatter | 1 + src/util/DDBusSender | 1 + src/util/DDiskSizeFormatter | 1 + src/util/DExportedInterface | 1 + src/util/DFileServices | 1 + src/util/DNotifySender | 1 + src/util/DPinyin | 1 + src/util/DRecentManager | 1 + src/util/DThreadUtils | 1 + src/util/DTimeUnitFormatter | 1 + src/util/DUtil | 1 + src/util/DVtableHook | 1 + src/util/README.dpinyin | 6 + src/util/dabstractunitformatter.cpp | 145 + src/util/dabstractunitformatter.h | 50 + src/util/ddbussender.cpp | 91 + src/util/ddbussender.h | 97 + src/util/ddisksizeformatter.cpp | 95 + src/util/ddisksizeformatter.h | 54 + src/util/dexportedinterface.cpp | 151 + src/util/dexportedinterface.h | 52 + src/util/dfileservices.h | 55 + src/util/dfileservices_dummy.cpp | 162 + src/util/dfileservices_linux.cpp | 151 + src/util/dnotifysender.cpp | 114 + src/util/dnotifysender.h | 32 + src/util/dpinyin.cpp | 79 + src/util/dpinyin.h | 34 + src/util/drecentmanager.cpp | 250 + src/util/drecentmanager.h | 47 + src/util/dthreadutils.cpp | 63 + src/util/dthreadutils.h | 174 + src/util/dtimeunitformatter.cpp | 96 + src/util/dtimeunitformatter.h | 49 + src/util/dutil.h | 60 + src/util/dvtablehook.cpp | 320 + src/util/dvtablehook.h | 306 + src/util/resources/dpinyin.dict | 25333 ++++++++++++++++ src/util/util.pri | 52 + src/util/util.qrc | 5 + tests/ddesktopentry/CMakeLists.txt | 8 + tests/ddesktopentry/ddesktopentry.pro | 27 + tests/ddesktopentry/tst_ddesktopentrytest.cpp | 123 + tests/dthreadutils/dthreadutils.pro | 25 + tests/dthreadutils/tst_dthreadutils.cpp | 87 + tests/dutils/data.qrc | 5 + tests/dutils/data/dt-settings.json | 218 + tests/dutils/dutils.pro | 29 + tests/dutils/dutiltester.cpp | 243 + tests/dutils/dutiltester.h | 41 + tests/dutils/main.cpp | 22 + tests/dutils/singletontester.cpp | 42 + tests/dutils/singletontester.h | 43 + tests/dvtablehook/dvtablehook.pro | 25 + tests/dvtablehook/tst_dvtablehook.cpp | 115 + tests/tests.pro | 6 + tools/deepin-os-release/deepin-os-release.pro | 20 + tools/deepin-os-release/main.cpp | 139 + tools/script/dtk-license.py | 320 + tools/script/dtk-translate.py | 18 + tools/settings/main.cpp | 297 + tools/settings/settings.pro | 34 + tools/tools.pro | 3 + 188 files changed, 43945 insertions(+) create mode 100644 .clog.toml create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .qmake.conf create mode 100644 .release.json create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/Dtk/DtkConfig.cmake create mode 100644 cmake/DtkCMake/DtkCMakeConfig.cmake create mode 100644 cmake/DtkTools/DtkSettingsToolsMacros.cmake create mode 100644 cmake/DtkTools/DtkToolsConfig.cmake create mode 100644 conanfile.py create mode 100644 debian/api.json create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/libdtkcore-dev.install create mode 100644 debian/libdtkcore5-bin.install create mode 100644 debian/libdtkcore5.install create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/symbols.amd64 create mode 100644 doc/Specification.md create mode 100644 dtk_build_config.prf create mode 100644 dtkcore.pro create mode 100644 examples/examples.pro create mode 100644 examples/expintf-example/expintf-example.pro create mode 100644 examples/expintf-example/main.cpp create mode 100644 rpm/dtkcore.spec create mode 100644 src/DDesktopEntry create mode 100644 src/DSecureString create mode 100644 src/DSysInfo create mode 100644 src/base/DObject create mode 100644 src/base/DObjectPrivate create mode 100644 src/base/DSingleton create mode 100644 src/base/base.pri create mode 100644 src/base/dobject.cpp create mode 100644 src/base/dobject.h create mode 100644 src/base/dsingleton.h create mode 100644 src/base/private/dobject_p.h create mode 100644 src/base/private/private.pri create mode 100644 src/com.deepin.dtk.gschema.xml create mode 100644 src/ddesktopentry.cpp create mode 100644 src/ddesktopentry.h create mode 100644 src/dsecurestring.cpp create mode 100644 src/dsecurestring.h create mode 100644 src/dsysinfo.cpp create mode 100644 src/dsysinfo.h create mode 100644 src/dtk_build.prf create mode 100644 src/dtk_cmake.prf create mode 100644 src/dtk_lib.prf create mode 100644 src/dtk_module.prf create mode 100644 src/dtk_qmake.prf create mode 100644 src/dtk_translation.prf create mode 100644 src/dtkcore_global.h create mode 100644 src/filesystem/DBaseFileWatcher create mode 100644 src/filesystem/DFileSystemWatcher create mode 100644 src/filesystem/DFileWatcher create mode 100644 src/filesystem/DFileWatcherManager create mode 100644 src/filesystem/DPathBuf create mode 100644 src/filesystem/DStandardPaths create mode 100644 src/filesystem/DTrashManager create mode 100644 src/filesystem/dbasefilewatcher.cpp create mode 100644 src/filesystem/dbasefilewatcher.h create mode 100644 src/filesystem/dfilesystemwatcher.h create mode 100644 src/filesystem/dfilesystemwatcher_dummy.cpp create mode 100644 src/filesystem/dfilesystemwatcher_linux.cpp create mode 100644 src/filesystem/dfilesystemwatcher_win.cpp create mode 100644 src/filesystem/dfilewatcher.cpp create mode 100644 src/filesystem/dfilewatcher.h create mode 100644 src/filesystem/dfilewatchermanager.cpp create mode 100644 src/filesystem/dfilewatchermanager.h create mode 100644 src/filesystem/dpathbuf.cpp create mode 100644 src/filesystem/dpathbuf.h create mode 100644 src/filesystem/dstandardpaths.cpp create mode 100644 src/filesystem/dstandardpaths.h create mode 100644 src/filesystem/dtrashmanager.h create mode 100644 src/filesystem/dtrashmanager_dummy.cpp create mode 100644 src/filesystem/dtrashmanager_linux.cpp create mode 100644 src/filesystem/filesystem.pri create mode 100644 src/filesystem/private/dbasefilewatcher_p.h create mode 100644 src/filesystem/private/dfilesystemwatcher_dummy_p.h create mode 100644 src/filesystem/private/dfilesystemwatcher_linux_p.h create mode 100644 src/filesystem/private/dfilesystemwatcher_win_p.h create mode 100644 src/filesystem/private/private.pri create mode 100644 src/log/AbstractAppender.cpp create mode 100644 src/log/AbstractAppender.h create mode 100644 src/log/AbstractStringAppender.cpp create mode 100644 src/log/AbstractStringAppender.h create mode 100644 src/log/ConsoleAppender.cpp create mode 100644 src/log/ConsoleAppender.h create mode 100644 src/log/CuteLogger_global.h create mode 100644 src/log/DLog create mode 100644 src/log/FileAppender.cpp create mode 100644 src/log/FileAppender.h create mode 100644 src/log/LICENSE create mode 100644 src/log/LogManager.cpp create mode 100644 src/log/LogManager.h create mode 100644 src/log/Logger.cpp create mode 100644 src/log/Logger.h create mode 100644 src/log/OutputDebugAppender.cpp create mode 100644 src/log/OutputDebugAppender.h create mode 100644 src/log/README.md create mode 100644 src/log/RollingFileAppender.cpp create mode 100644 src/log/RollingFileAppender.h create mode 100644 src/log/cutelogger.pri create mode 100644 src/log/log.pri create mode 100644 src/settings/DSettings create mode 100644 src/settings/DSettingsGroup create mode 100644 src/settings/DSettingsOption create mode 100644 src/settings/backend/gsettingsbackend.cpp create mode 100644 src/settings/backend/gsettingsbackend.h create mode 100644 src/settings/backend/qsettingbackend.cpp create mode 100644 src/settings/backend/qsettingbackend.h create mode 100644 src/settings/dsettings.cpp create mode 100644 src/settings/dsettings.h create mode 100644 src/settings/dsettingsbackend.h create mode 100644 src/settings/dsettingsgroup.cpp create mode 100644 src/settings/dsettingsgroup.h create mode 100644 src/settings/dsettingsoption.cpp create mode 100644 src/settings/dsettingsoption.h create mode 100644 src/settings/settings.pri create mode 100644 src/src.pro create mode 100644 src/util/DAbstractUnitFormatter create mode 100644 src/util/DDBusSender create mode 100644 src/util/DDiskSizeFormatter create mode 100644 src/util/DExportedInterface create mode 100644 src/util/DFileServices create mode 100644 src/util/DNotifySender create mode 100644 src/util/DPinyin create mode 100644 src/util/DRecentManager create mode 100644 src/util/DThreadUtils create mode 100644 src/util/DTimeUnitFormatter create mode 100644 src/util/DUtil create mode 100644 src/util/DVtableHook create mode 100644 src/util/README.dpinyin create mode 100644 src/util/dabstractunitformatter.cpp create mode 100644 src/util/dabstractunitformatter.h create mode 100644 src/util/ddbussender.cpp create mode 100644 src/util/ddbussender.h create mode 100644 src/util/ddisksizeformatter.cpp create mode 100644 src/util/ddisksizeformatter.h create mode 100644 src/util/dexportedinterface.cpp create mode 100644 src/util/dexportedinterface.h create mode 100644 src/util/dfileservices.h create mode 100644 src/util/dfileservices_dummy.cpp create mode 100644 src/util/dfileservices_linux.cpp create mode 100644 src/util/dnotifysender.cpp create mode 100644 src/util/dnotifysender.h create mode 100644 src/util/dpinyin.cpp create mode 100644 src/util/dpinyin.h create mode 100644 src/util/drecentmanager.cpp create mode 100644 src/util/drecentmanager.h create mode 100644 src/util/dthreadutils.cpp create mode 100644 src/util/dthreadutils.h create mode 100644 src/util/dtimeunitformatter.cpp create mode 100644 src/util/dtimeunitformatter.h create mode 100644 src/util/dutil.h create mode 100644 src/util/dvtablehook.cpp create mode 100644 src/util/dvtablehook.h create mode 100644 src/util/resources/dpinyin.dict create mode 100644 src/util/util.pri create mode 100644 src/util/util.qrc create mode 100644 tests/ddesktopentry/CMakeLists.txt create mode 100644 tests/ddesktopentry/ddesktopentry.pro create mode 100644 tests/ddesktopentry/tst_ddesktopentrytest.cpp create mode 100644 tests/dthreadutils/dthreadutils.pro create mode 100644 tests/dthreadutils/tst_dthreadutils.cpp create mode 100644 tests/dutils/data.qrc create mode 100644 tests/dutils/data/dt-settings.json create mode 100644 tests/dutils/dutils.pro create mode 100644 tests/dutils/dutiltester.cpp create mode 100644 tests/dutils/dutiltester.h create mode 100644 tests/dutils/main.cpp create mode 100644 tests/dutils/singletontester.cpp create mode 100644 tests/dutils/singletontester.h create mode 100644 tests/dvtablehook/dvtablehook.pro create mode 100644 tests/dvtablehook/tst_dvtablehook.cpp create mode 100644 tests/tests.pro create mode 100644 tools/deepin-os-release/deepin-os-release.pro create mode 100644 tools/deepin-os-release/main.cpp create mode 100644 tools/script/dtk-license.py create mode 100644 tools/script/dtk-translate.py create mode 100644 tools/settings/main.cpp create mode 100644 tools/settings/settings.pro create mode 100644 tools/tools.pro diff --git a/.clog.toml b/.clog.toml new file mode 100644 index 0000000..646b8fe --- /dev/null +++ b/.clog.toml @@ -0,0 +1,5 @@ +[clog] +repository = "https://github.com/linuxdeepin/dtkcore" +from-latest-tag = true + +changelog = "CHANGELOG.md" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a49eb98 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +build*/ +*.pro.user* +*.DS_Store + +# executeable files +*.qm + +src/DtkCores +src/dtkcore_config.h +cmake/DtkCore/DtkCoreConfig.cmake +src/qt_lib_d*.pri + +bin/ +.qmake* +Makefile diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..6da6602 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,5 @@ +include: + - remote: 'https://gitlab.deepin.io/dev-tools/letmeci/raw/master/gitlab-ci/dde.yml' +variables: + CPPCHECK: "true" + CODESPELL: "true" diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 0000000..ee2de90 --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,2 @@ +isEmpty(DTK_VERSION):DTK_VERSION=5.0.0 +DTK_MODULE_NAME=dtkcore diff --git a/.release.json b/.release.json new file mode 100644 index 0000000..169c9a8 --- /dev/null +++ b/.release.json @@ -0,0 +1,16 @@ +{ + "commit": { + "quilt": false, + "pkgver": "echo $(git tag | sort -V | tail -n1)'+r'$(git log $(git describe --abbrev=0 --tags)..HEAD --oneline|wc -l)'+g'$(git rev-parse --short HEAD);", + "dist": "experimental" + }, + "release": { + "quilt": true, + "pkgver": "git describe --abbrev=0 --tags %(ref)s", + "dist": "unstable" + }, + "release-candidate": { + "quilt": true, + "dist": "unstable" + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15fbd7f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,266 @@ + +## 2.0.14 (2019-05-23) + +#### Bug Fixes + +* **DSettings:** crash when calling getOption() if option doesn't exist ([90ac734b](https://github.com/linuxdeepin/dtkcore/commit/90ac734b872203ea698808a7197aa7a9c7e2b5bd)) + + + + +## 2.0.12 (2019-04-18) + + + + + +## 2.0.11 (2019-04-17) + + +#### Bug Fixes + +* Cross-builds incorrectly, built packages contain paths from build architecture ([8d32577a](https://github.com/linuxdeepin/dtkcore/commit/8d32577a89e54b5c9c834caae83d98e50f59df77)) +* https://github.com/linuxdeepin/dtkcore/issues/10 ([3f99873a](https://github.com/linuxdeepin/dtkcore/commit/3f99873a786f6830688ecd0d8d2e2bf8dfb63ce0)) + + + + +## 2.0.10 (2019-03-27) + + +#### Bug Fixes + +* crash at application ([d852a218](https://github.com/linuxdeepin/dtkcore/commit/d852a21811f9f86e04274fc9f732d7c7a210ef3f)) + +#### Features + +* add DNotifySender ([89bbcd7c](https://github.com/linuxdeepin/dtkcore/commit/89bbcd7c3821985bb2bca51247394fd4a65b25bf)) + + + + +## 2.0.9.17 (2019-02-26) + + + + + +## 2.0.9.16 (2019-02-26) + + +#### Bug Fixes + +* deepin-os-release support cpu model and other info query ([cbeb47c9](https://github.com/linuxdeepin/dtkcore/commit/cbeb47c97e31d2b5dd3c198c60ee74332fecb293)) + + + + +## 2.0.9.15 (2019-01-25) + + +#### Bug Fixes + +* failed build the deepin-os-release on Qt 5.7.1 ([8bae8654](https://github.com/linuxdeepin/dtkcore/commit/8bae8654bdb20a7f773130d22b9db139460ba575)) +* use main project c/cxx/ld flags on build deepin-os-release ([86dbd507](https://github.com/linuxdeepin/dtkcore/commit/86dbd507c1b3b101c1816f091782430ec1ce20ce)) + + + + +## 2.0.9.14 (2019-01-02) + + + + + +## 2.0.9.13 (2018-12-28) + + + + + +## 2.0.9.12 (2018-12-24) + + +#### Bug Fixes + +* **DPathBuf:** missing default constructor ([74374cb4](https://github.com/linuxdeepin/dtkcore/commit/74374cb4cf0245ab1fe73f62fe0d13566f945db3)) + +#### Features + +* support connan build ([ba2d213f](https://github.com/linuxdeepin/dtkcore/commit/ba2d213fd6c7e36e118288305e5892c339250623)) + + + + +## 2.0.9.11 (2018-12-14) + + + + + +## 2.0.9.10 (2018-12-05) + + +#### Bug Fixes + +* include unistd.h instead of sys/unistd.h ([39c50a13](https://github.com/linuxdeepin/dtkcore/commit/39c50a1398c34123e3806a3060a4c64e7f45ed68)) +* url encoding ([4a6b7b61](https://github.com/linuxdeepin/dtkcore/commit/4a6b7b61bb3ad9ab417eda69249b5e9aced0aa97)) + + + + +## 2.0.9.9 (2018-11-19) + + +#### Features + +* add DRecentManager class. ([a2defafd](https://github.com/linuxdeepin/dtkcore/commit/a2defafdcf57078461221c665e322287a43d24a8)) + +#### Bug Fixes + +* compatibility with Qt 5.6 ([0ec7f3ce](https://github.com/linuxdeepin/dtkcore/commit/0ec7f3ce389b323ecb2b103801c1cd1d55f100fa)) +* **drecentmanager:** + * xbel file does not exist. ([c57ffe71](https://github.com/linuxdeepin/dtkcore/commit/c57ffe714f26b1a8a8859e2ffbeeed3d75ee11a1)) + * uniform url format. ([413a8988](https://github.com/linuxdeepin/dtkcore/commit/413a8988116708ab8bcf9efbb9bc8f52e048efa5)) + * url encoded. ([e234a8cc](https://github.com/linuxdeepin/dtkcore/commit/e234a8cc5ad9d2c14a16950838115c4f2f27c605)) +* **recent:** chinese doc ([fb256461](https://github.com/linuxdeepin/dtkcore/commit/fb256461d1bdb0862b1a3a129978fc3932a6bcab)) + + + + +## 2.0.9.8 (2018-11-09) + + +#### Bug Fixes + +* can't get correct disk size in some case ([20a12b62](https://github.com/linuxdeepin/dtkcore/commit/20a12b622ea7b01f0616c15a8af85e31fc2d36cb)) + + + + +## 2.0.9.5 (2018-10-26) + + +#### Features + +* update version number for expermimental ([02b5d5c1](https://github.com/linuxdeepin/dtkcore/commit/02b5d5c1e01a05f57651b774b02cae31ef9a549f)) + + + + +## 2.0.9 (2018-07-20) + + +#### Bug Fixes + +* remove qt symbols ([57ec78ba](https://github.com/linuxdeepin/dtkcore/commit/57ec78ba685a53692b0260d3d558d8b0915fc3e4)) +* non array type value is wrong on parse josn file ([9f138664](https://github.com/linuxdeepin/dtkcore/commit/9f13866439d8d650893434594da023e7d331d866)) + + + + +### 2.0.8.1 (2018-05-14) + + +#### Bug Fixes + +* update symbols ([f6c53cc4](https://github.com/linuxdeepin/dtkcore/commit/f6c53cc493c1bcf55dca54dbf500e2e484af73c9)) +* add LIBDTKCORESHARED_EXPORT for windows ([6fb1096f](https://github.com/linuxdeepin/dtkcore/commit/6fb1096f6d0784937cf84f0e4ae1f5f7587085e5)) +* **changelog:** update email format ([cb09a0ca](https://github.com/linuxdeepin/dtkcore/commit/cb09a0cadcf2fa0ba271b1d98d3b96a993eb892b)) + + + + +## 2.0.8 (2018-05-02) + + +#### Features + +* add symbols ([048de455](https://github.com/linuxdeepin/dtkcore/commit/048de4551bdd770aca5e9c12798362f913061654)) + + + + +## 2.0.7 (2018-03-01) + + +#### Bug Fixes + +* cmake link depends ([cdfcff9e](https://github.com/linuxdeepin/dtkcore/commit/cdfcff9e2f3e92bc6dbb45644d2714d6c4dbdda0)) +* better static lib support ([99886406](https://github.com/linuxdeepin/dtkcore/commit/99886406a0cae849fad23286fdf64bb399e37da0)) +* read settings value failed ([cf1c7698](https://github.com/linuxdeepin/dtkcore/commit/cf1c769893773794dff5a67c235c5d1f3234541a)) +* set default should not use ([146529f6](https://github.com/linuxdeepin/dtkcore/commit/146529f6887e798606f2bf763ab8a760969bff26)) +* fix dtk-settings install path ([1893cff3](https://github.com/linuxdeepin/dtkcore/commit/1893cff301dacb546a246a4f824dab68eac51351)) +* develop package no install the "version.pri" file ([5667b562](https://github.com/linuxdeepin/dtkcore/commit/5667b562630565fca5abed690f3d3478dd3c7603)) +* awk script failed ([524a3fa6](https://github.com/linuxdeepin/dtkcore/commit/524a3fa6021ee54db416503520aea65ef0e2c3a0)) +* set default build version for debian changelog ([ec6e2a83](https://github.com/linuxdeepin/dtkcore/commit/ec6e2a8376c7aca7162b4fbb782b998c9a6ab630)) +* set its value only if VERSION is empty ([1836000c](https://github.com/linuxdeepin/dtkcore/commit/1836000c49eb149a6495322c4cbb1474d5d48204)) + +#### Features + +* add hide support for group ([e7e4fb66](https://github.com/linuxdeepin/dtkcore/commit/e7e4fb669276fbce61c6378e74ae82573e7c0313)) +* add get option interface ([d8682485](https://github.com/linuxdeepin/dtkcore/commit/d8682485a6737da83fb28f22335f1da1afb8956c)) +* add group interface for DSettingsGroup ([c876180f](https://github.com/linuxdeepin/dtkcore/commit/c876180f535e3027dce63628f31379ef874367ed)) +* support generate cmake with qt function ([524b0559](https://github.com/linuxdeepin/dtkcore/commit/524b055929b7be84375a45f9d10cbc3a0ecac6de)) +* config pkg config with dtk_module ([137b9138](https://github.com/linuxdeepin/dtkcore/commit/137b91388d9b9db24c8136dd4e2c6e690a5712c5)) +* support qt module ([17ca0de9](https://github.com/linuxdeepin/dtkcore/commit/17ca0de9156a320cea32208dcff2f8cdf7d6a237)) +* add the "version.pri" file ([07aab9fd](https://github.com/linuxdeepin/dtkcore/commit/07aab9fd6478c83c7bae1062f64b4bd20b21869c)) +* remove build version from install path ([3bf0bfb5](https://github.com/linuxdeepin/dtkcore/commit/3bf0bfb5f49c3e83d4c36cc33f219150bf3731d8)) +* make version parser easier ([6d3b4ead](https://github.com/linuxdeepin/dtkcore/commit/6d3b4ead7080158d1d8977bf7cf99ae842e574ec)) +* set verion when build ([9083dbd3](https://github.com/linuxdeepin/dtkcore/commit/9083dbd3e29bf9d06b1032901ba13848fa964f4c)) +* add .qmake.conf file ([2890f643](https://github.com/linuxdeepin/dtkcore/commit/2890f643a57c3532ab623410f7c6c6dbfdd6788d)) +* add DtkCore and dtkcore_config.h headers ([308a0cc4](https://github.com/linuxdeepin/dtkcore/commit/308a0cc41101499c04308b4ef3bb2fff4ab8d783)) +* **DSettings:** support set default value ([5fe9bfd0](https://github.com/linuxdeepin/dtkcore/commit/5fe9bfd0a5e20cef7393639712302825b803db29)) + + + + +## 2.0.6 (2018-01-15) + + + + + +## 2.0.5.3 (2017-12-27) + + +#### Bug Fixes + +* Adapt lintian ([27df15df](https://github.com/linuxdeepin/dtkcore/commit/27df15df32788002491a24f06f098a5f849a4988)) +* break forever loop for syncing backend data ([f70e500e](https://github.com/linuxdeepin/dtkcore/commit/f70e500ec2fd5c751e40833bdc4df586614bcff2)) + +#### Features + +* **util:** add dpinyin ([128d7d67](https://github.com/linuxdeepin/dtkcore/commit/128d7d678e921bc580dd732b14a454973397899c)) + + + + +## 2.0.5.2 (2017-11-28) + + +#### Bug Fixes + +* make macosx build success ([af04bbe1](https://github.com/linuxdeepin/dtkcore/commit/af04bbe193a4b4251908f830d927ebdc8f4459e7)) +* windows build failed ([66c4c812](https://github.com/linuxdeepin/dtkcore/commit/66c4c812eb29634710642f4e9d6b3d69cc692cb2)) + +#### Features + +* add macro D_DECL_DEPRECATED ([89e49868](https://github.com/linuxdeepin/dtkcore/commit/89e49868f113ef01c03bcf5b6846eec95c428382)) + + + + +## 2.0.5 (2017-11-06) + + +#### Bug Fixes + +* build failed on used dbasefilewatcher.h project ([34fbe4b3](34fbe4b3)) +* add miss libgsettings-qt-dev ([f61c1b54](f61c1b54)) +* not select python version ([7e7e8832](7e7e8832)) + +#### Features + +* support gsettingsbackend, remove dsettings-key ([26a29800](26a29800)) +* create gsettingsbackend ([b94b97b1](b94b97b1)) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..150a69d --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +## Deepin Tool Kit Core {#mainpage} + +Deepint Tool Kit (Dtk) is the base development tool of all C++/Qt Developer work on Deepin. + +You should read the [Deepin Application Specification](\ref doc/Specification) firstly. + +## Dependencies + +### Build dependencies + +* Qt >= 5.6 + +## Installation + +### Build from source code + +1. Make sure you have installed all dependencies. + +2. Build: + +```` +$ mkdir build +$ cd build +$ qmake .. +$ make +```` + +3. Install: + +```` +$ sudo make install +```` + +## Getting help + +Any usage issues can ask for help via + +* [Gitter](https://gitter.im/orgs/linuxdeepin/rooms) +* [IRC channel](https://webchat.freenode.net/?channels=deepin) +* [Forum](https://bbs.deepin.org) +* [WiKi](https://wiki.deepin.org/) + +## Getting involved + +We encourage you to report issues and contribute changes + +* [Contribution guide for developers](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers-en). (English) +* [开发者代码贡献指南](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers) (中文) + +## License + +deepin-tool-kit is licensed under [GPLv3](LICENSE). diff --git a/cmake/Dtk/DtkConfig.cmake b/cmake/Dtk/DtkConfig.cmake new file mode 100644 index 0000000..1f4022c --- /dev/null +++ b/cmake/Dtk/DtkConfig.cmake @@ -0,0 +1,3 @@ +foreach(module ${Dtk_FIND_COMPONENTS}) + find_package(Dtk${module}) +endforeach() diff --git a/cmake/DtkCMake/DtkCMakeConfig.cmake b/cmake/DtkCMake/DtkCMakeConfig.cmake new file mode 100644 index 0000000..f8d62f1 --- /dev/null +++ b/cmake/DtkCMake/DtkCMakeConfig.cmake @@ -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(DtkCore REQUIRED) + +set(DEEPIN_OS_RELEASE_TOOL_PATH ${DTKCORE_TOOL_DIR}) +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/DtkTools/DtkSettingsToolsMacros.cmake b/cmake/DtkTools/DtkSettingsToolsMacros.cmake new file mode 100644 index 0000000..da1cd10 --- /dev/null +++ b/cmake/DtkTools/DtkSettingsToolsMacros.cmake @@ -0,0 +1,53 @@ +#============================================================================= +# Copyright 2019 Deepin Technology Co., Ltd. +# Copyright 2019 Gary Wang +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * 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. +# +# * Neither the name of authors 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. +#============================================================================= + +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. + + 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} + ARGS ${_input_json_abs_path} -o ${_output_cpp_abs_path} + DEPENDS ${_input_json_abs_path} VERBATIM) + 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`.") + endif () + + set(${_generated_file_list} ${generated_file_list} PARENT_SCOPE) +endfunction() diff --git a/cmake/DtkTools/DtkToolsConfig.cmake b/cmake/DtkTools/DtkToolsConfig.cmake new file mode 100644 index 0000000..02ec88e --- /dev/null +++ b/cmake/DtkTools/DtkToolsConfig.cmake @@ -0,0 +1,9 @@ +find_package(DtkCore REQUIRED) + +set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DTKCORE_TOOL_DIR}/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/conanfile.py b/conanfile.py new file mode 100644 index 0000000..3a6161f --- /dev/null +++ b/conanfile.py @@ -0,0 +1,87 @@ +from conans import ConanFile, tools + + +class DtkcoreConan(ConanFile): + name = 'dtkcore' + version = '2.0.9' + license = 'GPL' + author = 'Iceyer me@iceyer.net' + url = 'https://github.com/linuxdeepin/dtkcore' + description = 'cross platform ui library' + topics = ('qt', 'dtk') + settings = 'os', 'compiler', 'build_type', 'arch' + options = {'shared': [True, False]} + default_options = 'shared=False' + generators = 'qmake' + exports_sources = '*' + requires = 'jom_installer/1.1.2@bincrafters/stable', 'qt/5.6.3@iceyer/stable' + + def extend_include_path(self): + return '%s/include/libdtk-%s/DCore' % (self.package_folder, self.version) + + # def source(self): + # self.run('git clone https://github.com/linuxdeepin/dtkcore.git source') + # self.run('cd source && git checkout 2.0.9.9') + + def build(self): + outdir = self.build_folder + # includedir = outdir + '/include' + mkspecsdir = outdir + '/mkspecs' + # libdir = outdir + '/lib' + + env_vars = tools.vcvars_dict(self.settings) + env_vars['_CL_'] = '/utf-8' + with tools.environment_append(env_vars): + command = 'qmake -r' + command += ' VERSION=%s' % self.version + # command += ' CONFIG-=debug_and_release' + # command += ' CONFIG-=debug_and_release_target' + command += ' CONFIG+=release' + command += ' PREFIX=%s' % outdir + command += ' MKSPECS_INSTALL_DIR=%s' % mkspecsdir + command += ' DTK_STATIC_LIB=YES' + command += ' DTK_STATIC_TRANSLATION=YES' + command += ' DTK_NO_MULTIMEDIA=YES' + command += ' %s' % self.source_folder + self.run(command) + self.run('jom clean') + self.run('jom') + self.run('jom install') + + def package(self): + self.deploy() + + outdir = self.build_folder + self.copy('*', dst='include', src=outdir+'/include') + self.copy('*.lib', dst='lib', src=outdir+'/lib') + self.copy('*', dst='mkspecs', src=outdir+'/mkspecs') + + def package_info(self): + self.cpp_info.libs = ['dtkcore'] + self.cpp_info.includedirs.append(self.extend_include_path()) + self.env_info.QMAKEPATH = self.cpp_info.rootpath + self.env_info.QMAKEFEATURES = self.cpp_info.rootpath + '/mkspecs/features' + + def deploy(self): + try: + content = [] + module_pri = self.build_folder + '/mkspecs/modules/qt_lib_dtkcore.pri' + s = open(module_pri) + for line in s.readlines(): + if line.startswith('QT.dtkcore.tools'): + line = 'QT.dtkcore.tools = %s\n' % ( + self.package_folder + '/bin') + elif line.startswith('QT.dtkcore.libs'): + line = 'QT.dtkcore.libs = %s\n' % ( + self.package_folder + '/lib') + elif line.startswith('QT.dtkcore.includes'): + line = 'QT.dtkcore.includes = %s\n' % ( + self.extend_include_path()) + content.append(line) + s.close() + + # print('create module file', content) + s = open(module_pri, 'w') + s.writelines(content) + except FileNotFoundError: + print('skip update qt module file') diff --git a/debian/api.json b/debian/api.json new file mode 100644 index 0000000..7fb6c81 --- /dev/null +++ b/debian/api.json @@ -0,0 +1,11 @@ +{"filepath":"src/ddesktopentry.h","functions":[{"uniquefunname":"_Bool DDesktopEntry::save()","funname":"DDesktopEntry::save","returntype":"_Bool","args":""},{"uniquefunname":"int DDesktopEntry::status()","funname":"DDesktopEntry::status","returntype":"int","args":""},{"uniquefunname":"int DDesktopEntry::keys(const int &)","funname":"DDesktopEntry::keys","returntype":"int","args":"const int &"},{"uniquefunname":"int DDesktopEntry::allGroups(_Bool)","funname":"DDesktopEntry::allGroups","returntype":"int","args":"_Bool"},{"uniquefunname":"_Bool DDesktopEntry::contains(const int &,const int &)","funname":"DDesktopEntry::contains","returntype":"_Bool","args":"const int &,const int &"},{"uniquefunname":"int DDesktopEntry::name()","funname":"DDesktopEntry::name","returntype":"int","args":""},{"uniquefunname":"int DDesktopEntry::genericName()","funname":"DDesktopEntry::genericName","returntype":"int","args":""},{"uniquefunname":"int DDesktopEntry::ddeDisplayName()","funname":"DDesktopEntry::ddeDisplayName","returntype":"int","args":""},{"uniquefunname":"int DDesktopEntry::comment()","funname":"DDesktopEntry::comment","returntype":"int","args":""},{"uniquefunname":"int DDesktopEntry::rawValue(const int &,const int &,const int &)","funname":"DDesktopEntry::rawValue","returntype":"int","args":"const int &,const int &,const int &"},{"uniquefunname":"int DDesktopEntry::stringValue(const int &,const int &,const int &)","funname":"DDesktopEntry::stringValue","returntype":"int","args":"const int &,const int &,const int &"},{"uniquefunname":"int DDesktopEntry::localizedValue(const int &,const int &,const int &,const int &)","funname":"DDesktopEntry::localizedValue","returntype":"int","args":"const int &,const int &,const int &,const int &"},{"uniquefunname":"int DDesktopEntry::localizedValue(const int &,const int &,const int &,const int &)","funname":"DDesktopEntry::localizedValue","returntype":"int","args":"const int &,const int &,const int &,const int &"},{"uniquefunname":"int DDesktopEntry::stringListValue(const int &,const int &)","funname":"DDesktopEntry::stringListValue","returntype":"int","args":"const int &,const int &"},{"uniquefunname":"_Bool DDesktopEntry::setRawValue(const int &,const int &,const int &)","funname":"DDesktopEntry::setRawValue","returntype":"_Bool","args":"const int &,const int &,const int &"},{"uniquefunname":"_Bool DDesktopEntry::setStringValue(const int &,const int &,const int &)","funname":"DDesktopEntry::setStringValue","returntype":"_Bool","args":"const int &,const int &,const int &"},{"uniquefunname":"_Bool DDesktopEntry::setLocalizedValue(const int &,const int &,const int &,const int &)","funname":"DDesktopEntry::setLocalizedValue","returntype":"_Bool","args":"const int &,const int &,const int &,const int &"},{"uniquefunname":"_Bool DDesktopEntry::removeEntry(const int &,const int &)","funname":"DDesktopEntry::removeEntry","returntype":"_Bool","args":"const int &,const int &"},{"uniquefunname":"int & DDesktopEntry::escape(int &)","funname":"DDesktopEntry::escape","returntype":"int &","args":"int &"},{"uniquefunname":"int & DDesktopEntry::escapeExec(int &)","funname":"DDesktopEntry::escapeExec","returntype":"int &","args":"int &"},{"uniquefunname":"int & DDesktopEntry::unescape(int &,_Bool)","funname":"DDesktopEntry::unescape","returntype":"int &","args":"int &,_Bool"},{"uniquefunname":"int & DDesktopEntry::unescapeExec(int &)","funname":"DDesktopEntry::unescapeExec","returntype":"int &","args":"int &"},{"uniquefunname":"_Bool DDesktopEntry::setStatus(const int &)","funname":"DDesktopEntry::setStatus","returntype":"_Bool","args":"const int &"}]} +{"filepath":"src/dsysinfo.h","functions":[{"uniquefunname":"int DSysInfo::Q_DECL_DEPRECATED_X()","funname":"DSysInfo::Q_DECL_DEPRECATED_X","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::distributionInfoPath()","funname":"DSysInfo::distributionInfoPath","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::distributionInfoSectionName(enum DSysInfo::OrgType)","funname":"DSysInfo::distributionInfoSectionName","returntype":"int","args":"enum DSysInfo::OrgType"},{"uniquefunname":"int DSysInfo::distributionOrgName(enum DSysInfo::OrgType,const int &)","funname":"DSysInfo::distributionOrgName","returntype":"int","args":"enum DSysInfo::OrgType,const int &"},{"uniquefunname":"int DSysInfo::Q_DECL_DEPRECATED_X()","funname":"DSysInfo::Q_DECL_DEPRECATED_X","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::distributionOrgWebsite(enum DSysInfo::OrgType)","funname":"DSysInfo::distributionOrgWebsite","returntype":"int","args":"enum DSysInfo::OrgType"},{"uniquefunname":"int DSysInfo::Q_DECL_DEPRECATED_X()","funname":"DSysInfo::Q_DECL_DEPRECATED_X","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::distributionOrgLogo(enum DSysInfo::OrgType,enum DSysInfo::LogoType,const int &)","funname":"DSysInfo::distributionOrgLogo","returntype":"int","args":"enum DSysInfo::OrgType,enum DSysInfo::LogoType,const int &"},{"uniquefunname":"int DSysInfo::Q_DECL_DEPRECATED_X()","funname":"DSysInfo::Q_DECL_DEPRECATED_X","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::operatingSystemName()","funname":"DSysInfo::operatingSystemName","returntype":"int","args":""},{"uniquefunname":"enum DSysInfo::ProductType DSysInfo::productType()","funname":"DSysInfo::productType","returntype":"enum DSysInfo::ProductType","args":""},{"uniquefunname":"int DSysInfo::productTypeString()","funname":"DSysInfo::productTypeString","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::productVersion()","funname":"DSysInfo::productVersion","returntype":"int","args":""},{"uniquefunname":"_Bool DSysInfo::isCommunityEdition()","funname":"DSysInfo::isCommunityEdition","returntype":"_Bool","args":""},{"uniquefunname":"int DSysInfo::computerName()","funname":"DSysInfo::computerName","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::cpuModelName()","funname":"DSysInfo::cpuModelName","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::memoryInstalledSize()","funname":"DSysInfo::memoryInstalledSize","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::memoryTotalSize()","funname":"DSysInfo::memoryTotalSize","returntype":"int","args":""},{"uniquefunname":"int DSysInfo::systemDiskSize()","funname":"DSysInfo::systemDiskSize","returntype":"int","args":""}]} +{"filepath":"src/filesystem/dtrashmanager.h","functions":[{"uniquefunname":"class DTrashManager * DTrashManager::instance()","funname":"DTrashManager::instance","returntype":"class DTrashManager *","args":""},{"uniquefunname":"_Bool DTrashManager::trashIsEmpty()","funname":"DTrashManager::trashIsEmpty","returntype":"_Bool","args":""},{"uniquefunname":"_Bool DTrashManager::cleanTrash()","funname":"DTrashManager::cleanTrash","returntype":"_Bool","args":""},{"uniquefunname":"_Bool DTrashManager::moveToTrash(const int &,_Bool)","funname":"DTrashManager::moveToTrash","returntype":"_Bool","args":"const int &,_Bool"}]} +{"filepath":"src/filesystem/private/dbasefilewatcher_p.h","functions":[{"uniquefunname":"_Bool DBaseFileWatcherPrivate::start()","funname":"DBaseFileWatcherPrivate::start","returntype":"_Bool","args":""},{"uniquefunname":"_Bool DBaseFileWatcherPrivate::stop()","funname":"DBaseFileWatcherPrivate::stop","returntype":"_Bool","args":""}]} +{"filepath":"src/filesystem/private/dfilesystemwatcher_dummy_p.h","functions":[{"uniquefunname":"void DFileSystemWatcherPrivate::_q_readFromInotify()","funname":"DFileSystemWatcherPrivate::_q_readFromInotify","returntype":"void","args":""},{"uniquefunname":"void DFileSystemWatcherPrivate::_q_readFromInotify()","funname":"DFileSystemWatcherPrivate::_q_readFromInotify","returntype":"void","args":""}]} +{"filepath":"src/filesystem/private/dfilesystemwatcher_linux_p.h","functions":[{"uniquefunname":"int DFileSystemWatcherPrivate::addPaths(const int &,int *,int *)","funname":"DFileSystemWatcherPrivate::addPaths","returntype":"int","args":"const int &,int *,int *"},{"uniquefunname":"int DFileSystemWatcherPrivate::removePaths(const int &,int *,int *)","funname":"DFileSystemWatcherPrivate::removePaths","returntype":"int","args":"const int &,int *,int *"},{"uniquefunname":"void DFileSystemWatcherPrivate::_q_readFromInotify()","funname":"DFileSystemWatcherPrivate::_q_readFromInotify","returntype":"void","args":""},{"uniquefunname":"void DFileSystemWatcherPrivate::onFileChanged(const int &,_Bool)","funname":"DFileSystemWatcherPrivate::onFileChanged","returntype":"void","args":"const int &,_Bool"},{"uniquefunname":"void DFileSystemWatcherPrivate::onDirectoryChanged(const int &,_Bool)","funname":"DFileSystemWatcherPrivate::onDirectoryChanged","returntype":"void","args":"const int &,_Bool"}]} +{"filepath":"src/filesystem/private/dfilesystemwatcher_win_p.h","functions":[{"uniquefunname":"void DFileSystemWatcherPrivate::_q_readFromInotify()","funname":"DFileSystemWatcherPrivate::_q_readFromInotify","returntype":"void","args":""},{"uniquefunname":"void DFileSystemWatcherPrivate::_q_readFromInotify()","funname":"DFileSystemWatcherPrivate::_q_readFromInotify","returntype":"void","args":""}]} +{"filepath":"src/util/drecentmanager.h","functions":[{"uniquefunname":"_Bool DRecentManager::addItem(const int &,int &)","funname":"DRecentManager::addItem","returntype":"_Bool","args":"const int &,int &"},{"uniquefunname":"void DRecentManager::removeItem(const int &)","funname":"DRecentManager::removeItem","returntype":"void","args":"const int &"},{"uniquefunname":"void DRecentManager::removeItems(const int &)","funname":"DRecentManager::removeItems","returntype":"void","args":"const int &"}]} +{"filepath":"src/util/dutil.h","functions":[{"uniquefunname":"void DUtil::TimerSingleShot(int,Func1)","funname":"DUtil::TimerSingleShot","returntype":"void","args":"int,Func1"},{"uniquefunname":"void DUtil::SecureErase(T *,int)","funname":"DUtil::SecureErase","returntype":"void","args":"T *,int"},{"uniquefunname":"void DUtil::SecureErase(T &)","funname":"DUtil::SecureErase","returntype":"void","args":"T &"}]} +{"filepath":"tests/dutils/dutiltester.h","functions":[{"uniquefunname":"void TestDUtil::testPathChange()","funname":"TestDUtil::testPathChange","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testDSingleton()","funname":"TestDUtil::testDSingleton","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testTimeFormatter()","funname":"TestDUtil::testTimeFormatter","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testTimeFormatterList()","funname":"TestDUtil::testTimeFormatterList","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testDiskFormatter()","funname":"TestDUtil::testDiskFormatter","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testDiskFormatterList()","funname":"TestDUtil::testDiskFormatterList","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testDiskFormatter1024()","funname":"TestDUtil::testDiskFormatter1024","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testDBusSender()","funname":"TestDUtil::testDBusSender","returntype":"void","args":""},{"uniquefunname":"void TestDUtil::testGroups()","funname":"TestDUtil::testGroups","returntype":"void","args":""}]} +{"filepath":"tests/dutils/singletontester.h","functions":[{"uniquefunname":"void Singleton::test()","funname":"Singleton::test","returntype":"void","args":""},{"uniquefunname":"void MultiSingletonTester::run()","funname":"MultiSingletonTester::run","returntype":"void","args":""}]} diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..63463dc --- /dev/null +++ b/debian/changelog @@ -0,0 +1,23 @@ +dtkcore (5.0.3) unstable; urgency=medium + + * Release 5.0.3 + + -- Deepin Packages Builder Tue, 21 Sep 2019 13:31:03 +0800 + +dtkcore (5.0.0) unstable; urgency=medium + + * Release 5.0.0 + + -- Deepin Packages Builder Tue, 03 Sep 2019 08:47:03 +0800 + +dtkcore (2.0.8) unstable; urgency=medium + + * Release 2.0.8 + + -- Deepin Packages Builder Wed, 02 May 2018 10:52:03 +0800 + +dtkcore (0.3.3-1) unstable; urgency=medium + + * Initial release + + -- Deepin Packages Builder Mon, 10 Oct 2016 16:58:07 +0800 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..0a5dde2 --- /dev/null +++ b/debian/control @@ -0,0 +1,34 @@ +Source: dtkcore +Section: libdevel +Priority: optional +Maintainer: Deepin Packages Builder +Build-Depends: debhelper (>= 9), pkg-config, + qttools5-dev-tools, qtbase5-private-dev, + libgsettings-qt-dev +Standards-Version: 3.9.8 + +Package: libdtkcore5 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, lshw +Multi-Arch: same +Description: Deepin Tool Kit Core library + DtkCore is base library of Deepin Qt/C++ applications. + . + This package contains the shared libraries. + +Package: libdtkcore5-bin +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + libdtkcore5( =${binary:Version}) +Description: Deepin Tool Kit Core Utilities + DtkCore is base devel library of Deepin Qt/C++ applications. + . + This package contains the utilities of DtkCore + +Package: libdtkcore-dev +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkcore5( =${binary:Version}) +Description: Deepin Tool Kit Core Devel library + DtkCore is base devel library of Deepin Qt/C++ applications. + . + This package contains the header files and static libraries of DtkCore diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..7a0c37f --- /dev/null +++ b/debian/copyright @@ -0,0 +1,22 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: dtkcore +Source: https://github.com/linuxdeepin/dtkcore + +Files: * +Copyright: 2017 Deepin Technology Co., Ltd. +License: LGPL-3+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU Lesser General + Public License version 3 can be found in "/usr/share/common-licenses/LGPL-3". diff --git a/debian/libdtkcore-dev.install b/debian/libdtkcore-dev.install new file mode 100644 index 0000000..f1f7613 --- /dev/null +++ b/debian/libdtkcore-dev.install @@ -0,0 +1,5 @@ +usr/lib/*/lib*.so +usr/include +usr/lib/*/pkgconfig/*.pc +usr/lib/*/cmake/*/*.cmake +usr/lib/*/qt5/* diff --git a/debian/libdtkcore5-bin.install b/debian/libdtkcore5-bin.install new file mode 100644 index 0000000..0ca22cc --- /dev/null +++ b/debian/libdtkcore5-bin.install @@ -0,0 +1 @@ +usr/lib/*/*/DCore/bin/* diff --git a/debian/libdtkcore5.install b/debian/libdtkcore5.install new file mode 100644 index 0000000..751f0dc --- /dev/null +++ b/debian/libdtkcore5.install @@ -0,0 +1,2 @@ +usr/lib/*/lib*.so.* +usr/share/glib-2.0/schemas diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..d13bf0f --- /dev/null +++ b/debian/rules @@ -0,0 +1,31 @@ +#!/usr/bin/make -f +DPKG_EXPORT_BUILDFLAGS = 1 +include /usr/share/dpkg/default.mk +export QT_SELECT = qt5 + +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + +ifneq (,$(wildcard .git/config)) + CONFIG_VERSION= +else +VERSION = $(DEB_VERSION_UPSTREAM) +_PACK_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$1}') +_BUILD_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$2}' | sed 's/[^0-9]//g') +ifeq ($(_BUILD_VER),) + CONFIG_VERSION = $(_PACK_VER) +else + CONFIG_VERSION = $(_PACK_VER).$(_BUILD_VER) +endif +endif + +%: + dh $@ --parallel + +override_dh_auto_configure: + dh_auto_configure -- LIB_INSTALL_DIR=/usr/lib/$(DEB_HOST_MULTIARCH) VERSION=$(CONFIG_VERSION) + +override_dh_auto_test: + echo "skip auto test" + +#override_dh_makeshlibs: +# dh_makeshlibs -V diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/debian/symbols.amd64 b/debian/symbols.amd64 new file mode 100644 index 0000000..502b661 --- /dev/null +++ b/debian/symbols.amd64 @@ -0,0 +1,909 @@ +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/doc/Specification.md b/doc/Specification.md new file mode 100644 index 0000000..94bf3a8 --- /dev/null +++ b/doc/Specification.md @@ -0,0 +1,81 @@ +# Deepin Application Specification {#Specification} + +Every application should keep the rule in this document. + +## 1. Application Information + +Application should set the property Organization-name and Application-name. + +Organization/Application name can contains alphabet, number and other visible ASCII code, BUT space MUST NOT appear in the name. And we do not approve +of no-ASCII code character in the Organization/Application name + +Application can stay Organization-name empty, but it should always set an Application-name. + +## 2. Standard Path + +The log, configure and runtime cache of Application should store in specific path. + +**If Organization-name is empty, "{Organization-name}/" would not appear in path.** + +### 2.1 User Application Standard Path + +As an application run for user session, the Standard path should be: + +````bash +XGD_LOG_HOME_DEEPIN: + Where deepin-user-specific log should be written. + XGD_USER_HOME/.log + +DAPP_CONFIG_HOME: + Where application-specific configurations should be written. + XDG_CONFIG_HOME/{Organization-name}/{Application-name} + +DAPP_LOG_HOME: + Where application-specific log should be written. + XGD_LOG_HOME_DEEPIN/{Organization-name}/{Application-name} + +DAPP_CACHE_HOME: + Where application-specific cache files should be written. + XGD_CACHE_HOME/{Organization-name}/{Application-name} + +DAPP_DATA_HOME: + Where application-specific data files should be written. + $XDG_DATA_HOME/{Organization-name}/{Application-name} + +```` + +Simple example: + +The dde-dock is offcial application of deepin and the standard path will be: + +````bash +DAPP_CONFIG_HOME: $HOME/.config/deepin/dde-dock +DAPP_LOG_HOME: $HOME/.log/deepin/dde-dock +DAPP_CACHE_HOME: $HOME/.cache/deepin/dde-dock +DAPP_DATA_HOME: $HOME/.local/share/deepin/dde-dock +```` + +### 2.2 System Application Standard Path + +Application run as system daemon, or with user with no home directory should place it's file in this standard path: + +````bash +DAPP_CONFIG_SYS: + /etc/{Organization-name}/{Application-name} + +DAPP_LOG_SYS: + /var/log/{Organization-name}/{Application-name} + +DAPP_DATA_SYS: + /usr/share/{Organization-name}/{Application-name} + +DAPP_CACHE_SYS: + /var/cache/{Organization-name}/{Application-name} +```` + + +Refs: + +[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html) + +[XDG Base Directory support](https://wiki.archlinux.org/index.php/XDG_Base_Directory_support) diff --git a/dtk_build_config.prf b/dtk_build_config.prf new file mode 100644 index 0000000..dd6a1ac --- /dev/null +++ b/dtk_build_config.prf @@ -0,0 +1,77 @@ +isEmpty(DTK_MODULE_NAME): error(set DTK_MODULE_NAME first) +!contains(DTK_MODULE_NAME, ^dtk[a-z0-9]+$): error(The format of the value of DTK_MODULE_NAME is incorrect. eg: dtk[a-z0-9]+) +!isEqual(DTK_MODULE_NAME, dtkcore):!contains(QT, dtkcore): error(QT += dtkcore first) + +#将首字母改为大写 +defineReplace(capitalizingString) { + RAW=$$1 + FIRST = $$upper($$section(RAW, "", 1, 1)) + OTHERS = $$section(RAW, "", 2, -1) + return($$FIRST$$OTHERS) +} + +defineTest(checkDtkVersion) { + isEmpty(VERSION) { + !isEqual(DTK_MODULE_NAME, dtkcore) { + VERSION = $${QT.dtkcore.VERSION} + } + + # TODO: failed in windows + isEmpty(VERSION): VERSION = $$system(git describe --tags --abbrev=0) + isEmpty(VERSION): VERSION = $$DTK_VERSION + isEmpty(VERSION): return(false) + VERSION = $$replace(VERSION, [^0-9.],) + } + + export(VERSION) + return(true) +} + +!checkDtkVersion():error("check dtk version failed") + +message("build dtk with version $$VERSION") +ver_list = $$split(VERSION, .) + +isEmpty(VER_MAJ) { + VER_MAJ = $$first(ver_list) +} +isEmpty(VER_MIN) { + VER_MIN = $$member(ver_list, 1, 1) + isEmpty(VER_MIN):VER_MIN = 0 +} +isEmpty(VER_PAT) { + VER_PAT = $$member(ver_list, 2, 2) + isEmpty(VER_PAT):VER_PAT = 0 +} +isEmpty(VER_BUI) { + VER_BUI = $$member(ver_list, 3, 3) + isEmpty(VER_BUI):VER_BUI = 0 +} + +isEmpty(PREFIX){ + PREFIX = /usr +} + +isEmpty(LIB_INSTALL_DIR) { + isEqual(DTK_MODULE_NAME, dtkcore) { + LIB_INSTALL_DIR=$$PREFIX/lib + } else { + LIB_INSTALL_DIR=$${QT.dtkcore.libs} + } +} + +LIB_VERSION_NAME = libdtk-$${VER_MAJ}.$${VER_MIN}.$${VER_PAT} +MODULE_NAME = $$upper($$member($$list($$split(DTK_MODULE_NAME,)), 3, 3))$$join($$list($$member($$list($$split(DTK_MODULE_NAME,)), 4, -1))) +DMODULE_NAME = D$${MODULE_NAME} + +isEmpty(TOOL_INSTALL_DIR) { + TOOL_INSTALL_DIR=$$LIB_INSTALL_DIR/$$LIB_VERSION_NAME/$$DMODULE_NAME/bin +} + +isEmpty(INCLUDE_INSTALL_DIR) { + isEqual(DTK_MODULE_NAME, dtkcore) { + INCLUDE_INSTALL_DIR = $$PREFIX/include/$$LIB_VERSION_NAME/$$DMODULE_NAME + } else { + INCLUDE_INSTALL_DIR = $${QT.dtkcore.includes}/../$$DMODULE_NAME + } +} diff --git a/dtkcore.pro b/dtkcore.pro new file mode 100644 index 0000000..1b7c66f --- /dev/null +++ b/dtkcore.pro @@ -0,0 +1 @@ +include($$PWD/src/dtk_lib.prf) diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100644 index 0000000..984ab9d --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += expintf-example diff --git a/examples/expintf-example/expintf-example.pro b/examples/expintf-example/expintf-example.pro new file mode 100644 index 0000000..5663a98 --- /dev/null +++ b/examples/expintf-example/expintf-example.pro @@ -0,0 +1,16 @@ +TEMPLATE = app +QT += dbus + +SOURCES += \ + $$PWD/main.cpp + +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 +INCLUDEPATH += $$PWD/../../src/base + +CONFIG(debug, debug|release) { + unix:QMAKE_RPATHDIR += $$OUT_PWD/../../src +} diff --git a/examples/expintf-example/main.cpp b/examples/expintf-example/main.cpp new file mode 100644 index 0000000..5af9bb6 --- /dev/null +++ b/examples/expintf-example/main.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd. + * + * Author: Chris Xiong + * + * Maintainer: Chris Xiong + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "util/dexportedinterface.h" + +#include +#include +#include +#include + +#include + +//#define ALTERNATE_USAGE + +DCORE_USE_NAMESPACE + +class CustomInterface : public DUtil::DExportedInterface +{ + QVariant invoke(const QString &action, const QString ¶meters) const + { + QJsonDocument d = QJsonDocument::fromJson(parameters.toUtf8()); + if (action == "pow") { + return QVariant(pow(d["a"].toDouble(), d["b"].toDouble())); + } + return QVariant(); + } +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QDBusConnection::sessionBus().registerService("com.deepin.ExpIntfTest"); + +#ifndef ALTERNATE_USAGE + DUtil::DExportedInterface *ei = new DUtil::DExportedInterface(); + ei->registerAction("quit", "quit the application", [&app](QString)->QVariant { + app.quit(); + return QVariant(); + }); + + ei->registerAction("answer", "answer to the ultimate question of life, the universe, and everything", + [](QString)->QVariant {return QVariant(42);}); + + ei->registerAction("sum", "returns the sum of two integers", [](QString p)->QVariant { + QJsonDocument d = QJsonDocument::fromJson(p.toUtf8()); + return QVariant(d["a"].toInt() + d["b"].toInt()); + }); +#else + CustomInterface *cei = new CustomInterface(); + cei->registerAction("pow", "raise a number to a power"); +#endif + + return app.exec(); +} diff --git a/rpm/dtkcore.spec b/rpm/dtkcore.spec new file mode 100644 index 0000000..5358875 --- /dev/null +++ b/rpm/dtkcore.spec @@ -0,0 +1,75 @@ +Name: dtkcore +Version: 5.2.2.3 +Release: 1%{?dist} +Summary: Deepin tool kit core modules +License: GPLv3 +URL: https://github.com/linuxdeepin/dtkcore +Source0: %{name}_%{version}.orig.tar.xz +BuildRequires: gcc-c++ +BuildRequires: annobin +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(gsettings-qt) +Obsoletes: deepin-tool-kit <= 0.3.3 +Obsoletes: deepin-tool-kit-devel <= 0.3.3 +Obsoletes: dtksettings <= 0.1.7 +Obsoletes: dtksettings-devel <= 0.1.7 + +%description +Deepin tool kit core modules. + +%package devel +Summary: Development package for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: qt5-qtbase-devel + +%description devel +Header files and libraries for %{name}. + +%prep +%setup -q + +sed -i 's|/lib|/libexec|' tools/settings/settings.pro +## consider relying on %%_qt5_bindir (see %%build below) instead of patching -- rex +#sed -i 's|qmake|qmake-qt5|' src/dtk_module.prf +#sed -i 's|lrelease|lrelease-qt5|' tools/script/dtk-translate.py src/dtk_translation.prf + +%build +# help find (and prefer) qt5 utilities, e.g. qmake, lrelease +export PATH=%{_qt5_bindir}:$PATH +%qmake_qt5 PREFIX=%{_prefix} \ + DTK_VERSION=%{version} \ + LIB_INSTALL_DIR=%{_libdir} \ + BIN_INSTALL_DIR=%{_libexecdir}/dtk5 \ + TOOL_INSTALL_DIR=%{_libexecdir}/dtk5 +%make_build + +%install +%make_install INSTALL_ROOT=%{buildroot} + +%ldconfig_scriptlets + +%files +%doc README.md +%license LICENSE +%{_libdir}/libdtkcore.so.* +%{_libexecdir}/dtk5/dtk-settings +%{_libexecdir}/dtk5/dtk-license.py* +%{_libexecdir}/dtk5/dtk-translate.py* +%{_libexecdir}/dtk5/deepin-os-release + +%files devel +%doc doc/Specification.md +%{_includedir}/libdtk-*/ +%{_qt5_archdatadir}/mkspecs/features/*.prf +%{_qt5_archdatadir}/mkspecs/modules/*.pri +%{_libdir}/cmake/Dtk/ +%{_libdir}/cmake/DtkCore/ +%{_libdir}/cmake/DtkCMake/ +%{_libdir}/cmake/DtkTools/ +%{_libdir}/pkgconfig/dtkcore.pc +%{_libdir}/libdtkcore.so +/usr/share/glib-2.0/schemas/* + +%changelog +* Thu Jun 11 2020 uoser - 5.2.2.3 +- Update to 5.2.2.3 diff --git a/src/DDesktopEntry b/src/DDesktopEntry new file mode 100644 index 0000000..847127a --- /dev/null +++ b/src/DDesktopEntry @@ -0,0 +1 @@ +#include "ddesktopentry.h" diff --git a/src/DSecureString b/src/DSecureString new file mode 100644 index 0000000..83f6c1a --- /dev/null +++ b/src/DSecureString @@ -0,0 +1 @@ +#include "dsecurestring.h" diff --git a/src/DSysInfo b/src/DSysInfo new file mode 100644 index 0000000..c026f58 --- /dev/null +++ b/src/DSysInfo @@ -0,0 +1 @@ +#include "dsysinfo.h" diff --git a/src/base/DObject b/src/base/DObject new file mode 100644 index 0000000..75fbcb7 --- /dev/null +++ b/src/base/DObject @@ -0,0 +1 @@ +#include "dobject.h" diff --git a/src/base/DObjectPrivate b/src/base/DObjectPrivate new file mode 100644 index 0000000..0c145c8 --- /dev/null +++ b/src/base/DObjectPrivate @@ -0,0 +1 @@ +#include "dobject_p.h" diff --git a/src/base/DSingleton b/src/base/DSingleton new file mode 100644 index 0000000..280d2f9 --- /dev/null +++ b/src/base/DSingleton @@ -0,0 +1 @@ +#include "dsingleton.h" diff --git a/src/base/base.pri b/src/base/base.pri new file mode 100644 index 0000000..fb8de9e --- /dev/null +++ b/src/base/base.pri @@ -0,0 +1,18 @@ +include($$PWD/private/private.pri) + +INCLUDEPATH += $$PWD/base +INCLUDEPATH += $$PWD/private + +HEADERS += \ + $$PWD/dobject.h \ + $$PWD/dsingleton.h + +SOURCES += \ + $$PWD/dobject.cpp + +includes.files += $$PWD/*.h +includes.files += $$PWD/private/*.h +includes.files += \ + $$PWD/DObject \ + $$PWD/DObjectPrivate \ + $$PWD/DSingleton diff --git a/src/base/dobject.cpp b/src/base/dobject.cpp new file mode 100644 index 0000000..778457d --- /dev/null +++ b/src/base/dobject.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2015 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dobject.h" +#include "private/dobject_p.h" + +DCORE_BEGIN_NAMESPACE + +DObjectPrivate::DObjectPrivate(DObject *qq) + : q_ptr(qq) +{ + +} + +DObjectPrivate::~DObjectPrivate() +{ + +} + +/*! + * \~chinese \file dobject.h + * \~chinese \brief 一些宏的定义 +*/ + +/*! + * \~chinese \def D_DECLARE_PRIVATE(Class) + * + * \~chinese \brief 这个宏一定要放到类的私有区域,它定义了 d_func() 这个函数用于返回私有类的对象, + * \~chinese 这个对象只应该在类的内部使用,另外将私有类声明为公开类的友元类。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PUBLIC D_D D_DC +*/ + +/*! + * \~chinese \def D_DECLARE_PUBLIC(Class) + * + * \~chinese \brief 这个宏用于私有类中,它定义了 q_func() 这个函数用于返回公开类的对象,另外将公开类 + * \~chinese 声明为私有类的友元类。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PRIVATE D_Q D_QC +*/ + +/*! + * \~chinese \def D_D(Class) + * + * \~chinese \brief 这个宏用于公开类中,它定义了一个名字为 d 的变量存储 d_func() 的返回值。用于在公开 + * \~chinese 类中需要访问私有类的数据成员的函数中。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PRVATE D_DC +*/ + +/*! + * \~chinese \def D_DC(Class) + * + * \~chinese \brief 同 D_D,用在公开类加了 const 修饰符的成员函数中。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PRVATE D_D +*/ + +/*! + * \~chinese \def D_Q(Class) + * + * \~chinese \brief 这个宏用于私有类中,它定义了一个名字为 q 的变量存储 q_func() 的返回值。用于在私有 + * \~chinese 类中需要调用公开类的成员函数时。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PUBLIC D_QC +*/ + +/*! + * \~chinese \def D_QC(Class) + * + * \~chinese \brief 同 D_Q,用在私有类加了 const 修饰符的成员函数中。 + * \~chinese \param Class 公开类的类名 + * \~chinese \sa D_DECLARE_PUBLIC D_Q +*/ + +/*! + * \~chinese \def D_PRIVATE_SLOT(Func) + * + * \~chinese \brief 同 Q_PRIVATE_SLOT,用在继承了 QObject 的公开类中,在公开类中定一个槽函数,且函数 + * \~chinese 必须在私有类中有实现。用这个方式定义的槽函数无法被直接调用,只能用于 QObject::connect + * \~chinese 使用 SIGNAL 和 SLOT 的方式连接信号,或者使用 QMetaObject::invokeMethod 调用。 + * \~chinese 一般来讲,这个槽函数应该只在类内部使用,外界不应该通过任何方式来调用它。 + * + * \~chinese 例子: + * + * \~chinese a.h + * \code + * class APrivate; + * class A : public DObject + * { + * D_DECLARE_PRIVATE(A) + * public: + * A(); + * + * protected: + * A(APrivate &dd, DObject *parent = nullptr); + * + * private: + * D_PRIVATE_SLOT(void _q_testSlot() const) + * }; + * \endcode + * \~chinese a.cpp + * \code + * class APrivate : public DObjectPrivate + * { + * public: + * D_DECLARE_PUBLIC(A) + * + * APrivate(A *qq) + * : DObjectPrivate(qq) + * { + * QTimer *timer = new QTimer(); + * QObject::connect(timer, SIGNAL(timeout()), qq, SLOT(_q_testSlot())); + * timer->start(1000); + * } + * + * void _q_testSlot() const + * { + * qDebug() << "slot"; + * } + * }; + * + * A::A() + * : DObject(*new APrivate(this)) + * { + * + * } + * + * A::A(APrivate &dd, DObject *parent) + * : DObject(dd, parent) + * { + * + * } + * + * #include "moc_a.cpp" + * \endcode + * \~chinese \param Func 槽函数的完整签名 + * \~chinese \note 添加或更新私有槽之后需要重新手动调用 qmake + * \~chinese \sa D_DECLARE_PUBLIC D_Q +*/ + +/*! + * \~chinese \class DObject + * \~chinese \brief deepin-tool-kit 中所有公开类的祖先类。 + * + * \~chinese 通过和 \ref D_DECLARE_PRIVATE 、\ref D_DECLARE_PUBLIC + * \~chinese 等宏的配合方便派生类中实现 D-Point 结构。虽然 QObject 中已经有了这样的实现结构,但是没有 + * \~chinese 办法在不使用 Qt 私有模块的情况下,在 DTK 库中达到同样的目的。D-Point 结构由“公共接口类” + * \~chinese 和“私有数据类”两部分组成,在 DTK 中,DObjectPrivate 是所有数据类的祖先类。在这种结构下, + * \~chinese 只有 DObject 这个基类中定了一个指向于私有数据类的对象指针,派生类中不会也不应该再定义任何 + * \~chinese 成员变量,派生类中需要添加数据成员时,可以继承 DObjectPrivate,将新的成员变量放到私有类中 + * + * \~chinese 例子: + * + * \~chinese a.h + * \code + * class APrivate; + * class A : public DObject + * { + * D_DECLARE_PRIVATE(A) + * public: + * A(); + * int test() const; + * + * protected: + * A(APrivate &dd, DObject *parent = nullptr); + * }; + * \endcode + * \~chinese a.cpp + * \code + * class APrivate : public DObjectPrivate + * { + * public: + * APrivate(A *qq) + * : DObjectPrivate(qq) + * { + * + * } + * + * D_DECLARE_PUBLIC(A) + * // 此处添加数据成员 + * int data; + * }; + * + * A::A() + * : DObject(*new APrivate(this)) + * { + * + * } + * + * int test() const + * { + * D_D(A); + * + * return d->data; + * } + * + * A::A(APrivate &dd, DObject *parent) + * : DObject(dd, parent) + * { + * + * } + * \endcode + * 一般来讲,DObject 只会用在 DTK 库中定义的类,对于使用 DTK 库的应用程序来说不用关心它的存在 + * \~chinese \sa \href{https://wiki.qt.io/D-Pointer/zh,类的 D-Point 结构} + */ + +/*! + * \~chinese \brief 只有在不需要数据成员的派生类中才会使用 + */ +DObject::DObject(DObject * /*parent = nullptr*/) +{ + +} + +/*! + * \~chinese \brief 在派生类中比较常用的构造函数 + * \~chinese \param dd 私有类对象 + */ +DObject::DObject(DObjectPrivate &dd, DObject * /*parent = nullptr*/): + d_d_ptr(&dd) +{ + +} + +DObject::~DObject() +{ + +} + +DCORE_END_NAMESPACE diff --git a/src/base/dobject.h b/src/base/dobject.h new file mode 100644 index 0000000..d981d40 --- /dev/null +++ b/src/base/dobject.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DOBJECT_H +#define DOBJECT_H + +#include + +#include "dtkcore_global.h" + +DCORE_BEGIN_NAMESPACE + +#define D_DECLARE_PRIVATE(Class) Q_DECLARE_PRIVATE_D(qGetPtrHelper(d_d_ptr),Class) +#define D_DECLARE_PUBLIC(Class) Q_DECLARE_PUBLIC(Class) +#define D_D(Class) Q_D(Class) +#define D_Q(Class) Q_Q(Class) +#define D_DC(Class) Q_D(const Class) +#define D_QC(Class) Q_Q(const Class) +#define D_PRIVATE_SLOT(Func) Q_PRIVATE_SLOT(d_func(), Func) + +class DObjectPrivate; + +class LIBDTKCORESHARED_EXPORT DObject +{ +protected: + DObject(DObject *parent = nullptr); + + DObject(DObjectPrivate &dd, DObject *parent = nullptr); + + virtual ~DObject(); + + QScopedPointer d_d_ptr; + + Q_DISABLE_COPY(DObject) + D_DECLARE_PRIVATE(DObject) +}; + +DCORE_END_NAMESPACE + +#endif // DOBJECT_H diff --git a/src/base/dsingleton.h b/src/base/dsingleton.h new file mode 100644 index 0000000..fcb016c --- /dev/null +++ b/src/base/dsingleton.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DSINGLETON_H +#define DSINGLETON_H + +#include "dtkcore_global.h" + +DCORE_BEGIN_NAMESPACE + +/*! + * \~english a simple singleton template for std c++ 11 or later. + * + * example: + +``` + class ExampleSingleton : public QObject, public Dtk::DSingleton + { + Q_OBJECT + friend class DSingleton; + }; +``` + + * \note: for Qt, "public DSingleton" must be after QObject. + */ + + +/*! + * \~chinese 通过c++11的特性实现的单例模板 + * + * 使用示例: + +``` + class ExampleSingleton : public QObject, public Dtk::DSingleton + { + Q_OBJECT + friend class DSingleton; + }; +``` + + * \note 对于Qt程序 public DSingleton" 必须在卸载QObject后面出现。 + */ + +template +class DSingleton +{ +public: + static inline T *instance() + { + static T *_instance = new T; + return _instance; + } + +protected: + DSingleton(void) {} + ~DSingleton(void) {} + DSingleton(const DSingleton &) {} + DSingleton &operator= (const DSingleton &) {} +}; + +DCORE_END_NAMESPACE + +#endif // DSINGLETON_H diff --git a/src/base/private/dobject_p.h b/src/base/private/dobject_p.h new file mode 100644 index 0000000..30bdee5 --- /dev/null +++ b/src/base/private/dobject_p.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DOBJECT_P_H +#define DOBJECT_P_H + +#include "dtkcore_global.h" + +DCORE_BEGIN_NAMESPACE + +class DObject; +class DObjectPrivate +{ +public: + virtual ~DObjectPrivate(); + +protected: + DObjectPrivate(DObject *qq); + + DObject *q_ptr; + + Q_DECLARE_PUBLIC(DObject) +}; + +DCORE_END_NAMESPACE + +#endif // DOBJECT_P_H + diff --git a/src/base/private/private.pri b/src/base/private/private.pri new file mode 100644 index 0000000..5de92e3 --- /dev/null +++ b/src/base/private/private.pri @@ -0,0 +1,2 @@ +HEADERS += \ + $$PWD/dobject_p.h diff --git a/src/com.deepin.dtk.gschema.xml b/src/com.deepin.dtk.gschema.xml new file mode 100644 index 0000000..3010ad8 --- /dev/null +++ b/src/com.deepin.dtk.gschema.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + 'UnknownType' + application palette type + Palette type of the application. SystemTheme=0 LightTheme=1 DarkTheme=2 + + + diff --git a/src/ddesktopentry.cpp b/src/ddesktopentry.cpp new file mode 100644 index 0000000..247078a --- /dev/null +++ b/src/ddesktopentry.cpp @@ -0,0 +1,1043 @@ +/* + * Copyright (C) 2019 Deepin Technology Co., Ltd. + * 2019 Gary Wang + * + * Author: Gary Wang + * + * Maintainer: Gary Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "ddesktopentry.h" + +#include +#include +#include +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +enum { Space = 0x1, Special = 0x2 }; + +static const char charTraits[256] = { + // Space: '\t', '\n', '\r', ' ' + // Special: '\n', '\r', ';', '=', '\\', '#' + // Please note that '"' is NOT a special character + + 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, Space | Special, 0, 0, Space | Special, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Space, 0, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, Special, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +bool readLineFromData(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen, int &equalsPos) +{ + int dataLen = data.length(); + + equalsPos = -1; + + lineStart = dataPos; + while (lineStart < dataLen && (charTraits[uint(uchar(data.at(lineStart)))] & Space)) + ++lineStart; + + int i = lineStart; + while (i < dataLen) { + while (!(charTraits[uint(uchar(data.at(i)))] & Special)) { + if (++i == dataLen) + goto break_out_of_outer_loop; + } + + char ch = data.at(i++); + if (ch == '=') { + if (equalsPos == -1) + equalsPos = i - 1; + } else if (ch == '\n' || ch == '\r') { + if (i == lineStart + 1) { + ++lineStart; + } else { + --i; + goto break_out_of_outer_loop; + } + } else if (ch == '\\') { + if (i < dataLen) { + char ch = data.at(i++); + if (i < dataLen) { + char ch2 = data.at(i); + // \n, \r, \r\n, and \n\r are legitimate line terminators in INI files + if ((ch == '\n' && ch2 == '\r') || (ch == '\r' && ch2 == '\n')) + ++i; + } + } + } else if (ch == ';') { + // The multiple values should be separated by a semicolon and the value of the key + // may be optionally terminated by a semicolon. Trailing empty strings must always + // be terminated with a semicolon. Semicolons in these values need to be escaped + // using \; . + // Don't need to do anything here. + } else { + Q_ASSERT(ch == '#'); + + if (i == lineStart + 1) { + char ch; + while (i < dataLen && (((ch = data.at(i)) != '\n') && ch != '\r')) + ++i; + lineStart = i; + } + } + } + +break_out_of_outer_loop: + dataPos = i; + lineLen = i - lineStart; + return lineLen > 0; +} + +QString &doEscape(QString& str, const QHash &repl) +{ + // First we replace slash. + str.replace(QLatin1Char('\\'), QLatin1String("\\\\")); + + QHashIterator i(repl); + while (i.hasNext()) { + i.next(); + if (i.key() != QLatin1Char('\\')) + str.replace(i.key(), QString::fromLatin1("\\\\%1").arg(i.value())); + } + + return str; +} + +QString &doUnescape(QString& str, const QHash &repl) +{ + int n = 0; + while (1) { + n=str.indexOf(QLatin1String("\\"), n); + if (n < 0 || n > str.length() - 2) + break; + + if (repl.contains(str.at(n+1))) { + str.replace(n, 2, repl.value(str.at(n+1))); + } + + n++; + } + + return str; +} + +/*! \internal */ +class DDesktopEntrySection +{ +public: + DDesktopEntrySection() {} + + QString name; + QMap valuesMap; + QByteArray unparsedDatas; + int sectionPos = 99; + + inline operator QString() const { + return QLatin1String("DDesktopEntrySection(") + name + QLatin1String(")"); + } + + QByteArray sectionData() const { + if (unparsedDatas.isEmpty()) { + // construct data and return + QByteArray data; + + data.append(QString("[%1]\n").arg(name)); + + QMap::const_iterator i; + for (i = valuesMap.begin(); i != valuesMap.end(); i++) { + data.append(QString("%1=%2\n").arg(i.key(), i.value())); + } + + return data; + } else { + return unparsedDatas; + } + } + + bool ensureSectionDataParsed() { + if (unparsedDatas.isEmpty()) return true; + + valuesMap.clear(); + + // for readLineFromFileData() + int dataPos = 0; + int lineStart; + int lineLen; + int equalsPos; + + while(readLineFromData(unparsedDatas, dataPos, lineStart, lineLen, equalsPos)) { + if (unparsedDatas.at(lineStart) == '[') continue; // section name already parsed + + if (equalsPos != -1) { + QString key = unparsedDatas.mid(lineStart, equalsPos - lineStart).trimmed(); + QString rawValue = unparsedDatas.mid(equalsPos + 1, lineStart + lineLen - equalsPos - 1).trimmed(); + + valuesMap[key] = rawValue; + } + } + + unparsedDatas.clear(); + + return true; + } + + bool contains(const QString &key) const { + const_cast(this)->ensureSectionDataParsed(); + return valuesMap.contains(key); + } + + QStringList allKeys() const { + const_cast(this)->ensureSectionDataParsed(); + return valuesMap.keys(); + } + + QString get(const QString &key, QString &defaultValue) { + if (this->contains(key)) { + return valuesMap[key]; + } else { + return defaultValue; + } + } + + bool set(const QString &key, const QString &value) { + if (this->contains(key)) { + valuesMap.remove(key); + } + valuesMap[key] = value; + return true; + } + + bool remove(const QString &key) { + if (this->contains(key)) { + valuesMap.remove(key); + return true; + } + return false; + } +}; + +typedef QMap SectionMap; + +class DDesktopEntryPrivate +{ +public: + DDesktopEntryPrivate(const QString &filePath, DDesktopEntry *qq); + ~DDesktopEntryPrivate(); + + bool isWritable() const; + bool fuzzyLoad(); + bool initSectionsFromData(const QByteArray &data); + void setStatus(const DDesktopEntry::Status &newStatus) const; + bool write(QIODevice &device) const; + + int sectionPos(const QString §ionName) const; + bool contains(const QString §ionName, const QString &key) const; + QStringList keys(const QString §ionName) const; + bool get(const QString §ionName, const QString &key, QString *value); + bool set(const QString §ionName, const QString &key, const QString &value); + bool remove(const QString §ionName, const QString &key); + +protected: + QString filePath; + QMutex fileMutex; + SectionMap sectionsMap; + mutable DDesktopEntry::Status status; + +private: + bool __padding[4]; + DDesktopEntry *q_ptr = nullptr; + + Q_DECLARE_PUBLIC(DDesktopEntry) +}; + +DDesktopEntryPrivate::DDesktopEntryPrivate(const QString &filePath, DDesktopEntry *qq) + : filePath(filePath), q_ptr(qq) +{ + fuzzyLoad(); +} + +DDesktopEntryPrivate::~DDesktopEntryPrivate() +{ + +} + +bool DDesktopEntryPrivate::isWritable() const +{ + QFileInfo fileInfo(filePath); + +#ifndef QT_NO_TEMPORARYFILE + if (fileInfo.exists()) { +#endif + QFile file(filePath); + return file.open(QFile::ReadWrite); +#ifndef QT_NO_TEMPORARYFILE + } else { + // Create the directories to the file. + QDir dir(fileInfo.absolutePath()); + if (!dir.exists()) { + if (!dir.mkpath(dir.absolutePath())) + return false; + } + + // we use a temporary file to avoid race conditions + QTemporaryFile file(filePath); + return file.open(); + } +#endif +} + +bool DDesktopEntryPrivate::fuzzyLoad() +{ + QFile file(filePath); + QFileInfo fileInfo(filePath); + + if (fileInfo.exists() && !file.open(QFile::ReadOnly)) { + setStatus(DDesktopEntry::AccessError); + return false; + } + + if (file.isReadable() && file.size() != 0) { + bool ok = false; + QByteArray data = file.readAll(); + + ok = initSectionsFromData(data); + + if (!ok) { + setStatus(DDesktopEntry::FormatError); + return false; + } + } + + return true; +} + +bool DDesktopEntryPrivate::initSectionsFromData(const QByteArray &data) +{ + sectionsMap.clear(); + + QString lastSectionName; + int lastSectionStart = 0; + bool formatOk = true; + int sectionIdx = 0; + // for readLineFromFileData() + int dataPos = 0; + int lineStart; + int lineLen; + int equalsPos; + + auto commitSection = [=](const QString &name, int sectionStartPos, int sectionLength, int sectionIndex) { + DDesktopEntrySection lastSection; + lastSection.name = name; + lastSection.unparsedDatas = data.mid(sectionStartPos, sectionLength); + lastSection.sectionPos = sectionIndex; + sectionsMap[name] = lastSection; + }; + + // TODO: here we only need to find the section start, so things like equalsPos are useless here. + // maybe we can do some optimization here via adding extra argument to readLineFromData(). + while(readLineFromData(data, dataPos, lineStart, lineLen, equalsPos)) { + // qDebug() << "CurrentLine:" << data.mid(lineStart, lineLen); + if (data.at(lineStart) == '[') { + // commit the last section we've ever read before we read the new one. + if (!lastSectionName.isEmpty()) { + commitSection(lastSectionName, lastSectionStart, lineStart - lastSectionStart, sectionIdx); + sectionIdx++; + } + // process section name line + QByteArray sectionName; + int idx = data.indexOf(']', lineStart); + if (idx == -1 || idx >= lineStart + lineLen) { + qWarning() << "Bad desktop file format while reading line:" << data.mid(lineStart, lineLen); + formatOk = false; + sectionName = data.mid(lineStart + 1, lineLen - 1).trimmed(); + } else { + sectionName = data.mid(lineStart + 1, idx - lineStart - 1).trimmed(); + } + lastSectionName = sectionName; + lastSectionStart = lineStart; + } + } + + Q_ASSERT(lineStart == data.length()); + if (!lastSectionName.isEmpty()) { + commitSection(lastSectionName, lastSectionStart, lineStart - lastSectionStart, sectionIdx); + } + + return formatOk; +} + +// Always keep the first meet error status. and allowed clear the status. +void DDesktopEntryPrivate::setStatus(const DDesktopEntry::Status &newStatus) const +{ + if (newStatus == DDesktopEntry::NoError || this->status == DDesktopEntry::NoError) { + this->status = newStatus; + } +} + +bool DDesktopEntryPrivate::write(QIODevice &device) const +{ + Q_Q(const DDesktopEntry); + + QStringList sortedKeys = q->allGroups(true); + + for (const QString &key : sortedKeys) { + qint64 ret = device.write(sectionsMap[key].sectionData()); + if (ret == -1) return false; + } + + return true; +} + +int DDesktopEntryPrivate::sectionPos(const QString §ionName) const +{ + if (sectionsMap.contains(sectionName)) { + return sectionsMap[sectionName].sectionPos; + } + + return -1; +} + +bool DDesktopEntryPrivate::contains(const QString §ionName, const QString &key) const +{ + if (sectionName.isNull() || key.isNull()) { + return false; + } + + if (sectionsMap.contains(sectionName)) { + return sectionsMap[sectionName].contains(key); + } + + return false; +} + +QStringList DDesktopEntryPrivate::keys(const QString §ionName) const +{ + if (sectionName.isNull()) { + return {}; + } + + if (sectionsMap.contains(sectionName)) { + return sectionsMap[sectionName].allKeys(); + } + + return {}; +} + +// return true if we found the value, and set the value to *value +bool DDesktopEntryPrivate::get(const QString §ionName, const QString &key, QString *value) +{ + if (!this->contains(sectionName, key)) { + return false; + } + + if (sectionsMap.contains(sectionName)) { + QString &&result = sectionsMap[sectionName].get(key, *value); + *value = result; + return true; + } + + return false; +} + +bool DDesktopEntryPrivate::set(const QString §ionName, const QString &key, const QString &value) +{ + if (sectionsMap.contains(sectionName)) { + bool result = sectionsMap[sectionName].set(key, value); + return result; + } else { + // create new section. + DDesktopEntrySection newSection; + newSection.name = sectionName; + newSection.set(key, value); + sectionsMap[sectionName] = newSection; + return true; + } + + return false; +} + +bool DDesktopEntryPrivate::remove(const QString §ionName, const QString &key) +{ + if (this->contains(sectionName, key)) { + return sectionsMap[sectionName].remove(key); + } + return false; +} + +/*! + * \class DDesktopEntry + * \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. + * + * For more details about the spec itself, please refer to: + * https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html + */ + +DDesktopEntry::DDesktopEntry(const QString &filePath) noexcept + : d_ptr(new DDesktopEntryPrivate(filePath, this)) +{ + +} + +DDesktopEntry::~DDesktopEntry() +{ + +} + +/*! + * \brief Write back data to the desktop entry file. + * \return true if write success; otherwise returns false. + */ +bool DDesktopEntry::save() const +{ + Q_D(const DDesktopEntry); + + // write to file. + if (d->isWritable()) { + bool ok = false; + bool createFile = false; + QFileInfo fileInfo(d->filePath); + +#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile) + QSaveFile sf(d->filePath); + sf.setDirectWriteFallback(true); +#else + QFile sf(d->filePath); +#endif + if (!sf.open(QIODevice::WriteOnly)) { + d->setStatus(DDesktopEntry::AccessError); + return false; + } + + ok = d->write(sf); + +#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile) + if (ok) { + ok = sf.commit(); + } +#endif + + if (ok) { + // If we have created the file, apply the file perms + if (createFile) { + QFile::Permissions perms = fileInfo.permissions() | QFile::ReadOwner | QFile::WriteOwner + | QFile::ReadGroup | QFile::ReadOther; + QFile(d->filePath).setPermissions(perms); + } + return true; + } else { + d->setStatus(DDesktopEntry::AccessError); + return false; + } + } + + return false; +} + +/*! + * \brief Get data parse status + * + * 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. + */ +DDesktopEntry::Status DDesktopEntry::status() const +{ + Q_D(const DDesktopEntry); + return d->status; +} + +/*! + * \brief Get a list of all section keys inside the given \a section. + * + * \return all available section keys. + */ +QStringList DDesktopEntry::keys(const QString §ion) const +{ + Q_D(const DDesktopEntry); + + if (section.isEmpty()) { + qWarning("DDesktopEntry::keys: Empty section name passed"); + return {}; + } + + return d->keys(section); +} + +/*! + * \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. + */ +QStringList DDesktopEntry::allGroups(bool sorted) const +{ + Q_D(const DDesktopEntry); + + if (!sorted) { + return d->sectionsMap.keys(); + } else { + using StrIntPair = QPair; + + QStringList keys = d->sectionsMap.keys(); + QList result; + + for (const QString & key : keys) { + result << StrIntPair(key, d->sectionPos(key)); + } + + std::sort(result.begin(), result.end(), [](const StrIntPair& a, const StrIntPair& b) -> bool { + return a.second < b.second; + }); + + keys.clear(); + + for (const StrIntPair& pair : result) { + keys << pair.first; + } + + return keys; + } +} + +/*! + * \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. + */ +bool DDesktopEntry::contains(const QString &key, const QString §ion) const +{ + Q_D(const DDesktopEntry); + + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::contains: Empty key or section passed"); + return false; + } + + return d->contains(section, key); +} + +/*! + * \brief Returns the localized string value of the "Name" key under "Desktop Entry" section. + * + * It's equivalent to calling localizedValue("Name"). + * + * \sa localizedValue(), genericName(), ddeDisplayName() + */ +QString DDesktopEntry::name() const +{ + return localizedValue(QStringLiteral("Name")); +} + +/*! + * \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. + * + * \sa localizedValue(), name(), ddeDisplayName() + */ +QString DDesktopEntry::genericName() const +{ + return localizedValue(QStringLiteral("GenericName")); +} + +/*! + * \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". + * + * \sa localizedValue(), name(), genericName() + */ +QString DDesktopEntry::ddeDisplayName() const +{ + QString deepinVendor = stringValue("X-Deepin-Vendor"); + QString genericNameStr = genericName(); + if (deepinVendor == QStringLiteral("deepin") && !genericNameStr.isEmpty()) { + return genericNameStr; + } + + return name(); +} + +/*! + * \brief Returns the localized string value of the "Comment" key under "Desktop Entry" section. + * + * It's equivalent to calling localizedValue("Comment"). + * + * \sa localizedValue() + */ +QString DDesktopEntry::comment() const +{ + return localizedValue(QStringLiteral("Comment")); +} + +/*! + * \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 default-constructed value. + * + * \sa setRawValue(), stringValue(), localizedValue(), stringListValue() + */ +QString DDesktopEntry::rawValue(const QString &key, const QString §ion, const QString &defaultValue) const +{ + Q_D(const DDesktopEntry); + QString result = defaultValue; + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::value: Empty key or section passed"); + return result; + } + const_cast(d)->get(section, key, &result); // FIXME: better way than const_cast? + return result; +} + +/*! + * \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 default-constructed value. + * + * \sa setStringValue(), rawValue(), localizedValue(), stringListValue() + */ +QString DDesktopEntry::stringValue(const QString &key, const QString §ion, const QString &defaultValue) const +{ + QString rawResult = rawValue(key, section, defaultValue); + rawResult = DDesktopEntry::unescape(rawResult); + return rawResult; +} + +/*! + * \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 default-constructed value. + * + * \sa setLocalizedValue(), rawValue(), stringValue(), stringListValue() + */ +QString DDesktopEntry::localizedValue(const QString &key, const QString &localeKey, const QString §ion, const QString &defaultValue) const +{ + Q_D(const DDesktopEntry); + QString result = defaultValue; + QString actualLocaleKey = QLatin1String("C"); + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::localizedValue: Empty key or section passed"); + return result; + } + + QStringList possibleKeys; + + if (!localeKey.isEmpty()) { + if (localeKey == "empty") { + possibleKeys << key; + } else if (localeKey == "default") { + possibleKeys << QString("%1[%2]").arg(key, QLocale().name()); + } else if (localeKey == "system") { + possibleKeys << QString("%1[%2]").arg(key, QLocale::system().name()); + } else { + possibleKeys << QString("%1[%2]").arg(key, localeKey); + } + } + + if (!actualLocaleKey.isEmpty()) { + possibleKeys << QString("%1[%2]").arg(key, actualLocaleKey); + } + possibleKeys << QString("%1[%2]").arg(key, "C"); + possibleKeys << key; + + for (const QString &oneKey : possibleKeys) { + if (d->contains(section, oneKey)) { + const_cast(d)->get(section, oneKey, &result); + break; + } + } + + return result; +} + +/*! + * \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. + * + * \sa setLocalizedValue(), rawValue(), stringValue(), stringListValue() + */ +QString DDesktopEntry::localizedValue(const QString &key, const QLocale &locale, const QString §ion, const QString &defaultValue) const +{ + return localizedValue(key, locale.name(), section, defaultValue); +} + +/*! + * \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. + * + * \sa setRawValue(), rawValue(), stringValue(), localizedValue() + */ +QStringList DDesktopEntry::stringListValue(const QString &key, const QString §ion) const +{ + Q_D(const DDesktopEntry); + + QString value; + + const_cast(d)->get(section, key, &value); + + if (value.endsWith(';')) { + value = value.left(value.length() - 1); + } + QStringList&& strings = value.split(';'); + + QString combine; + QStringList result; + for (QString oneStr : strings) { + if (oneStr.endsWith('\\')) { + combine = combine + oneStr + ';'; + continue; + } + if (!combine.isEmpty()) { + oneStr = combine + oneStr; + combine.clear(); + } + result << DDesktopEntry::unescape(oneStr, true); + } + + return result; +} + +bool DDesktopEntry::setRawValue(const QString &value, const QString &key, const QString §ion) +{ + Q_D(DDesktopEntry); + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::setRawValue: Empty key or section passed"); + return false; + } + + bool result = d->set(section, key, value); + return result; +} + +bool DDesktopEntry::setStringValue(const QString &value, const QString &key, const QString §ion) +{ + QString escapedValue = value; + DDesktopEntry::escape(escapedValue); + bool result = setRawValue(escapedValue, key, section); + return result; +} + +bool DDesktopEntry::setLocalizedValue(const QString &value, const QString &localeKey, const QString &key, const QString §ion) +{ + Q_D(DDesktopEntry); + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::setLocalizedValue: Empty key or section passed"); + return false; + } + + QString actualKey = localeKey.isEmpty() ? key : QString("%1[%2]").arg(key, localeKey); + + bool result = d->set(section, actualKey, value); + return result; +} + +bool DDesktopEntry::removeEntry(const QString &key, const QString §ion) +{ + Q_D(DDesktopEntry); + if (key.isEmpty() || section.isEmpty()) { + qWarning("DDesktopEntry::setLocalizedValue: Empty key or section passed"); + return false; + } + bool result = d->remove(section, key); + return result; +} + +/************************************************ + The escape sequences \s, \n, \t, \r, and \\ are supported for values + of type string and localestring, meaning ASCII space, newline, tab, + carriage return, and backslash, respectively. + ************************************************/ +QString &DDesktopEntry::escape(QString &str) +{ + QHash repl; + repl.insert(QLatin1Char('\n'), QLatin1Char('n')); + repl.insert(QLatin1Char('\t'), QLatin1Char('t')); + repl.insert(QLatin1Char('\r'), QLatin1Char('r')); + + return doEscape(str, repl); +} + +/************************************************ + Quoting must be done by enclosing the argument between double quotes and + escaping the + double quote character, + backtick character ("`"), + dollar sign ("$") and + backslash character ("\") +by preceding it with an additional backslash character. +Implementations must undo quoting before expanding field codes and before +passing the argument to the executable program. + +Note that the general escape rule for values of type string states that the +backslash character can be escaped as ("\\") as well and that this escape +rule is applied before the quoting rule. As such, to unambiguously represent a +literal backslash character in a quoted argument in a desktop entry file +requires the use of four successive backslash characters ("\\\\"). +Likewise, a literal dollar sign in a quoted argument in a desktop entry file +is unambiguously represented with ("\\$"). + ************************************************/ +QString &DDesktopEntry::escapeExec(QString &str) +{ + QHash repl; + // 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('"'), QLatin1Char('"')); // double quote, + repl.insert(QLatin1Char('\''), QLatin1Char('\'')); // single quote ("'"), + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); // backslash character ("\"), + repl.insert(QLatin1Char('$'), QLatin1Char('$')); // dollar sign ("$"), + + return doEscape(str, repl); +} + +/* + * The escape sequences \s, \n, \t, \r, and \\ are supported for values of type string and localestring, + * meaning ASCII space, newline, tab, carriage return, and backslash, respectively. + * + * Some keys can have multiple values. In such a case, the value of the key is specified as a plural: for + * example, string(s). The multiple values should be separated by a semicolon and the value of the key may + * be optionally terminated by a semicolon. Trailing empty strings must always be terminated with a semicolon. + * Semicolons in these values need to be escaped using \;. + * + * https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#value-types +*/ +QString &DDesktopEntry::unescape(QString &str, bool unescapeSemicolons) +{ + QHash repl; + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); + repl.insert(QLatin1Char('s'), QLatin1Char(' ')); + repl.insert(QLatin1Char('n'), QLatin1Char('\n')); + repl.insert(QLatin1Char('t'), QLatin1Char('\t')); + repl.insert(QLatin1Char('r'), QLatin1Char('\r')); + + if (unescapeSemicolons) { + repl.insert(QLatin1Char(';'), QLatin1Char(';')); + } + + return doUnescape(str, repl); +} + +/************************************************ + Quoting must be done by enclosing the argument between double quotes and + escaping the + double quote character, + backtick character ("`"), + dollar sign ("$") and + backslash character ("\") +by preceding it with an additional backslash character. +Implementations must undo quoting before expanding field codes and before +passing the argument to the executable program. + +Reserved characters are + 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 ("(") and (")") + backtick character ("`"). + +Note that the general escape rule for values of type string states that the +backslash character can be escaped as ("\\") as well and that this escape +rule is applied before the quoting rule. As such, to unambiguously represent a +literal backslash character in a quoted argument in a desktop entry file +requires the use of four successive backslash characters ("\\\\"). +Likewise, a literal dollar sign in a quoted argument in a desktop entry file +is unambiguously represented with ("\\$"). + ************************************************/ +QString &DDesktopEntry::unescapeExec(QString &str) +{ + unescape(str); + QHash repl; + // 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('"'), QLatin1Char('"')); // double quote, + repl.insert(QLatin1Char('\''), QLatin1Char('\'')); // single quote ("'"), + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); // backslash character ("\"), + repl.insert(QLatin1Char('>'), QLatin1Char('>')); // greater-than sign (">"), + repl.insert(QLatin1Char('<'), QLatin1Char('<')); // less-than sign ("<"), + repl.insert(QLatin1Char('~'), QLatin1Char('~')); // tilde ("~"), + repl.insert(QLatin1Char('|'), QLatin1Char('|')); // vertical bar ("|"), + repl.insert(QLatin1Char('&'), QLatin1Char('&')); // ampersand ("&"), + repl.insert(QLatin1Char(';'), QLatin1Char(';')); // semicolon (";"), + repl.insert(QLatin1Char('$'), QLatin1Char('$')); // dollar sign ("$"), + repl.insert(QLatin1Char('*'), QLatin1Char('*')); // asterisk ("*"), + repl.insert(QLatin1Char('?'), QLatin1Char('?')); // question mark ("?"), + repl.insert(QLatin1Char('#'), QLatin1Char('#')); // hash mark ("#"), + repl.insert(QLatin1Char('('), QLatin1Char('(')); // parenthesis ("(") + repl.insert(QLatin1Char(')'), QLatin1Char(')')); // parenthesis (")") + repl.insert(QLatin1Char('`'), QLatin1Char('`')); // backtick character ("`"). + + return doUnescape(str, repl); +} + +bool DDesktopEntry::setStatus(const DDesktopEntry::Status &status) +{ + Q_D(DDesktopEntry); + d->setStatus(status); + + return true; +} + +DCORE_END_NAMESPACE diff --git a/src/ddesktopentry.h b/src/ddesktopentry.h new file mode 100644 index 0000000..5b3554a --- /dev/null +++ b/src/ddesktopentry.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 Deepin Technology Co., Ltd. + * 2019 Gary Wang + * + * Author: Gary Wang + * + * Maintainer: Gary Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DDesktopEntryPrivate; +class 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. + }; + Q_ENUM(EntryType) + + enum ValueType { + Unparsed = 0, // Maybe useless, consider remove it? + String, + Strings, + Boolean, + Numeric, + NotExisted = 99 + }; + 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). + }; + Q_ENUM(Status) + + explicit DDesktopEntry(const QString &filePath) noexcept; + ~DDesktopEntry(); + + bool save() const; + + Status status() const; + QStringList keys(const QString §ion = "Desktop Entry") const; + QStringList allGroups(bool sorted = false) const; + + bool contains(const QString &key, const QString §ion = "Desktop Entry") const; + + QString name() const; + QString genericName() const; + QString ddeDisplayName() const; + QString comment() const; + + QString rawValue(const QString &key, const QString §ion = "Desktop Entry", + const QString &defaultValue = QString()) const; + QString stringValue(const QString &key, const QString §ion = "Desktop Entry", + const QString &defaultValue = QString()) const; + QString localizedValue(const QString &key, const QString &localeKey = "default", + const QString §ion = "Desktop Entry", const QString& defaultValue = QString()) const; + QString localizedValue(const QString &key, const QLocale &locale, + const QString §ion = "Desktop Entry", const QString& defaultValue = QString()) const; + QStringList stringListValue(const QString &key, const QString §ion = "Desktop Entry") const; + + bool setRawValue(const QString &value, const QString &key, const QString& section = "Desktop Entry"); + bool setStringValue(const QString &value, const QString &key, const QString& section = "Desktop Entry"); + bool setLocalizedValue(const QString &value, const QString& localeKey, + const QString &key, const QString& section = "Desktop Entry"); + + bool removeEntry(const QString &key, const QString §ion = "Desktop Entry"); + + static QString &escape(QString &str); + static QString &escapeExec(QString &str); + static QString &unescape(QString &str, bool unescapeSemicolons = false); + static QString &unescapeExec(QString &str); + +protected: + bool setStatus(const Status &status); + +private: + QScopedPointer d_ptr; + + Q_DECLARE_PRIVATE(DDesktopEntry) +}; + +DCORE_END_NAMESPACE diff --git a/src/dsecurestring.cpp b/src/dsecurestring.cpp new file mode 100644 index 0000000..cc5965a --- /dev/null +++ b/src/dsecurestring.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Deepin Technology Co., Ltd. + * + * Author: Gary Wang + * + * Maintainer: Gary Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +#include "dsecurestring.h" +#include "dutil.h" + +DCORE_BEGIN_NAMESPACE + +DSecureString::DSecureString(const QString &other) noexcept + : QString(other) +{ +} + +DSecureString::~DSecureString() +{ + DUtil::SecureErase(*this); +} + +DCORE_END_NAMESPACE diff --git a/src/dsecurestring.h b/src/dsecurestring.h new file mode 100644 index 0000000..d94922b --- /dev/null +++ b/src/dsecurestring.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Deepin Technology Co., Ltd. + * + * Author: Gary Wang + * + * Maintainer: Gary Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DSecureString : public QString +{ +public: + using QString::QString; + DSecureString(const QString &other) noexcept; + ~DSecureString(); +}; + +DCORE_END_NAMESPACE diff --git a/src/dsysinfo.cpp b/src/dsysinfo.cpp new file mode 100644 index 0000000..a364f4c --- /dev/null +++ b/src/dsysinfo.cpp @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: zccrs + * + * Maintainer: zccrs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +#include "dsysinfo.h" +#include "ddesktopentry.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_LINUX +#include +#include +#include +#endif + +DCORE_BEGIN_NAMESPACE + +class DSysInfoPrivate +{ +public: + DSysInfoPrivate(); + +#ifdef Q_OS_LINUX + void ensureDeepinInfo(); + bool ensureOsVersion(); +#endif + void ensureReleaseInfo(); + void ensureComputerInfo(); + QMap parseInfoFile(QFile &file); + +#ifdef Q_OS_LINUX + DSysInfo::DeepinType deepinType = DSysInfo::DeepinType(-1); + QMap deepinTypeMap; //Type Name with Language + QString deepinVersion; + QString deepinEdition; + QString deepinCopyright; + + QString majorVersion; + QString minorVersion; + struct MinVersion { + MinVersion():A(0), BC(0), D(0){ + } + uint A, BC, D; // A-BC-D + }; + struct OSBuild { + OSBuild():A(0), B(0), C(0), D(0), xyz(100){ + } + uint A, B, C, D, E, xyz; // ABCDE.xyz + }; + + MinVersion minVersion; + OSBuild osBuild; +#endif + + QScopedPointer distributionInfo; + + DSysInfo::ProductType productType = DSysInfo::ProductType(-1); + QString prettyName; + QString productTypeString; + QString productVersion; + + QString computerName; + QString cpuModelName; + qint64 memoryAvailableSize = -1; + qint64 memoryInstalledSize = -1; + qint64 diskSize = 0; +}; + +DSysInfoPrivate::DSysInfoPrivate() +{ + +} + +#ifdef Q_OS_LINUX +void DSysInfoPrivate::ensureDeepinInfo() +{ + if (static_cast(deepinType) >= 0) + return; + + QFile file("/etc/deepin-version"); + + if (!file.open(QFile::ReadOnly)) { + deepinType = DSysInfo::UnknownDeepin; + + return; + } + + char buf[1024]; + int buf_length = 0; + + Q_FOREVER { + buf_length = file.readLine(buf, sizeof(buf)); + + if (buf_length < 0) + break; + + const QByteArray line(buf, buf_length); + const QByteArrayList &list = line.split('='); + + if (list.count() != 2) { + continue; + } + + const auto key_value = qMakePair(list.first().trimmed(), list.last().trimmed()); + + if (key_value.first == "Version") { + deepinVersion = key_value.second; + } else if (line.startsWith("Type")) { + if (key_value.first == "Type") { + deepinTypeMap[QString()] = QString::fromLatin1(key_value.second); + } else if (key_value.first.at(4) == '[' && key_value.first.at(key_value.first.size() - 1) == ']') { + const QByteArray &language = key_value.first.mid(5, key_value.first.size() - 6); + + if (!language.isEmpty()) { + deepinTypeMap[QString::fromLatin1(language)] = QString::fromUtf8(key_value.second); + } + } + } else if (key_value.first == "Edition") { + deepinEdition = QString::fromUtf8(key_value.second); + } else if (key_value.first == "Copyright") { + deepinCopyright = QString::fromUtf8(key_value.second); + } + + if (!deepinTypeMap.isEmpty() && !deepinEdition.isEmpty() && !deepinCopyright.isEmpty()) { + break; + } + } + + file.close(); + + const QString &deepin_type = deepinTypeMap[QString()]; + + if (deepin_type.isEmpty()) { + deepinType = DSysInfo::UnknownDeepin; + } else if (deepin_type == "Desktop") { + deepinType = DSysInfo::DeepinDesktop; + } else if (deepin_type == "Professional") { + deepinType = DSysInfo::DeepinProfessional; + } else if (deepin_type == "Server") { + deepinType = DSysInfo::DeepinServer; + } else if (deepin_type == "Personal") { + deepinType = DSysInfo::DeepinPersonal; + } else { + deepinType = DSysInfo::UnknownDeepin; + } + + const QString distributionInfoFile(DSysInfo::distributionInfoPath()); + // Generic DDE distribution info + distributionInfo.reset(new DDesktopEntry(distributionInfoFile)); + QSettings distributionInfo(distributionInfoFile, QSettings::IniFormat); // TODO: treat as `.desktop` format instead of `.ini` +} + +bool DSysInfoPrivate::ensureOsVersion() +{ + if (minVersion.A > 0) + return true; + + DDesktopEntry entry("/etc/os-version"); + majorVersion = entry.stringValue("MajorVersion", "Version"); + minorVersion = entry.stringValue("MinorVersion", "Version"); + Q_ASSERT(minorVersion.length() == 4); + + // A-BC-D + bool ok = false; + uint minv = minorVersion.toUInt(&ok); + if (ok) { + minVersion.D = minv % 10; + } else if (minorVersion.length() > 0) { + // 0-9...A-Z + minVersion.D = 10 + static_cast(minorVersion.right(1).data()->toLatin1() - 'A'); + } + uint minVer = minorVersion.left(3).toUInt(); + minVersion.BC = minVer % 100; + minVer /= 100; + minVersion.A = minVer % 10; + + // ABCDE.xyz + QString osb = entry.stringValue("OsBuild", "Version"); + QStringList osbs = osb.split("."); + Q_ASSERT(osbs.size() == 2 && osbs.value(0).size() == 5); + uint left = osbs.value(0).trimmed().toUInt(&ok); + Q_ASSERT(ok); + if (ok) { + osBuild.E = left % 10; + left /= 10; + osBuild.D = left % 10; + left /= 10; + osBuild.C = left % 10; // default C is 0 + left /= 10; + osBuild.B = left % 10; + left /= 10; + osBuild.A = left % 10; + } + + // xyz + osBuild.xyz = osbs.value(1).trimmed().toUInt(&ok); + + return ok; +} + +static QString unquote(const QByteArray &value) +{ + if (value.at(0) == '"' || value.at(0) == '\'') { + return QString::fromLatin1(value.mid(1, value.size() - 2)); + } + + return QString::fromLatin1(value); +} + +static bool readEtcFile(DSysInfoPrivate *info, const char *filename, + const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey) +{ + + QFile file(QString::fromLatin1(filename)); + + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + + quint8 valid_data_count = 0; + char buf[1024]; + + while (valid_data_count < 3) { + int buf_length = file.readLine(buf, sizeof(buf)); + + if (buf_length < 0) + break; + + const QByteArray line(buf, buf_length - 1); + + if (info->productTypeString.isEmpty() && line.startsWith(idKey)) { + const QByteArray value(line.constData() + idKey.size()); + info->productTypeString = unquote(value); + ++valid_data_count; + continue; + } + + if (info->prettyName.isEmpty() && line.startsWith(prettyNameKey)) { + const QByteArray value(line.constData() + prettyNameKey.size()); + info->prettyName = unquote(value); + ++valid_data_count; + continue; + } + + if (info->productVersion.isEmpty() && line.startsWith(versionKey)) { + const QByteArray value(line.constData() + versionKey.size()); + info->productVersion = unquote(value); + ++valid_data_count; + continue; + } + } + + file.close(); + + return valid_data_count != 0; +} + +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="); + + return true; +} + +static bool readLsbRelease(DSysInfoPrivate *info) +{ + return readEtcFile(info, "/etc/lsb-release", "DISTRIB_ID=", "DISTRIB_RELEASE=", "DISTRIB_DESCRIPTION="); +} +#endif + +void DSysInfoPrivate::ensureReleaseInfo() +{ + if (productType >= 0) { + return; + } + +#ifdef Q_OS_LINUX + readOsRelease(this); + readLsbRelease(this); + + if (productTypeString.isEmpty()) { + productType = DSysInfo::UnknownType; + } else { + switch (productTypeString.at(0).unicode()) { + case 'd': + case 'D': + if (productTypeString.compare("deepin", Qt::CaseInsensitive) == 0) { + productType = DSysInfo::Deepin; + } else if (productTypeString.compare("debian", Qt::CaseInsensitive) == 0) { + productType = DSysInfo::Debian; + } + break; + case 'a': + case 'A': + if (productTypeString.compare("arch", Qt::CaseInsensitive) == 0) + productType = DSysInfo::ArchLinux; + break; + case 'c': + case 'C': + if (productTypeString.compare("centos", Qt::CaseInsensitive) == 0) + productType = DSysInfo::CentOS; + break; + case 'f': + case 'F': + if (productTypeString.compare("fedora", Qt::CaseInsensitive) == 0) + productType = DSysInfo::Fedora; + break; + case 'l': + case 'L': + if (productTypeString.compare("linuxmint", Qt::CaseInsensitive) == 0) + productType = DSysInfo::LinuxMint; + break; + case 'm': + case 'M': + if (productTypeString.compare("manjaro", Qt::CaseInsensitive) == 0) + productType = DSysInfo::Manjaro; + break; + case 'o': + case 'O': + if (productTypeString.compare("opensuse", Qt::CaseInsensitive) == 0) + productType = DSysInfo::openSUSE; + break; + case 's': + case 'S': + if (productTypeString.compare("sailfishos", Qt::CaseInsensitive) == 0) + productType = DSysInfo::SailfishOS; + break; + case 'u': + case 'U': + if (productTypeString.compare("ubuntu", Qt::CaseInsensitive) == 0) { + productType = DSysInfo::Ubuntu; + } else if (productTypeString.compare("uos", Qt::CaseInsensitive) == 0 || productTypeString.compare("UnionTech OS", Qt::CaseInsensitive) == 0) { + productType = DSysInfo::Uos; + } + break; + default: + productType = DSysInfo::UnknownType; + break; + } + } +#endif +} + +void DSysInfoPrivate::ensureComputerInfo() +{ + if (memoryAvailableSize >= 0) + return; + +#ifdef Q_OS_LINUX + struct utsname u; + if (uname(&u) == 0) + computerName = QString::fromLatin1(u.nodename); + + QFile file("/proc/cpuinfo"); + + if (file.open(QFile::ReadOnly)) { + QMap map = parseInfoFile(file); + if (map.contains("Processor")) { + // arm-cpuinfo hw_kirin-cpuinfo + cpuModelName = map.value("Processor"); + } else if (map.contains("model name")) { + // cpuinfo + cpuModelName = map.value("model name"); + } else if (map.contains("cpu model")) { + // loonson3-cpuinfo sw-cpuinfo + cpuModelName = map.value("cpu model"); + } + + file.close(); + } + + memoryAvailableSize = get_phys_pages() * sysconf(_SC_PAGESIZE); + + // Getting Memory Installed Size + // TODO: way to not dept on lshw? + if (!QStandardPaths::findExecutable("lshw").isEmpty()) { + QProcess lshw; + + lshw.start("lshw", {"-c", "memory", "-json", "-sanitize"}, QIODevice::ReadOnly); + + if (!lshw.waitForFinished()) { + return; + } + + 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"); + memoryInstalledSize = memoryHwInfo.toObject().value("size").toDouble(); // TODO: check "units" is "bytes" ? + } + } + + // Getting Disk Size + const QString &deviceName = QStorageInfo::root().device(); + QProcess lsblk; + + lsblk.start("lsblk", {"-Jlpb", "-oNAME,KNAME,PKNAME,SIZE"}, QIODevice::ReadOnly); + + if (!lsblk.waitForFinished()) { + return; + } + + const QByteArray &diskStatusJson = lsblk.readAllStandardOutput(); + QJsonDocument diskStatus = QJsonDocument::fromJson(diskStatusJson); + QJsonValue diskStatusJsonValue = diskStatus.object().value("blockdevices"); + QMap> deviceParentAndSizeMap; + + if (!diskStatusJsonValue.isUndefined()) { + QJsonArray diskStatusArray = diskStatusJsonValue.toArray(); + QString keyName; + + for (const QJsonValue oneValue : diskStatusArray) { + QString name = oneValue.toObject().value("name").toString(); + QString kname = oneValue.toObject().value("kname").toString(); + QString pkname = oneValue.toObject().value("pkname").toString(); + qulonglong size = oneValue.toObject().value("size").toVariant().toULongLong(); + + if (keyName.isNull() && deviceName == name) { + keyName = kname; + } + + deviceParentAndSizeMap[kname] = QPair(pkname, size); + } + + while (!deviceParentAndSizeMap[keyName].first.isNull()) { + keyName = deviceParentAndSizeMap[keyName].first; + } + + diskSize = deviceParentAndSizeMap[keyName].second; + } +#endif +} + +QMap DSysInfoPrivate::parseInfoFile(QFile &file) +{ + char buf[1024]; + qint64 lineLength = 0; + QMap map; + do { + lineLength = file.readLine(buf, sizeof(buf)); + QString s(buf); + if (s.contains(':')) { + QStringList list = s.split(':'); + if (list.size() == 2) { + map.insert(list.first().trimmed(), list.back().trimmed()); + } + } + } while (lineLength >= 0); + return map; +} + +Q_GLOBAL_STATIC(DSysInfoPrivate, siGlobal) + +QString DSysInfo::operatingSystemName() +{ + siGlobal->ensureReleaseInfo(); + + return siGlobal->prettyName; +} + +#ifdef Q_OS_LINUX +/*! + * \brief Check current distro is Deepin or not. + * \note Uos will also return true. + */ +bool DSysInfo::isDeepin() +{ + siGlobal->ensureReleaseInfo(); + + return productType() == Deepin || productType() == Uos; +} + +bool DSysInfo::isDDE() +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinType != UnknownDeepin; +} + +DSysInfo::DeepinType DSysInfo::deepinType() +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinType; +} + +QString DSysInfo::deepinTypeDisplayName(const QLocale &locale) +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinTypeMap.value(locale.name(), siGlobal->deepinTypeMap.value(QString())); +} + +QString DSysInfo::deepinVersion() +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinVersion; +} + +QString DSysInfo::deepinEdition() +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinEdition; +} + +QString DSysInfo::deepinCopyright() +{ + siGlobal->ensureDeepinInfo(); + + return siGlobal->deepinCopyright; +} + +/*! + * \~chinese \brief DSysInfo::osType 系统类型 + * \~chinese \row 显示系统类型【1:桌面】【2:服务器】【3:专用设备】 + * \~chinese \note 根据 osBuild.B 判断 + */ +DSysInfo::UosType DSysInfo::uosType() +{ + siGlobal->ensureOsVersion(); + + UosType ost = UosTypeUnknown; + if ((siGlobal->osBuild.B > UosTypeUnknown && siGlobal->osBuild.B < UosTypeCount)) { + ost = static_cast(siGlobal->osBuild.B); + } + + return ost; +} + +/*! + * \~chinese \brief DSysInfo::osEditionType 版本类型 + * \~chinese \row 显示版本类型 专业版/个人版/社区版... + * \~chinese \note 根据 osBuild.B && osBuild.D + */ +DSysInfo::UosEdition DSysInfo::uosEditionType() +{ + siGlobal->ensureOsVersion(); + UosEdition ospt = UosEditionUnknown; + + if (siGlobal->osBuild.B == UosDesktop) { + ospt = static_cast(siGlobal->osBuild.D); + } else if (siGlobal->osBuild.B == UosServer) { + ospt = static_cast(siGlobal->osBuild.D + UosMilitary); + } else if (siGlobal->osBuild.B == UosDevice){ + ospt = UosProfessional; + } + + return ospt; +} + +/*! + * \~chinese \brief DSysInfo::osArch 架构信息(使用一个字节的二进制位,从低位到高位) + * \~chinese \row 【0x8 sw64】【0x4 mips64】【0x2 arm64】【0x1 amd64】 + */ +DSysInfo::UosArch DSysInfo::uosArch() +{ + siGlobal->ensureOsVersion(); + + return static_cast(siGlobal->osBuild.E); +} + +static QString getUosVersionValue(const QString &key, const QLocale &locale) +{ + DDesktopEntry entry("/etc/os-version"); + QString localKey = QString("%1[%2]").arg(key, locale.name()); + + return entry.stringValue(localKey, "Version", entry.stringValue(key, "Version")); +} + +/*! + * \~chinese \brief DSysInfo::osProductTypeName 版本名称 + * \~chinese \row ProductType[xx] 项对应的值, 如果找不到对应语言的默认使用 ProductType的值(Desktop/Server/Device) + * \~chinese \param locale 当前系统语言 + */ +QString DSysInfo::uosProductTypeName(const QLocale &locale) +{ + return getUosVersionValue("ProductType", locale); +} + +/*! + * \~chinese \brief DSysInfo::osSystemName 版本名称 + * \~chinese \row SystemName[xx] 项对应的值, 如果找不到对应语言的默认使用 SystemName 的值 Uniontech OS + * \~chinese \param locale 当前系统语言 + */ +QString DSysInfo::uosSystemName(const QLocale &locale) +{ + return getUosVersionValue("SystemName", locale); +} + +/*! + * \~chinese \brief DSysInfo::osEditionName 版本名称 + * \~chinese \row EditionName[xx] 项对应的值, 如果找不到对应语言的默认使用 EditionName 的值(Professional/Home/Community...) + * \~chinese \param locale 当前系统语言 + */ +QString DSysInfo::uosEditionName(const QLocale &locale) +{ + return getUosVersionValue("EditionName", locale); +} + +/*! + * \~chinese \brief DSysInfo::spVersion 阶段版本名称 + * \~chinese \row 小版本号 A-BC-D 中 BC, 返回 SP1-SPxx, 如果正式版返回空 + * \~chinese \note minVersion.BC == 00:正式版本 minVersion.BC == 01-99:SP1….SP99 + */ +QString DSysInfo::spVersion() +{ + siGlobal->ensureOsVersion(); + if (siGlobal->minVersion.BC > 0) { + return QString("SP%1").arg(siGlobal->minVersion.BC); + } else { + return QString(); // 00 正式版 + } +} + +/*! + * \~chinese \brief DSysInfo::udpateVersion 更新版本名称 + * \~chinese \row 小版本号 A-BC-D 中 D, 返回 update1… update9, 如果正式版返回空 + * \~chinese \note minVersion.D == 0:正式版本 minVersion.D == 1-9:update1… update9,updateA...updateZ + */ +QString DSysInfo::udpateVersion() +{ + siGlobal->ensureOsVersion(); + if (siGlobal->minVersion.D > 0) { + uint uv = siGlobal->minVersion.D; + if (uv < 10) { + return QString("update%1").arg(uv); + } else { + return QString("update").append(QChar(uv - 10 + 'A')); + } + } else { + return QString(); // 0 正式版 + } +} + +/*! + * \~chinese \brief DSysInfo::majorVersion 主版本号 + * \~chinese \row 主版本号 【20】【23】【25】【26】【29】【30】 + * \~chinese \note 返回 MajorVersion 的值 + */ +QString DSysInfo::majorVersion() +{ + siGlobal->ensureOsVersion(); + return siGlobal->majorVersion; +} + +/*! + * \~chinese \brief DSysInfo::minorVersion 小版本号 + * \~chinese \row 【ABCD】 ·[0-9]{4} + * \~chinese \note 返回 MinorVersion 的值 + */ +QString DSysInfo::minorVersion() +{ + siGlobal->ensureOsVersion(); + return siGlobal->minorVersion; +} + +/*! + * \~chinese \brief DSysInfo::buildVersion 小版本号 + * \~chinese \row 系统镜像批次号,按时间顺序(不可回退)从100-999递增 + * \~chinese \note 返回 osBuild.xyz 的值 + */ +QString DSysInfo::buildVersion() +{ + siGlobal->ensureOsVersion(); + return QString::number(siGlobal->osBuild.xyz); +} +#endif + +QString DSysInfo::deepinDistributionInfoPath() +{ + return distributionInfoPath(); +} + +QString DSysInfo::distributionInfoPath() +{ +#ifdef Q_OS_LINUX + return "/usr/share/deepin/distribution.info"; +#else + return QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).filePath("deepin-distribution.info"); +#endif // Q_OS_LINUX +} + +QString DSysInfo::distributionInfoSectionName(DSysInfo::OrgType type) +{ + switch (type) { + case Distribution: + return "Distribution"; + case Distributor: + return "Distributor"; + case Manufacturer: + return "Manufacturer"; + } + + return QString(); +} + +/*! + * \return the organization name. + * + * use \l type as Distribution to get the name of current deepin distribution itself. + * + * \sa deepinDistributionInfoPath() + */ +QString DSysInfo::distributionOrgName(DSysInfo::OrgType type, const QLocale &locale) +{ +#ifdef Q_OS_LINUX + siGlobal->ensureDeepinInfo(); +#endif + + QString fallback = type == Distribution ? QStringLiteral("Deepin") : QString(); + + return siGlobal->distributionInfo->localizedValue("Name", locale, distributionInfoSectionName(type), fallback); +} + +QString DSysInfo::deepinDistributorName() +{ + return distributionOrgName(Distributor); +} + +/*! + * \return the organization website name and url. + * + * use \l type as Distribution to get the name of current deepin distribution itself. + * + * \sa deepinDistributionInfoPath() + */ +QPair DSysInfo::distributionOrgWebsite(DSysInfo::OrgType type) +{ +#ifdef Q_OS_LINUX + siGlobal->ensureDeepinInfo(); +#endif + + QString fallbackSiteName = type == Distribution ? QStringLiteral("www.deepin.org") : QString(); + QString fallbackSiteUrl = type == Distribution ? QStringLiteral("https://www.deepin.org") : QString(); + + return { + siGlobal->distributionInfo->stringValue("WebsiteName", distributionInfoSectionName(type), fallbackSiteName), + siGlobal->distributionInfo->stringValue("Website", distributionInfoSectionName(type), fallbackSiteUrl), + }; +} + +QPair DSysInfo::deepinDistributorWebsite() +{ + return distributionOrgWebsite(Distributor); +} + +/*! + * \return the obtained organization logo path, or the given \l fallback one if there are no such logo. + * + * use \l type as Distribution to get the logo of current deepin distribution itself. + * + * \sa deepinDistributionInfoPath() + */ +QString DSysInfo::distributionOrgLogo(DSysInfo::OrgType orgType, DSysInfo::LogoType type, const QString &fallback) +{ + DDesktopEntry distributionInfo(distributionInfoPath()); + QString orgSectionName = distributionInfoSectionName(orgType); + + switch (type) { + case Normal: + return distributionInfo.stringValue("Logo", orgSectionName, fallback); + case Light: + return distributionInfo.stringValue("LogoLight", orgSectionName, fallback); + case Symbolic: + return distributionInfo.stringValue("LogoSymbolic", orgSectionName, fallback); + case Transparent: + return distributionInfo.stringValue("LogoTransparent", orgSectionName, fallback); + } + + return QString(); +} + +QString DSysInfo::deepinDistributorLogo(DSysInfo::LogoType type, const QString &fallback) +{ + return distributionOrgLogo(Distributor, type, fallback); +} + +DSysInfo::ProductType DSysInfo::productType() +{ + siGlobal->ensureReleaseInfo(); + + return siGlobal->productType; +} + +QString DSysInfo::productTypeString() +{ + siGlobal->ensureReleaseInfo(); + + return siGlobal->productTypeString; +} + +QString DSysInfo::productVersion() +{ + siGlobal->ensureReleaseInfo(); + + return siGlobal->productVersion; +} + +/*! + * \brief Check if current edition is a community edition + * + * Developer can use this way to check if we need enable or disable features + * for community or enterprise edition. + * + * Current rule: + * - Professional, Server, Personal edition (DeepinType) will be treat as Enterprise edition. + * - Uos (ProductType) will be treat as Enterprise edition. + * + * \return true if it's on a community edition distro/installation + */ +bool DSysInfo::isCommunityEdition() +{ +#ifdef Q_OS_LINUX + DeepinType type = deepinType(); + QList enterpriseTypes { + DeepinProfessional, DeepinServer, DeepinPersonal + }; + + if (enterpriseTypes.contains(type)) { + return false; + } + + if (productType() == Uos) { + return false; + } +#endif // Q_OS_LINUX + + return true; +} + +QString DSysInfo::computerName() +{ + siGlobal->ensureComputerInfo(); + + return siGlobal->computerName; +} + +QString DSysInfo::cpuModelName() +{ + siGlobal->ensureComputerInfo(); + + return siGlobal->cpuModelName; +} + +/*! + * \return the installed memory size + */ +qint64 DSysInfo::memoryInstalledSize() +{ + siGlobal->ensureComputerInfo(); + + return siGlobal->memoryInstalledSize; +} + +/*! + * \return the total available to use memory size + */ +qint64 DSysInfo::memoryTotalSize() +{ + siGlobal->ensureComputerInfo(); + + return siGlobal->memoryAvailableSize; +} + +qint64 DSysInfo::systemDiskSize() +{ + siGlobal->ensureComputerInfo(); + + return siGlobal->diskSize; +} + +DCORE_END_NAMESPACE diff --git a/src/dsysinfo.h b/src/dsysinfo.h new file mode 100644 index 0000000..9c41c49 --- /dev/null +++ b/src/dsysinfo.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: zccrs + * + * Maintainer: zccrs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +#ifndef DSYSINFO_H +#define DSYSINFO_H + +#include + +#include + +DCORE_BEGIN_NAMESPACE + +class DSysInfoPrivate; +class DSysInfo +{ +public: + enum ProductType { + UnknownType = 0, + Deepin, + ArchLinux, + CentOS, + Debian, + Fedora, + LinuxMint, + Manjaro, + openSUSE, + SailfishOS, + Ubuntu, + Uos + }; + + enum DeepinType { + UnknownDeepin = 0, + DeepinDesktop, + DeepinProfessional, + DeepinServer, + DeepinPersonal + }; + + enum LogoType { + Normal = 0, + Light, + Symbolic, + Transparent + }; + + enum OrgType { + Distribution, //!< distribution itself + Distributor, //!< distributer of the current distribution + Manufacturer //!< manufacturer of the current distribution or device + }; + + enum UosType { + UosTypeUnknown, + UosDesktop, + UosServer, + UosDevice, + + UosTypeCount // must at last + }; + + enum UosEdition { + UosEditionUnknown, + UosProfessional, + UosHome, + UosCommunity, + UosMilitary, + UosEnterprise, + UosEnterpriseC, + UosEuler, + UosMilitaryS, // for Server + + UosEditionCount // must at last + }; + + // 注意:此处架构是从OsBuild获取的系统版本的Arch信息,并不是指硬件的Arch信息 + enum UosArch { + UosArchUnknown, + UosAMD64 = 1 << 0, + UosARM64 = 1 << 1, + UosMIPS64 = 1 << 2, + UosSW64 = 1 << 3 + }; + +#ifdef Q_OS_LINUX + static bool isDeepin(); + static bool isDDE(); + static DeepinType deepinType(); + static QString deepinTypeDisplayName(const QLocale &locale = QLocale::system()); + static QString deepinVersion(); + static QString deepinEdition(); + static QString deepinCopyright(); + + // uos version interface + static UosType uosType(); + static UosEdition uosEditionType(); + static UosArch uosArch(); + static QString uosProductTypeName(const QLocale &locale = QLocale::system()); + static QString uosSystemName(const QLocale &locale = QLocale::system()); + static QString uosEditionName(const QLocale &locale = QLocale::system()); + + static QString spVersion(); // SP1...SP99 + static QString udpateVersion(); // update1...update9 + static QString majorVersion(); + static QString minorVersion(); + static QString buildVersion(); // xyz +#endif + + Q_DECL_DEPRECATED_X("Use distributionInfoPath() instead") static QString deepinDistributionInfoPath(); + 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(); + static QString productTypeString(); + static QString productVersion(); + static bool isCommunityEdition(); + + static QString computerName(); + static QString cpuModelName(); + static qint64 memoryInstalledSize(); + static qint64 memoryTotalSize(); + static qint64 systemDiskSize(); +}; + +DCORE_END_NAMESPACE + +#endif // DSYSINFO_H diff --git a/src/dtk_build.prf b/src/dtk_build.prf new file mode 100644 index 0000000..4543eff --- /dev/null +++ b/src/dtk_build.prf @@ -0,0 +1,98 @@ +exists(../dtk_build_config.prf) { + include(../dtk_build_config.prf) +} else { + load(dtk_build_config) +} + +#标记已经加载了dtk_build.prf +DTK_BUILD=1 +TEMPLATE = lib + +CONFIG += c++11 create_pc create_prl no_install_prl +CONFIG += no_keywords + +DEFINES += QT_MESSAGELOGCONTEXT +DEFINES += LIB$$upper($$DTK_MODULE_NAME)_LIBRARY +DEFINES += DTK_LIB_DIR_NAME=\\\"$$LIB_VERSION_NAME\\\" + +isEmpty(target.path): target.path = $$LIB_INSTALL_DIR +isEmpty(includes.path): includes.path = $$quote($$INCLUDE_INSTALL_DIR) + +!isEmpty(DTK_STATIC_LIB) { + DEFINES += DTK_STATIC_LIB + CONFIG += staticlib +} + +!isEmpty(DTK_STATIC_TRANSLATION) { + DEFINES += DTK_STATIC_TRANSLATION +} + +defineTest(containIncludeFiles) { + header = $$absolute_path($$ARGS) + header_dir = $$quote($$dirname(header)) + + for (file, includes.files) { + file_ap = $$absolute_path($$file) + file_dir = $$quote($$dirname(file_ap)) + + isEqual(file_dir, $$header_dir):return(true) + } + + return(false) +} + +ALL_HEADER_FILE_NAME=Dtk$${MODULE_NAME}s + +#添加一个include模块提供的所有头文件的总的头文件 +defineTest(updateDtkHeaderFile) { + include_files = $$HEADERS + file_content = $$quote($${LITERAL_HASH}ifndef DTK_$$upper($$MODULE_NAME)_MODULE_H) + file_content += $$quote($${LITERAL_HASH}define DTK_$$upper($$MODULE_NAME)_MODULE_H) + + for(header, include_files) { + #排除私有头文件,以 _p.h 结尾的认为是私有头文件 + suffix = $$str_member($$header, -4, -1) + !isEqual(suffix, "_p.h"): containIncludeFiles($$header) { + file_content += $$quote($${LITERAL_HASH}include \"$$basename(header)\") + } + } + + file_content += $$quote($${LITERAL_HASH}endif) + !write_file($$_PRO_FILE_PWD_/$$ALL_HEADER_FILE_NAME, file_content):return(false) + + return(true) +} + +!updateDtkHeaderFile():warning(Cannot create "$${ALL_HEADER_FILE_NAME}" header file) + +# create dtkxxx_config.h file +defineTest(updateDtkConfigFile) { + isEqual(DTK_MODULE_NAME, dtkcore) { + config_content += $$quote($${LITERAL_HASH}define DTK_VERSION_MAJOR $$VER_MAJ) + config_content += $$quote($${LITERAL_HASH}define DTK_VERSION_MINOR $$VER_MIN) + config_content += $$quote($${LITERAL_HASH}define DTK_VERSION_PATCH $$VER_PAT) + config_content += $$quote($${LITERAL_HASH}define DTK_VERSION_BUILD $$VER_BUI) + config_content += $$quote($${LITERAL_HASH}define DTK_VERSION_STR \"$$VERSION\") + config_content += $$quote(//) + } + + for(file, includes.files) { + file = $$quote($$basename(file)) + + !isEqual(file, $$ALL_HEADER_FILE_NAME):contains(file, D[A-Za-z0-9_]+) { + config_content += $$quote($${LITERAL_HASH}define $$upper($$DTK_MODULE_NAME)_CLASS_$$file) + } + } + + !write_file($$_PRO_FILE_PWD_/$${DTK_MODULE_NAME}_config.h, config_content):return(false) + + return(true) +} + +!updateDtkConfigFile():warning(Cannot create "$${DTK_MODULE_NAME}_config.h" header file) + +exists($$PWD/dtk_translation.prf) { + include($$PWD/dtk_translation.prf) +} else { + load(dtk_translation) +} diff --git a/src/dtk_cmake.prf b/src/dtk_cmake.prf new file mode 100644 index 0000000..ecc91ac --- /dev/null +++ b/src/dtk_cmake.prf @@ -0,0 +1,44 @@ +# CMake configure + +#TODO: check cmake exist + +!win*: { +MODULE_DEPENDS=$$find(QT, dtk*) +CMAKE_MODULE_DEPENDS=$$replace(MODULE_DEPENDS,"dtk","") + +CMAKE_MODULE=Dtk$$MODULE_NAME +WORK_DIR=$$_PRO_FILE_PWD_ + +message("config cmake module: $$CMAKE_MODULE") + +MODULE_PRI_CONT = "" +LINK_LIBRARIES = "" + +for(MODULE_DEPEND, CMAKE_MODULE_DEPENDS) { + MODULE_DEPEND=$$capitalizingString($$MODULE_DEPEND) + CMAKE_CONTENT += "find_package(Dtk REQUIRED $$MODULE_DEPEND)" + LINK_LIBRARIES += " ${Dtk$${MODULE_DEPEND}_LIBRARIES}" +} + +CMAKE_MODULE_INCLUDE_DIR=$$upper($${CMAKE_MODULE})_INCLUDE_DIR +INC_DIR = $$replace(INCLUDE_INSTALL_DIR, "/", "/") + +CMAKE_MODULE_TOO_DIR=$$upper($${CMAKE_MODULE})_TOOL_DIR +TOOL_DIR = $$TOOL_INSTALL_DIR + +CMAKE_CONTENT += "set($${CMAKE_MODULE_INCLUDE_DIR} $${INC_DIR})" +CMAKE_CONTENT += "set($${CMAKE_MODULE_TOO_DIR} $${TOOL_DIR})" +CMAKE_CONTENT += "set($${CMAKE_MODULE}_LIBRARIES $$TARGET$$LINK_LIBRARIES)" +CMAKE_CONTENT += "include_directories(\"${"$${CMAKE_MODULE_INCLUDE_DIR}"}\")" + +CMAKE_DIR=$$WORK_DIR/../cmake/$${CMAKE_MODULE} +CMAKE_PATH=$$CMAKE_DIR/$${CMAKE_MODULE}Config.cmake +mkpath($$CMAKE_DIR) +message("write cmake file to $$CMAKE_PATH") +write_file($$CMAKE_PATH, CMAKE_CONTENT) | error("Aborting.") + +cmake_config.files = $$WORK_DIR/../cmake +cmake_config.path = $$LIB_INSTALL_DIR + +INSTALLS += cmake_config +} diff --git a/src/dtk_lib.prf b/src/dtk_lib.prf new file mode 100644 index 0000000..047643e --- /dev/null +++ b/src/dtk_lib.prf @@ -0,0 +1,7 @@ +TEMPLATE = subdirs +CONFIG += ordered + +exists($$_PRO_FILE_PWD_/src) SUBDIRS += src +exists($$_PRO_FILE_PWD_/tools) SUBDIRS += tools +exists($$_PRO_FILE_PWD_/tests) SUBDIRS += tests +exists($$_PRO_FILE_PWD_/examples) SUBDIRS += examples diff --git a/src/dtk_module.prf b/src/dtk_module.prf new file mode 100644 index 0000000..800e28c --- /dev/null +++ b/src/dtk_module.prf @@ -0,0 +1,127 @@ +isEmpty(DTK_BUILD): error("Please load(dtk_build) first!") + +# ----------------------- +# Config Qt module +MODULE_ID=$$DTK_MODULE_NAME +mod_inst_pfx=$$_PRO_FILE_PWD_ +MODULE_PRI = $$mod_inst_pfx/qt_lib_$${MODULE_ID}.pri +module_libs = $$LIB_INSTALL_DIR +module_tools = $$TOOL_INSTALL_DIR +MODULE_INCLUDES = $$INCLUDE_INSTALL_DIR +MODULE_DEPENDS=$$find(QT, dtk*) + +message("config qt module: $$MODULE_ID") +message("write $$MODULE_PRI to: $$mod_inst_pfx") + +internal_module: \ + MODULE_DEPENDS = $$replace(QT, -private$, _private) +else: \ + MODULE_DEPENDS = $$replace(QT, -private$, ) +MODULE_DEPENDS = $$unique(MODULE_DEPENDS) +contains(MODULE_DEPENDS, $$MODULE): \ + error("$$MODULE_ID depends on itself.") + +# Create a module .pri file +module_libs=$$LIB_INSTALL_DIR +isEmpty(module_libs) { +host_build: \ + module_libs = "\$\$QT_MODULE_HOST_LIB_BASE" +else: \ + module_libs = "\$\$QT_MODULE_LIB_BASE" +} + +# In addition to the library's private deps, the private module's deps +# are logically runtime deps of the public module. +runtime_deps = $$QT_PRIVATE $$QT_FOR_PRIVATE +!isEmpty(runtime_deps): \ + module_rundep = "QT.$${MODULE_ID}.run_depends = $$replace(runtime_deps, -private$, _private)" +else: \ + module_rundep = +module_build_type = v2 +static: \ + module_build_type += staticlib +lib_bundle { + module_build_type += lib_bundle + MODULE_FRAMEWORKS = " \$\$QT_MODULE_LIB_BASE" +} +internal_module: \ + module_build_type += internal_module +ltcg: \ + module_build_type += ltcg +module_module = +!equals(TEMPLATE, aux) { + module_module = $$MODULE_ID$$QT_LIBINFIX + !lib_bundle: module_module ~= s,^Qt,Qt$$QT_MAJOR_VERSION, +} +!isEmpty(MODULE_CONFIG): \ + module_config = "QT.$${MODULE_ID}.CONFIG = $$MODULE_CONFIG" +else: \ + module_config = +!isEmpty(MODULE_PLUGIN_TYPES): \ + module_plugtypes = "QT.$${MODULE_ID}.plugin_types = $$replace(MODULE_PLUGIN_TYPES, /.*$, )" +else: \ + module_plugtypes = +!isEmpty(MODULE_MASTER_HEADER): \ + module_master = "QT.$${MODULE_ID}.master_header = $$MODULE_MASTER_HEADER" +else: \ + module_master = + +MODULE_PRI_CONT = \ + "QT.$${MODULE_ID}.VERSION = $${VERSION}" \ + "QT.$${MODULE_ID}.MAJOR_VERSION = $${VER_MAJ}" \ + "QT.$${MODULE_ID}.MINOR_VERSION = $${VER_MIN}" \ + "QT.$${MODULE_ID}.PATCH_VERSION = $${VER_PAT}" \ + "" \ + "QT.$${MODULE_ID}.name = $${MODULE_ID}" \ + "QT.$${MODULE_ID}.module = $$module_module" \ + "QT.$${MODULE_ID}.tools = $$module_tools" \ + "QT.$${MODULE_ID}.libs = $$module_libs" \ + $$module_master \ + "QT.$${MODULE_ID}.includes = $$MODULE_INCLUDES" \ + "QT.$${MODULE_ID}.frameworks =$$MODULE_FRAMEWORKS" + +MODULE_PRI_CONT += \ + "QT.$${MODULE_ID}.depends =$$join(MODULE_DEPENDS, " ", " ")" \ + $$module_rundep \ + "QT.$${MODULE_ID}.module_config =$$join(module_build_type, " ", " ")" \ + $$module_config \ + "QT.$${MODULE_ID}.DEFINES = $$val_escape(MODULE_DEFINES)" \ + "" \ + "QT_MODULES += $$MODULE" + +write_file($$MODULE_PRI, MODULE_PRI_CONT)|error("Aborting.") + +qt_module.files = $$MODULE_PRI + +isEmpty(MKSPECS_INSTALL_DIR) { + MKSPECS_INSTALL_DIR=$$[QT_INSTALL_ARCHDATA]/mkspecs +} +qt_module.path = $${MKSPECS_INSTALL_DIR}/modules + +INSTALLS += qt_module + +PKG_MODULE_DEPENDS=$$find(QT, dtk*) + +#不能添加Qt包的依赖,无法单纯的从Qt模块名称获取其pkgconfig的pc文件名 +#for (qt_module, QT) { +# #DBus模块需要特殊处理 +# isEqual(qt_module, "dbus") { +# PKG_MODULE_DEPENDS+=Qt5DBus +# } else { +# suffix = $$str_member($$qt_module, -7, -1) +# #排除以private结尾的模块 +# !isEqual(suffix, "private"): PKG_MODULE_DEPENDS+=Qt5$$capitalizingString($$qt_module) +# } +#} + +PKG_MODULE_DEPENDS = $$unique(PKG_MODULE_DEPENDS) + +# ----------------------- +# Config pkg-config +QMAKE_PKGCONFIG_VERSION = $$VERSION +QMAKE_PKGCONFIG_DESTDIR = pkgconfig +QMAKE_PKGCONFIG_NAME = $$upper($$MODULE_ID) +QMAKE_PKGCONFIG_DESCRIPTION = Deepin Tool Kit $$MODULE_ID header files +QMAKE_PKGCONFIG_REQUIRES += $$join(PKG_MODULE_DEPENDS, ", ") +QMAKE_PKGCONFIG_INCDIR = $$includes.path +QMAKE_PKGCONFIG_LIBDIR = $$target.path diff --git a/src/dtk_qmake.prf b/src/dtk_qmake.prf new file mode 100644 index 0000000..38a3835 --- /dev/null +++ b/src/dtk_qmake.prf @@ -0,0 +1,121 @@ +CONFIG += host_$$QMAKE_HOST.arch +DEFINES += Q_HOST_NAME=\\\"$$QMAKE_HOST.arch\\\" Q_HOST_$$upper($$QMAKE_HOST.arch) + +defineTest(buildQMAKEProject) { + pro_dir = $$1 + pro_out_dir = $$shadowed($$pro_dir) + isEmpty(QMAKE_CD): QMAKE_CD=cd + pro_cmd_base = "$$QMAKE_CD $$system_quote($$system_path($$pro_out_dir)) &&" + mkpath($$pro_out_dir) + command = $$pro_cmd_base $$system_quote($$system_path($$QMAKE_QMAKE)) + CONFIG(debug, debug|release) { + command += QMAKE_CFLAGS_DEBUG*=\"$$QMAKE_CFLAGS_DEBUG\" \ + QMAKE_CXXFLAGS_DEBUG*=\"$$QMAKE_CXXFLAGS_DEBUG\" \ + QMAKE_LFLAGS_DEBUG*=\"$$QMAKE_LFLAGS_DEBUG\" \ + CONFIG+=debug + } else { + command += QMAKE_CFLAGS_RELEASE*=\"$$QMAKE_CFLAGS_RELEASE\" \ + QMAKE_CXXFLAGS_RELEASE*=\"$$QMAKE_CXXFLAGS_RELEASE\" \ + QMAKE_LFLAGS_RELEASE*=\"$$QMAKE_LFLAGS_RELEASE\" + } + command += -spec $$QMAKESPEC $$shell_quote($$pro_dir) + message($${command}:) + # Qt >= 5.8 + greaterThan(QT_MINOR_VERSION, 7) { + !equals(3, false): 1 = "( $$1 ) 2>&1" + output = $$system("$$command", lines, result) + !isEmpty(output): message($$output) + !equals(result, 0): return(false) + } else { + system("$$command")|return(false) + } + load(configure) + command = $$pro_cmd_base $$QMAKE_MAKE + message($${command}:) + # Qt >= 5.8 + greaterThan(QT_MINOR_VERSION, 7) { + !equals(3, false): 1 = "( $$1 ) 2>&1" + output = $$system("$$command", lines, result) + !isEmpty(output): message($$output) + !equals(result, 0): return(false) + } else { + system("$$command")|return(false) + } + return(true) +} + +isEqual(TARGET, dtkcore) { + DEEPIN_OS_RELEASE_TOOL=$$_PRO_FILE_PWD_/../bin/deepin-os-release + + !exists($$DEEPIN_OS_RELEASE_TOOL) { + tools_dir = $$_PRO_FILE_PWD_/../tools/deepin-os-release + !buildQMAKEProject($$tools_dir): error(Failed on build deepin-os-release) + } +} else { + isEmpty(QT.dtkcore.tools): error(QT += dtkcore first) + DEEPIN_OS_RELEASE_TOOL=$${QT.dtkcore.tools}/deepin-os-release +} + +!exists($$DEEPIN_OS_RELEASE_TOOL): error(\"$$DEEPIN_OS_RELEASE_TOOL\" is not exists. Install \"dtkcore-bin\" first) + +defineReplace(formatString) { + string = $$1 + string = $$replace(string, \\s+, _) + string_count = $$size(string) + + greaterThan(string_count, 1) { + for (item, string) { + isEmpty(new_string): new_string = $$item + else: new_string = $${new_string}_$${item} + } + + return($$new_string) + } + + return($$string) +} + +DEEPIN_OS_TYPE = $$system($$DEEPIN_OS_RELEASE_TOOL --deepin-type) +DEEPIN_OS_VERSION = $$system($$DEEPIN_OS_RELEASE_TOOL --deepin-version) +DISTRIB_ID = $$system($$DEEPIN_OS_RELEASE_TOOL --product-type) +DISTRIB_RELEASE = $$system($$DEEPIN_OS_RELEASE_TOOL --product-version) + +isEmpty(DISTRIB_ID): warning(No value of the "--product-type" in the process "$$DEEPIN_OS_RELEASE_TOOL") +else { + DISTRIB_ID = $$formatString($$DISTRIB_ID) + + message("OS: $$DISTRIB_ID, Version: $$DISTRIB_RELEASE") + + QMAKE_PLATFORM += $$lower($$DISTRIB_ID) + + DISTRIB_ID = $$upper($$DISTRIB_ID) + !isEmpty(DISTRIB_ID): DEFINES += Q_OS_$$DISTRIB_ID + CONFIG *= $$QMAKE_PLATFORM + + DISTRIB_RELEASE = $$formatString($$DISTRIB_RELEASE) + DEFINES += Q_OS_VERSION=\\\"$$DISTRIB_RELEASE\\\" + + #uos base with deepin + isEqual(DISTRIB_ID, UOS) { + QMAKE_PLATFORM += deepin + DEFINES += Q_OS_DEEPIN + } +} + +isEmpty(DEEPIN_OS_TYPE): warning(No value of the "--deepin-type" in the process "$$DEEPIN_OS_RELEASE_TOOL") +else { + DEEPIN_OS_TYPE = $$formatString($$DEEPIN_OS_TYPE) + + message(Deepin OS Type: $$DEEPIN_OS_TYPE) + message(Deepin OS Version: $$DEEPIN_OS_VERSION) + + !isEmpty(DEEPIN_OS_TYPE) { + QMAKE_PLATFORM += deepin_$$lower($$DEEPIN_OS_TYPE) deepin_dde + DEFINES += Q_OS_DEEPIN_$$upper($$DEEPIN_OS_TYPE) DEEPIN_DDE + } + + DEEPIN_OS_VERSION = $$formatString($$DEEPIN_OS_VERSION) + DEFINES += Q_OS_DEEPIN_VERSION=\\\"$$DEEPIN_OS_VERSION\\\" + + CONFIG *= $$QMAKE_PLATFORM +} diff --git a/src/dtk_translation.prf b/src/dtk_translation.prf new file mode 100644 index 0000000..352c022 --- /dev/null +++ b/src/dtk_translation.prf @@ -0,0 +1,63 @@ +message ("Process dtk translation") +message ("Add DTK_NO_TRANSLATION=YES to qmake arguments to skip this") +message ("Add DTK_STATIC_TRANSLATION=YES to add support for static translations") + +# TODO: check lrelease/lupdate exist + +ROOT_DIR = $$_PRO_FILE_PWD_ + +BASENAME = $$basename(_PRO_FILE_) +BASENAME = $$split(BASENAME, .) +BASENAME = $$first(BASENAME) + +isEmpty(DTK_NO_TRANSLATION) { +# system(lupdate $$_PRO_FILE_) | error("Failed to lupdate") + + TRANSLATIONS = $$files($$ROOT_DIR/translations/*.ts) + for(tsfile, TRANSLATIONS) { + qmfile = $$replace(tsfile, .ts$, .qm) + system(lrelease $$tsfile -qm $$qmfile) | error("Failed to lrelease") + } + + # create static translations qrc file + !isEmpty(DTK_STATIC_TRANSLATION) { + # qrc template + # + # + # dtkwidget_am_ET.qm + # dtkwidget_ar.qm + # dtkwidget_ast.qm + # + # + QRC_PATH = $$ROOT_DIR/translations/$${BASENAME}_translations.qrc + message ("Create static translations file $${QRC_PATH}") + + QRC_CONTENT = "" + QRC_CONTENT += " " + + QM_FILE_LIST = $$files($$ROOT_DIR/translations/*.qm) + for(qmfile, QM_FILE_LIST) { + QRC_CONTENT += " $$basename(qmfile)" + } + QRC_CONTENT += " " + QRC_CONTENT += "" + write_file($$QRC_PATH, QRC_CONTENT) | error("Aborting.") + } +} + +!isEmpty(DTK_STATIC_TRANSLATION) { + QRC_PATH = $$ROOT_DIR/translations/$${TARGET}_translations.qrc + RESOURCES += $$QRC_PATH +} + +TRANSLATIONS += $$ROOT_DIR/translations/* + +TRANSLATIONS_DIR = $$LIB_VERSION_NAME/$$DMODULE_NAME/translations +TRANSLATIONS_PATH = $$PREFIX/share/$$TRANSLATIONS_DIR +DEFINES += $$upper($$DMODULE_NAME)_TRANSLATIONS_PATH=\\\"$$TRANSLATIONS_PATH\\\" +DEFINES += $$upper($$DMODULE_NAME)_TRANSLATIONS_DIR=\\\"$$TRANSLATIONS_DIR\\\" + +dtk_translations.path = $$TRANSLATIONS_PATH +dtk_translations.files = $$ROOT_DIR/translations/*.qm + +INSTALLS += dtk_translations diff --git a/src/dtkcore_global.h b/src/dtkcore_global.h new file mode 100644 index 0000000..2b749da --- /dev/null +++ b/src/dtkcore_global.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include + +#define DTK_NAMESPACE Dtk + +#if !defined(DTK_NAMESPACE) +# define DTK_BEGIN_NAMESPACE +# define DTK_END_NAMESPACE +# define DTK_USE_NAMESPACE +#else +# define DTK_BEGIN_NAMESPACE namespace DTK_NAMESPACE { +# define DTK_END_NAMESPACE } +# define DTK_USE_NAMESPACE using namespace DTK_NAMESPACE; +#endif + +#define DCORE_NAMESPACE Core +#define DTK_CORE_NAMESPACE DTK_NAMESPACE::DCORE_NAMESPACE + +#if !defined(DCORE_NAMESPACE) +# define DCORE_BEGIN_NAMESPACE +# define DCORE_END_NAMESPACE +# define DCORE_USE_NAMESPACE +#else +# define DCORE_BEGIN_NAMESPACE namespace DTK_NAMESPACE { namespace DCORE_NAMESPACE { +# define DCORE_END_NAMESPACE }} +# define DCORE_USE_NAMESPACE using namespace DTK_CORE_NAMESPACE; +#endif + + +#if defined(DTK_STATIC_LIB) +# define LIBDTKCORESHARED_EXPORT +#else +#if defined(LIBDTKCORE_LIBRARY) +# define LIBDTKCORESHARED_EXPORT Q_DECL_EXPORT +#else +# define LIBDTKCORESHARED_EXPORT Q_DECL_IMPORT +#endif +#endif + +#ifdef D_DEPRECATED_CHECK +#define D_DECL_DEPRECATED_X(text) Q_DECL_HIDDEN +#define D_DECL_DEPRECATED Q_DECL_HIDDEN +#else +#define D_DECL_DEPRECATED Q_DECL_DEPRECATED +#define D_DECL_DEPRECATED_X Q_DECL_DEPRECATED_X +#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) diff --git a/src/filesystem/DBaseFileWatcher b/src/filesystem/DBaseFileWatcher new file mode 100644 index 0000000..1348031 --- /dev/null +++ b/src/filesystem/DBaseFileWatcher @@ -0,0 +1 @@ +#include "dbasefilewatcher.h" diff --git a/src/filesystem/DFileSystemWatcher b/src/filesystem/DFileSystemWatcher new file mode 100644 index 0000000..97400f2 --- /dev/null +++ b/src/filesystem/DFileSystemWatcher @@ -0,0 +1 @@ +#include "dfilesystemwatcher.h" diff --git a/src/filesystem/DFileWatcher b/src/filesystem/DFileWatcher new file mode 100644 index 0000000..768151a --- /dev/null +++ b/src/filesystem/DFileWatcher @@ -0,0 +1 @@ +#include "dfilewatcher.h" diff --git a/src/filesystem/DFileWatcherManager b/src/filesystem/DFileWatcherManager new file mode 100644 index 0000000..a9f8682 --- /dev/null +++ b/src/filesystem/DFileWatcherManager @@ -0,0 +1 @@ +#include "dfilewatchermanager.h" diff --git a/src/filesystem/DPathBuf b/src/filesystem/DPathBuf new file mode 100644 index 0000000..961c40b --- /dev/null +++ b/src/filesystem/DPathBuf @@ -0,0 +1 @@ +#include "dpathbuf.h" diff --git a/src/filesystem/DStandardPaths b/src/filesystem/DStandardPaths new file mode 100644 index 0000000..9d0b963 --- /dev/null +++ b/src/filesystem/DStandardPaths @@ -0,0 +1 @@ +#include "dstandardpaths.h" diff --git a/src/filesystem/DTrashManager b/src/filesystem/DTrashManager new file mode 100644 index 0000000..e763093 --- /dev/null +++ b/src/filesystem/DTrashManager @@ -0,0 +1 @@ +#include "dtrashmanager.h" diff --git a/src/filesystem/dbasefilewatcher.cpp b/src/filesystem/dbasefilewatcher.cpp new file mode 100644 index 0000000..393c27e --- /dev/null +++ b/src/filesystem/dbasefilewatcher.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dbasefilewatcher.h" +#include "private/dbasefilewatcher_p.h" + +#include +#include + +DCORE_BEGIN_NAMESPACE + +QList DBaseFileWatcherPrivate::watcherList; +DBaseFileWatcherPrivate::DBaseFileWatcherPrivate(DBaseFileWatcher *qq) + : DObjectPrivate(qq) +{ + +} + +/*! + \~english \class DBaseFileWatcher + \~english \brief The DBaseFileWatcher class provides an interface for monitoring files and directories for modifications. +*/ + +/*! + \~chinese \class DBaseFileWatcher + \~chinese \brief DBaseFileWatcher 类提供了一系列接口可供监视文件和目录的变动。 +*/ + +DBaseFileWatcher::~DBaseFileWatcher() +{ + stopWatcher(); + DBaseFileWatcherPrivate::watcherList.removeOne(this); +} + +QUrl DBaseFileWatcher::fileUrl() const +{ + Q_D(const DBaseFileWatcher); + + return d->url; +} + +/*! + * \~chinese \brief 开始文件变动监视 + * \~english \brief Let file watcher start watching file changes. + * + * \sa stopWatcher(), restartWatcher() + */ +bool DBaseFileWatcher::startWatcher() +{ + Q_D(DBaseFileWatcher); + + if (d->started) + return true; + + if (d->start()) { + d->started = true; + + return true; + } + + return false; +} + +/*! + * \~chinese \brief 停止文件变动监视 + * \~english \brief Stop watching file changes. + * + * \sa startWatcher(), restartWatcher() + */ +bool DBaseFileWatcher::stopWatcher() +{ + Q_D(DBaseFileWatcher); + + if (!d->started) + return false; + + if (d->stop()) { + d->started = false; + + return true; + } + + return false; +} + +/*! + * \~chinese \brief 重新开始文件变动监视 + * \~english \brief Stop file watcher and then restart it to watching file changes. + * + * \sa startWatcher(), stopWatcher() + */ +bool DBaseFileWatcher::restartWatcher() +{ + bool ok = stopWatcher(); + return ok && startWatcher(); +} + +/*! + * \~chinese \brief 设置是否对 \a subfileUrl 目录启用文件监视 + * \~english \brief Set enable file watcher for \a subfileUrl or not + * + * \~chinese \param subfileUrl 设置所针对的 Url + * \~english \param subfileUrl The given url + * + * \~chinese \param enabled 是否启用文件变动监视 + * \~english \param enabled Enable file change watching or not. + */ +void DBaseFileWatcher::setEnabledSubfileWatcher(const QUrl &subfileUrl, bool enabled) +{ + Q_UNUSED(subfileUrl) + Q_UNUSED(enabled) +} + +/*! + * \~chinese \brief 发送一个信号表示目标目录 \a targetUrl 得到了一个 \a signal 信号,包含参数 \a arg1 。 + * \~english \brief Emit a signal about \a targetUrl got a \a signal with \a arg1 + * + * \~chinese 示例用法: + * \~english Example usage: + * + * \~ \code{.cpp} + * DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileDeleted, QUrl("bookmark:///bookmarkFile1")); + * \endcode + */ +bool DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::SignalType1 signal, const QUrl &arg1) +{ + if (!signal) + return false; + + bool ok = false; + + for (DBaseFileWatcher *watcher : DBaseFileWatcherPrivate::watcherList) { + if (watcher->fileUrl() == targetUrl) { + ok = true; + (watcher->*signal)(arg1); + } + } + + return ok; +} + +/*! + * \~chinese \brief 发送一个信号表示目标目录 \a targetUrl 得到了一个 \a signal 信号,包含参数 \a arg1 和 \arg2。 + * \~english \brief Emit a signal about \a targetUrl got a \a signal with \a arg1 and \a arg2 + * + * \~chinese 示例用法: + * \~english Example usage: + * + * \~ \code{.cpp} + * DBaseFileWatcher::ghostSignal(QUrl("bookmark:///"), &DBaseFileWatcher::fileMoved, QUrl("bookmark:///bookmarkFile1"), QUrl("bookmark:///NewNameFile1")); + * \endcode + */ +bool DBaseFileWatcher::ghostSignal(const QUrl &targetUrl, DBaseFileWatcher::SignalType2 signal, const QUrl &arg1, const QUrl &arg2) +{ + if (!signal) + return false; + + bool ok = false; + + for (DBaseFileWatcher *watcher : DBaseFileWatcherPrivate::watcherList) { + if (watcher->fileUrl() == targetUrl) { + ok = true; + (watcher->*signal)(arg1, arg2); + } + } + + return ok; +} + +DBaseFileWatcher::DBaseFileWatcher(DBaseFileWatcherPrivate &dd, + const QUrl &url, QObject *parent) + : QObject(parent) + , DObject(dd) +{ + Q_ASSERT(url.isValid()); + + d_func()->url = url; + DBaseFileWatcherPrivate::watcherList << this; +} + +DCORE_END_NAMESPACE + +#include "moc_dbasefilewatcher.cpp" diff --git a/src/filesystem/dbasefilewatcher.h b/src/filesystem/dbasefilewatcher.h new file mode 100644 index 0000000..e011bd5 --- /dev/null +++ b/src/filesystem/dbasefilewatcher.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DBASEFILEWATCHER_H +#define DBASEFILEWATCHER_H + +#include "dtkcore_global.h" +#include "dobject.h" + +#include + +DCORE_BEGIN_NAMESPACE + +class DBaseFileWatcherPrivate; +class LIBDTKCORESHARED_EXPORT DBaseFileWatcher : public QObject, public DObject +{ + Q_OBJECT + +public: + ~DBaseFileWatcher(); + + QUrl fileUrl() const; + + bool startWatcher(); + bool stopWatcher(); + bool restartWatcher(); + + virtual void setEnabledSubfileWatcher(const QUrl &subfileUrl, bool enabled = true); + + using SignalType1 = void(DBaseFileWatcher::*)(const QUrl &); + using SignalType2 = void(DBaseFileWatcher::*)(const QUrl &, const QUrl &); + static bool ghostSignal(const QUrl &targetUrl, SignalType1 signal, const QUrl &arg1); + static bool ghostSignal(const QUrl &targetUrl, SignalType2 signal, const QUrl &arg1, const QUrl &arg2); + +Q_SIGNALS: + void fileDeleted(const QUrl &url); + void fileAttributeChanged(const QUrl &url); + void fileMoved(const QUrl &fromUrl, const QUrl &toUrl); + void subfileCreated(const QUrl &url); + void fileModified(const QUrl &url); + void fileClosed(const QUrl &url); + +protected: + explicit DBaseFileWatcher(DBaseFileWatcherPrivate &dd, const QUrl &url, QObject *parent = 0); + +private: + Q_DISABLE_COPY(DBaseFileWatcher) + D_DECLARE_PRIVATE(DBaseFileWatcher) +}; + +DCORE_END_NAMESPACE + +#endif // DBASEFILEWATCHER_H diff --git a/src/filesystem/dfilesystemwatcher.h b/src/filesystem/dfilesystemwatcher.h new file mode 100644 index 0000000..a8be007 --- /dev/null +++ b/src/filesystem/dfilesystemwatcher.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILESYSTEMWATCHER_H +#define DFILESYSTEMWATCHER_H + +#include "dtkcore_global.h" +#include "dobject.h" + +#include + +DCORE_BEGIN_NAMESPACE + +class DFileSystemWatcherPrivate; +class LIBDTKCORESHARED_EXPORT DFileSystemWatcher : public QObject, public DObject +{ + Q_OBJECT + D_DECLARE_PRIVATE(DFileSystemWatcher) + +public: + DFileSystemWatcher(QObject *parent = Q_NULLPTR); + DFileSystemWatcher(const QStringList &paths, QObject *parent = Q_NULLPTR); + ~DFileSystemWatcher(); + + bool addPath(const QString &file); + QStringList addPaths(const QStringList &files); + bool removePath(const QString &file); + QStringList removePaths(const QStringList &files); + + QStringList files() const; + QStringList directories() const; + +Q_SIGNALS: + void fileDeleted(const QString &path, const QString &name, QPrivateSignal); + void fileAttributeChanged(const QString &path, const QString &name, QPrivateSignal); + void fileClosed(const QString &path, const QString &name, QPrivateSignal); + void fileMoved(const QString &fromPath, const QString &fromName, + const QString &toPath, const QString &toName, QPrivateSignal); + void fileCreated(const QString &path, const QString &name, QPrivateSignal); + void fileModified(const QString &path, const QString &name, QPrivateSignal); + +private: + Q_PRIVATE_SLOT(d_func(), void _q_readFromInotify()) +}; + +DCORE_END_NAMESPACE + +#endif // DFILESYSTEMWATCHER_H diff --git a/src/filesystem/dfilesystemwatcher_dummy.cpp b/src/filesystem/dfilesystemwatcher_dummy.cpp new file mode 100644 index 0000000..bb2cf51 --- /dev/null +++ b/src/filesystem/dfilesystemwatcher_dummy.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dfilesystemwatcher.h" +#include "private/dfilesystemwatcher_dummy_p.h" + +DCORE_BEGIN_NAMESPACE + +DFileSystemWatcherPrivate::DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq) + : DObjectPrivate(qq) +{ + +} + +DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() +{ + +} + +/*! + \class DFileSystemWatcher + \inmodule QtCore + \brief The DFileSystemWatcher class provides an interface for monitoring files and directories for modifications. + \ingroup io + \since 4.2 + \reentrant + + DFileSystemWatcher monitors the file system for changes to files + and directories by watching a list of specified paths. + + Call addPath() to watch a particular file or directory. Multiple + paths can be added using the addPaths() function. Existing paths can + be removed by using the removePath() and removePaths() functions. + + DFileSystemWatcher examines each path added to it. Files that have + been added to the DFileSystemWatcher can be accessed using the + files() function, and directories using the directories() function. + + The fileChanged() signal is emitted when a file has been modified, + renamed or removed from disk. Similarly, the directoryChanged() + signal is emitted when a directory or its contents is modified or + removed. Note that DFileSystemWatcher stops monitoring files once + 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, + file systems that contain watched paths cannot be unmounted. + + \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 + 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 + example, an open file descriptor is required for each monitored + file. Some system limits the number of open file descriptors to 256 + by default. This means that addPath() and addPaths() will fail if + your process tries to add more than 256 files or directories to + the file system monitor. Also note that your process may have + other file descriptors open in addition to the ones for files + being monitored, and these other open descriptors also count in + the total. OS X uses a different backend and does not + suffer from this issue. + + + \sa QFile, QDir +*/ + + +/*! + Constructs a new file system watcher object with the given \a parent. +*/ +DFileSystemWatcher::DFileSystemWatcher(QObject *parent) + : QObject(parent) + , DObject() +{ + +} + +/*! + Constructs a new file system watcher object with the given \a parent + which monitors the specified \a paths list. +*/ +DFileSystemWatcher::DFileSystemWatcher(const QStringList &paths, QObject *parent) + : DFileSystemWatcher(parent) +{ + addPaths(paths); +} + +/*! + Destroys the file system watcher. +*/ +DFileSystemWatcher::~DFileSystemWatcher() +{ } + +/*! + 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. + + If \a path specifies a directory, the directoryChanged() signal + will be emitted when \a path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when \a path is + modified, renamed or removed. + + If the watch was successful, true is returned. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +bool DFileSystemWatcher::addPath(const QString &path) +{ + return false; +} + +/*! + 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. + + If a path specifies a directory, the directoryChanged() signal + will be emitted when the path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when the path is + modified, renamed, or removed. + + The return value is a list of paths that could not be watched. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +QStringList DFileSystemWatcher::addPaths(const QStringList &paths) +{ + return QStringList(); +} + +/*! + Removes the specified \a path from the file system watcher. + + If the watch is successfully removed, true is returned. + + 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() +*/ +bool DFileSystemWatcher::removePath(const QString &path) +{ + return false; +} + +/*! + Removes the specified \a paths from the file system watcher. + + The return value is a list of paths which were not able to be + unwatched successfully. + + 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() +*/ +QStringList DFileSystemWatcher::removePaths(const QStringList &paths) +{ + return QStringList(); +} + +/*! + \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() +*/ + +/*! + \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 + from disk. Note that if there are several changes during a short + period of time, some of the changes might not Q_EMIT this signal. + However, the last change in the sequence of changes will always + generate this signal. + + \sa fileChanged() +*/ + +/*! + \fn QStringList DFileSystemWatcher::directories() const + + Returns a list of paths to directories that are being watched. + + \sa files() +*/ + +/*! + \fn QStringList DFileSystemWatcher::files() const + + Returns a list of paths to files that are being watched. + + \sa directories() +*/ + +QStringList DFileSystemWatcher::directories() const +{ + return QStringList(); +} + +QStringList DFileSystemWatcher::files() const +{ + return QStringList(); +} + +DCORE_END_NAMESPACE + +#include "moc_dfilesystemwatcher.cpp" diff --git a/src/filesystem/dfilesystemwatcher_linux.cpp b/src/filesystem/dfilesystemwatcher_linux.cpp new file mode 100644 index 0000000..bfddfd3 --- /dev/null +++ b/src/filesystem/dfilesystemwatcher_linux.cpp @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dfilesystemwatcher.h" +#include "private/dfilesystemwatcher_linux_p.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +DFileSystemWatcherPrivate::DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq) + : DObjectPrivate(qq) + , inotifyFd(fd) + , notifier(fd, QSocketNotifier::Read, qq) +{ + fcntl(inotifyFd, F_SETFD, FD_CLOEXEC); + qq->connect(¬ifier, SIGNAL(activated(int)), qq, SLOT(_q_readFromInotify())); +} + +DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() +{ + notifier.setEnabled(false); + Q_FOREACH (int id, pathToID) + inotify_rm_watch(inotifyFd, id < 0 ? -id : id); + + ::close(inotifyFd); +} + +QStringList DFileSystemWatcherPrivate::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) +{ + QStringList p = paths; + QMutableListIterator it(p); + while (it.hasNext()) { + QString path = it.next(); + QFileInfo fi(path); + bool isDir = fi.isDir(); + if (isDir) { + if (directories->contains(path)) + continue; + } else { + if (files->contains(path)) + continue; + } + + int wd = inotify_add_watch(inotifyFd, + QFile::encodeName(path), + (isDir + ? (0 + | IN_ATTRIB + | IN_MOVE + | IN_MOVE_SELF + | IN_CREATE + | IN_DELETE + | IN_DELETE_SELF + | IN_MODIFY + ) + : (0 + | IN_ATTRIB + | IN_CLOSE_WRITE + | IN_MODIFY + | IN_MOVE + | IN_MOVE_SELF + | IN_DELETE_SELF + ))); + if (wd < 0) { + perror("DFileSystemWatcherPrivate::addPaths: inotify_add_watch failed"); + continue; + } + + it.remove(); + + int id = isDir ? -wd : wd; + if (id < 0) { + directories->append(path); + } else { + files->append(path); + } + + pathToID.insert(path, id); + idToPath.insert(id, path); + } + + return p; +} + +QStringList DFileSystemWatcherPrivate::removePaths(const QStringList &paths, QStringList *files, QStringList *directories) +{ + QStringList p = paths; + QMutableListIterator it(p); + while (it.hasNext()) { + QString path = it.next(); + int id = pathToID.take(path); + for (auto hit = idToPath.find(id); hit != idToPath.end() && hit.key() == id; ++hit) { + if (hit.value() == path) { + idToPath.erase(hit); + break; + } + } + + it.remove(); + + if (!idToPath.contains(id)) { + int wd = id < 0 ? -id : id; + //qDebug() << "removing watch for path" << path << "wd" << wd; + inotify_rm_watch(inotifyFd, wd); + } + + if (id < 0) { + directories->removeAll(path); + } else { + files->removeAll(path); + } + } + + return p; +} + +void DFileSystemWatcherPrivate::_q_readFromInotify() +{ + Q_Q(DFileSystemWatcher); +// qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify"; + + int buffSize = 0; + ioctl(inotifyFd, FIONREAD, (char *) &buffSize); + QVarLengthArray buffer(buffSize); + buffSize = read(inotifyFd, buffer.data(), buffSize); + char *at = buffer.data(); + char * const end = at + buffSize; + + QList eventList; + QMultiHash batch_pathmap; + /// only save event: IN_MOVE_TO + QMultiMap cookieToFilePath; + QMultiMap cookieToFileName; + QSet hasMoveFromByCookie; +#ifdef QT_DEBUG + int exist_count = 0; +#endif + while (at < end) { + inotify_event *event = reinterpret_cast(at); + QStringList paths; + + at += sizeof(inotify_event) + event->len; + + int id = event->wd; + paths = idToPath.values(id); + if (paths.empty()) { + // perhaps a directory? + id = -id; + paths = idToPath.values(id); + if (paths.empty()) + continue; + } + + if (!(event->mask & IN_MOVED_TO) || !hasMoveFromByCookie.contains(event->cookie)) { + auto it = std::find_if(eventList.begin(), eventList.end(), [event](inotify_event *e){ + return event->wd == e->wd && event->mask == e->mask && + event->cookie == e->cookie && + event->len == e->len && + !strcmp(event->name, e->name); + }); + + if (it==eventList.end()) { + eventList.append(event); + } +#ifdef QT_DEBUG + else { + qDebug() << "exist event:" << "event->wd" << event->wd << + "event->mask" << event->mask << + "event->cookie" << event->cookie << "exist counts " << ++exist_count; + } +#endif + const QList bps = batch_pathmap.values(id); + for (auto &path : paths) { + if (!bps.contains(path)) { + batch_pathmap.insert(id, path); + } + } + } + + if (event->mask & IN_MOVED_TO) { + for (auto &path : paths) { + cookieToFilePath.insert(event->cookie, path); + } + cookieToFileName.insert(event->cookie, QString::fromUtf8(event->name)); + } + + if (event->mask & IN_MOVED_FROM) + hasMoveFromByCookie << event->cookie; + } + +// qDebug() << "event count:" << eventList.count(); + + QList::const_iterator it = eventList.constBegin(); + while (it != eventList.constEnd()) { + const inotify_event &event = **it; + ++it; + +// qDebug() << "inotify event, wd" << event.wd << "cookie" << event.cookie << "mask" << hex << event.mask; + + int id = event.wd; + QStringList paths = batch_pathmap.values(id); + + if (paths.empty()) { + id = -id; + paths = batch_pathmap.values(id); + + if (paths.empty()) + continue; + } + const QString &name = QString::fromUtf8(event.name); + + for (auto &path : paths) { +// qDebug() << "event for path" << path; + +// /// TODO: Existence of invalid utf8 characters QFile can not read the file information +// if (event.name != QString::fromLocal8Bit(event.name).toLocal8Bit()) { +// if (event.mask & (IN_CREATE | IN_MOVED_TO)) { +// DFMGlobal::fileNameCorrection(path); +// } +// } + + 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(); + + bool isMove = false; + + while (iterator != cookieToFilePath.constEnd()) { + const QString &_path = iterator.value(); + const QString &_name = cookieToFileName.value(iterator.key()); + + if (QFileInfo(_path + QDir::separator() + _name) == QFileInfo(path)) { + isMove = true; + break; + } + + ++iterator; + } + + if (isMove) + break; + } + + /// Keep watcher +// pathToID.remove(path); +// idToPath.remove(id, getPathFromID(id)); +// if (!idToPath.contains(id)) +// inotify_rm_watch(inotifyFd, event.wd); + +// if (id < 0) +// onDirectoryChanged(path, true); +// else +// onFileChanged(path, true); + + Q_EMIT q->fileDeleted(path, QString(), DFileSystemWatcher::QPrivateSignal()); + } while (false); + } else { + if (id < 0) + onDirectoryChanged(path, false); + else + onFileChanged(path, false); + } + + QString filePath = path; + + if (id < 0) { + if (path.endsWith(QDir::separator())) + filePath = path + name; + else + filePath = path + QDir::separator() + name; + } + + if (event.mask & IN_CREATE) { +// qDebug() << "IN_CREATE" << filePath << name; + + if (name.isEmpty()) { + if (pathToID.contains(path)) { + q->removePath(path); + q->addPath(path); + } + } else if (pathToID.contains(filePath)) { + q->removePath(filePath); + q->addPath(filePath); + } + + Q_EMIT q->fileCreated(path, name, DFileSystemWatcher::QPrivateSignal()); + } + + if (event.mask & IN_DELETE) { +// qDebug() << "IN_DELETE" << filePath; + + Q_EMIT q->fileDeleted(path, name, DFileSystemWatcher::QPrivateSignal()); + } + + if (event.mask & IN_MOVED_FROM) { + const QString toName = cookieToFileName.value(event.cookie); + + if (cookieToFilePath.values(event.cookie).empty()) { + Q_EMIT q->fileMoved(path, name, QString(), QString(), DFileSystemWatcher::QPrivateSignal()); + } else { + for (QString &toPath : cookieToFilePath.values(event.cookie)) { +// qDebug() << "IN_MOVED_FROM" << filePath << "to path:" << toPath << "to name:" << toName; + + Q_EMIT q->fileMoved(path, name, toPath, toName, DFileSystemWatcher::QPrivateSignal()); + } + } + } + + if (event.mask & IN_MOVED_TO) { +// qDebug() << "IN_MOVED_TO" << filePath; + + if (!hasMoveFromByCookie.contains(event.cookie)) + Q_EMIT q->fileMoved(QString(), QString(), path, name, DFileSystemWatcher::QPrivateSignal()); + } + + if (event.mask & IN_ATTRIB) { +// qDebug() << "IN_ATTRIB" << event.mask << filePath; + + Q_EMIT q->fileAttributeChanged(path, name, DFileSystemWatcher::QPrivateSignal()); + } + + /*only monitor file close event which is opend by write mode*/ + if (event.mask & IN_CLOSE_WRITE) { +// qDebug() << "IN_CLOSE_WRITE" << event.mask << filePath; + + Q_EMIT q->fileClosed(path, id < 0 ? name : QString(), DFileSystemWatcher::QPrivateSignal()); + } + + if (event.mask & IN_MODIFY) { +// qDebug() << "IN_MODIFY" << event.mask << filePath << name; + + Q_EMIT q->fileModified(path, name, DFileSystemWatcher::QPrivateSignal()); + } + } + } +} + +void DFileSystemWatcherPrivate::onFileChanged(const QString &path, bool removed) +{ + Q_Q(DFileSystemWatcher); + if (!files.contains(path)) { + // the path was removed after a change was detected, but before we delivered the signal + return; + } + if (removed) { + files.removeAll(path); + } +// Q_EMIT q->fileChanged(path, DFileSystemWatcher::QPrivateSignal()); +} + +void DFileSystemWatcherPrivate::onDirectoryChanged(const QString &path, bool removed) +{ + Q_Q(DFileSystemWatcher); + if (!directories.contains(path)) { + // perhaps the path was removed after a change was detected, but before we delivered the signal + return; + } + if (removed) { + directories.removeAll(path); + } +// Q_EMIT q->directoryChanged(path, DFileSystemWatcher::QPrivateSignal()); +} + +/*! + \class DFileSystemWatcher + \inmodule QtCore + \brief The DFileSystemWatcher class provides an interface for monitoring files and directories for modifications. + \ingroup io + \since 4.2 + \reentrant + + DFileSystemWatcher monitors the file system for changes to files + and directories by watching a list of specified paths. + + Call addPath() to watch a particular file or directory. Multiple + paths can be added using the addPaths() function. Existing paths can + be removed by using the removePath() and removePaths() functions. + + DFileSystemWatcher examines each path added to it. Files that have + been added to the DFileSystemWatcher can be accessed using the + files() function, and directories using the directories() function. + + The fileChanged() signal is emitted when a file has been modified, + renamed or removed from disk. Similarly, the directoryChanged() + signal is emitted when a directory or its contents is modified or + removed. Note that DFileSystemWatcher stops monitoring files once + 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, + file systems that contain watched paths cannot be unmounted. + + \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 + 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 + example, an open file descriptor is required for each monitored + file. Some system limits the number of open file descriptors to 256 + by default. This means that addPath() and addPaths() will fail if + your process tries to add more than 256 files or directories to + the file system monitor. Also note that your process may have + other file descriptors open in addition to the ones for files + being monitored, and these other open descriptors also count in + the total. OS X uses a different backend and does not + suffer from this issue. + + + \sa QFile, QDir +*/ + + +/*! + Constructs a new file system watcher object with the given \a parent. +*/ +DFileSystemWatcher::DFileSystemWatcher(QObject *parent) + : QObject(parent) + , DObject() +{ + int fd = -1; +#ifdef IN_CLOEXEC + fd = inotify_init1(IN_CLOEXEC | O_NONBLOCK); +#endif + if (fd == -1) { + fd = inotify_init1(O_NONBLOCK); + } + + if (fd != -1) + d_d_ptr.reset(new DFileSystemWatcherPrivate(fd, this)); +} + +/*! + Constructs a new file system watcher object with the given \a parent + which monitors the specified \a paths list. +*/ +DFileSystemWatcher::DFileSystemWatcher(const QStringList &paths, QObject *parent) + : DFileSystemWatcher(parent) +{ + addPaths(paths); +} + +/*! + Destroys the file system watcher. +*/ +DFileSystemWatcher::~DFileSystemWatcher() +{ } + +/*! + 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. + + If \a path specifies a directory, the directoryChanged() signal + will be emitted when \a path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when \a path is + modified, renamed or removed. + + If the watch was successful, true is returned. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +bool DFileSystemWatcher::addPath(const QString &path) +{ + if (path.isEmpty()) { + qWarning("DFileSystemWatcher::addPath: path is empty"); + return true; + } + + QStringList paths = addPaths(QStringList(path)); + return paths.isEmpty(); +} + +/*! + 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. + + If a path specifies a directory, the directoryChanged() signal + will be emitted when the path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when the path is + modified, renamed, or removed. + + The return value is a list of paths that could not be watched. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +QStringList DFileSystemWatcher::addPaths(const QStringList &paths) +{ + Q_D(DFileSystemWatcher); + + QStringList p = paths; + QMutableListIterator it(p); + + while (it.hasNext()) { + const QString &path = it.next(); + if (path.isEmpty()) + it.remove(); + } + + if (p.isEmpty()) { + qWarning("DFileSystemWatcher::addPaths: list is empty"); + return QStringList(); + } + + if (d) + p = d->addPaths(p, &d->files, &d->directories); + + return p; +} + +/*! + Removes the specified \a path from the file system watcher. + + If the watch is successfully removed, true is returned. + + 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() +*/ +bool DFileSystemWatcher::removePath(const QString &path) +{ + if (path.isEmpty()) { + qWarning("DFileSystemWatcher::removePath: path is empty"); + return true; + } + + QStringList paths = removePaths(QStringList(path)); + return paths.isEmpty(); +} + +/*! + Removes the specified \a paths from the file system watcher. + + The return value is a list of paths which were not able to be + unwatched successfully. + + 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() +*/ +QStringList DFileSystemWatcher::removePaths(const QStringList &paths) +{ + Q_D(DFileSystemWatcher); + + QStringList p = paths; + QMutableListIterator it(p); + + while (it.hasNext()) { + const QString &path = it.next(); + if (path.isEmpty()) + it.remove(); + } + + if (p.isEmpty()) { + qWarning("DFileSystemWatcher::removePaths: list is empty"); + return QStringList(); + } + + if (d) + p = d->removePaths(p, &d->files, &d->directories); + + return p; +} + +/*! + \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() +*/ + +/*! + \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 + from disk. Note that if there are several changes during a short + period of time, some of the changes might not Q_EMIT this signal. + However, the last change in the sequence of changes will always + generate this signal. + + \sa fileChanged() +*/ + +/*! + \fn QStringList DFileSystemWatcher::directories() const + + Returns a list of paths to directories that are being watched. + + \sa files() +*/ + +/*! + \fn QStringList DFileSystemWatcher::files() const + + Returns a list of paths to files that are being watched. + + \sa directories() +*/ + +QStringList DFileSystemWatcher::directories() const +{ + Q_D(const DFileSystemWatcher); + + if (!d) + return QStringList(); + + return d->directories; +} + +QStringList DFileSystemWatcher::files() const +{ + Q_D(const DFileSystemWatcher); + + if (!d) + return QStringList(); + + return d->files; +} + +DCORE_END_NAMESPACE + +#include "moc_dfilesystemwatcher.cpp" diff --git a/src/filesystem/dfilesystemwatcher_win.cpp b/src/filesystem/dfilesystemwatcher_win.cpp new file mode 100644 index 0000000..826ad25 --- /dev/null +++ b/src/filesystem/dfilesystemwatcher_win.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dfilesystemwatcher.h" +#include "private/dfilesystemwatcher_win_p.h" + +DCORE_BEGIN_NAMESPACE + +DFileSystemWatcherPrivate::DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq) + : DObjectPrivate(qq) +{ + +} + +DFileSystemWatcherPrivate::~DFileSystemWatcherPrivate() +{ + +} + +/*! + \class DFileSystemWatcher + \inmodule QtCore + \brief The DFileSystemWatcher class provides an interface for monitoring files and directories for modifications. + \ingroup io + \since 4.2 + \reentrant + + DFileSystemWatcher monitors the file system for changes to files + and directories by watching a list of specified paths. + + Call addPath() to watch a particular file or directory. Multiple + paths can be added using the addPaths() function. Existing paths can + be removed by using the removePath() and removePaths() functions. + + DFileSystemWatcher examines each path added to it. Files that have + been added to the DFileSystemWatcher can be accessed using the + files() function, and directories using the directories() function. + + The fileChanged() signal is emitted when a file has been modified, + renamed or removed from disk. Similarly, the directoryChanged() + signal is emitted when a directory or its contents is modified or + removed. Note that DFileSystemWatcher stops monitoring files once + 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, + file systems that contain watched paths cannot be unmounted. + + \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 + 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 + example, an open file descriptor is required for each monitored + file. Some system limits the number of open file descriptors to 256 + by default. This means that addPath() and addPaths() will fail if + your process tries to add more than 256 files or directories to + the file system monitor. Also note that your process may have + other file descriptors open in addition to the ones for files + being monitored, and these other open descriptors also count in + the total. OS X uses a different backend and does not + suffer from this issue. + + + \sa QFile, QDir +*/ + + +/*! + Constructs a new file system watcher object with the given \a parent. +*/ +DFileSystemWatcher::DFileSystemWatcher(QObject *parent) + : QObject(parent) + , DObject() +{ + +} + +/*! + Constructs a new file system watcher object with the given \a parent + which monitors the specified \a paths list. +*/ +DFileSystemWatcher::DFileSystemWatcher(const QStringList &paths, QObject *parent) + : DFileSystemWatcher(parent) +{ + addPaths(paths); +} + +/*! + Destroys the file system watcher. +*/ +DFileSystemWatcher::~DFileSystemWatcher() +{ } + +/*! + 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. + + If \a path specifies a directory, the directoryChanged() signal + will be emitted when \a path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when \a path is + modified, renamed or removed. + + If the watch was successful, true is returned. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +bool DFileSystemWatcher::addPath(const QString &path) +{ + return false; +} + +/*! + 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. + + If a path specifies a directory, the directoryChanged() signal + will be emitted when the path is modified or removed from disk; + otherwise the fileChanged() signal is emitted when the path is + modified, renamed, or removed. + + The return value is a list of paths that could not be watched. + + Reasons for a watch failure are generally system-dependent, but + 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 + 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() +*/ +QStringList DFileSystemWatcher::addPaths(const QStringList &paths) +{ + return QStringList(); +} + +/*! + Removes the specified \a path from the file system watcher. + + If the watch is successfully removed, true is returned. + + 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() +*/ +bool DFileSystemWatcher::removePath(const QString &path) +{ + return false; +} + +/*! + Removes the specified \a paths from the file system watcher. + + The return value is a list of paths which were not able to be + unwatched successfully. + + 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() +*/ +QStringList DFileSystemWatcher::removePaths(const QStringList &paths) +{ + return QStringList(); +} + +/*! + \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() +*/ + +/*! + \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 + from disk. Note that if there are several changes during a short + period of time, some of the changes might not Q_EMIT this signal. + However, the last change in the sequence of changes will always + generate this signal. + + \sa fileChanged() +*/ + +/*! + \fn QStringList DFileSystemWatcher::directories() const + + Returns a list of paths to directories that are being watched. + + \sa files() +*/ + +/*! + \fn QStringList DFileSystemWatcher::files() const + + Returns a list of paths to files that are being watched. + + \sa directories() +*/ + +QStringList DFileSystemWatcher::directories() const +{ + return QStringList(); +} + +QStringList DFileSystemWatcher::files() const +{ + return QStringList(); +} + +DCORE_END_NAMESPACE + +#include "moc_dfilesystemwatcher.cpp" diff --git a/src/filesystem/dfilewatcher.cpp b/src/filesystem/dfilewatcher.cpp new file mode 100644 index 0000000..fb06711 --- /dev/null +++ b/src/filesystem/dfilewatcher.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dfilewatcher.h" +#include "private/dbasefilewatcher_p.h" + +#include "dfilesystemwatcher.h" + +#include +#include + +DCORE_BEGIN_NAMESPACE + +static QString joinFilePath(const QString &path, const QString &name) +{ + if (path.endsWith(QDir::separator())) + return path + name; + + return path + QDir::separator() + name; +} + +class DFileWatcherPrivate : DBaseFileWatcherPrivate +{ +public: + DFileWatcherPrivate(DFileWatcher *qq) + : DBaseFileWatcherPrivate(qq) {} + + bool start() Q_DECL_OVERRIDE; + bool stop() Q_DECL_OVERRIDE; + + void _q_handleFileDeleted(const QString &path, const QString &parentPath); + void _q_handleFileAttributeChanged(const QString &path, const QString &parentPath); + void _q_handleFileMoved(const QString &from, const QString &fromParent, const QString &to, const QString &toParent); + void _q_handleFileCreated(const QString &path, const QString &parentPath); + void _q_handleFileModified(const QString &path, const QString &parentPath); + void _q_handleFileClose(const QString &path, const QString &parentPath); + + static QString formatPath(const QString &path); + + QString path; + QStringList watchFileList; + + static QMap filePathToWatcherCount; + + Q_DECLARE_PUBLIC(DFileWatcher) +}; + +QMap DFileWatcherPrivate::filePathToWatcherCount; +Q_GLOBAL_STATIC(DFileSystemWatcher, watcher_file_private) + +QStringList parentPathList(const QString &path) +{ + QStringList list; + QDir dir(path); + + list << path; + + while (dir.cdUp()) { + list << dir.absolutePath(); + } + + return list; +} + +bool DFileWatcherPrivate::start() +{ + Q_Q(DFileWatcher); + + started = true; + + Q_FOREACH (const QString &path, parentPathList(this->path)) { + if (watchFileList.contains(path)) + continue; + + if (filePathToWatcherCount.value(path, -1) <= 0) { + if (!watcher_file_private->addPath(path)) { + qWarning() << Q_FUNC_INFO << "start watch failed, file path =" << path; + q->stopWatcher(); + started = false; + return false; + } + } + + watchFileList << path; + filePathToWatcherCount[path] = filePathToWatcherCount.value(path, 0) + 1; + } + + q->connect(watcher_file_private, &DFileSystemWatcher::fileDeleted, + q, &DFileWatcher::onFileDeleted); + q->connect(watcher_file_private, &DFileSystemWatcher::fileAttributeChanged, + q, &DFileWatcher::onFileAttributeChanged); + q->connect(watcher_file_private, &DFileSystemWatcher::fileMoved, + q, &DFileWatcher::onFileMoved); + q->connect(watcher_file_private, &DFileSystemWatcher::fileCreated, + q, &DFileWatcher::onFileCreated); + q->connect(watcher_file_private, &DFileSystemWatcher::fileModified, + q, &DFileWatcher::onFileModified); + q->connect(watcher_file_private, &DFileSystemWatcher::fileClosed, + q, &DFileWatcher::onFileClosed); + + return true; +} + +bool DFileWatcherPrivate::stop() +{ + Q_Q(DFileWatcher); + + q->disconnect(watcher_file_private, 0, q, 0); + + bool ok = true; + + Q_FOREACH (const QString &path, watchFileList) { + int count = filePathToWatcherCount.value(path, 0); + + --count; + + if (count <= 0) { + filePathToWatcherCount.remove(path); + watchFileList.removeOne(path); + ok = ok && watcher_file_private->removePath(path); + } else { + filePathToWatcherCount[path] = count; + } + } + + return ok; +} + +void DFileWatcherPrivate::_q_handleFileDeleted(const QString &path, const QString &parentPath) +{ + if (path != this->path && parentPath != this->path) + return; + + Q_Q(DFileWatcher); + + Q_EMIT q->fileDeleted(QUrl::fromLocalFile(path)); +} + +void DFileWatcherPrivate::_q_handleFileAttributeChanged(const QString &path, const QString &parentPath) +{ + if (path != this->path && parentPath != this->path) + return; + + Q_Q(DFileWatcher); + + Q_EMIT q->fileAttributeChanged(QUrl::fromLocalFile(path)); +} + +void DFileWatcherPrivate::_q_handleFileMoved(const QString &from, const QString &fromParent, const QString &to, const QString &toParent) +{ + Q_Q(DFileWatcher); + + if ((fromParent == this->path && toParent == this->path) || from == this->path) { + Q_EMIT q->fileMoved(QUrl::fromLocalFile(from), QUrl::fromLocalFile(to)); + } else if (fromParent == this->path) { + Q_EMIT q->fileDeleted(QUrl::fromLocalFile(from)); + } else if (watchFileList.contains(from)) { + Q_EMIT q->fileDeleted(url); + } else if (toParent == this->path) { + Q_EMIT q->subfileCreated(QUrl::fromLocalFile(to)); + } +} + +void DFileWatcherPrivate::_q_handleFileCreated(const QString &path, const QString &parentPath) +{ + if (path != this->path && parentPath != this->path) + return; + + Q_Q(DFileWatcher); + + Q_EMIT q->subfileCreated(QUrl::fromLocalFile(path)); +} + +void DFileWatcherPrivate::_q_handleFileModified(const QString &path, const QString &parentPath) +{ + if (path != this->path && parentPath != this->path) + return; + + Q_Q(DFileWatcher); + + Q_EMIT q->fileModified(QUrl::fromLocalFile(path)); +} + +void DFileWatcherPrivate::_q_handleFileClose(const QString &path, const QString &parentPath) +{ + if (path != this->path && parentPath != this->path) + return; + + Q_Q(DFileWatcher); + + Q_EMIT q->fileClosed(QUrl::fromLocalFile(path)); +} + +QString DFileWatcherPrivate::formatPath(const QString &path) +{ + QString p = QFileInfo(path).absoluteFilePath(); + + if (p.endsWith(QDir::separator())) + p.chop(1); + + return p.isEmpty() ? path : p; +} + +/*! + \~english \class DFileWatcher + \~english \brief The DFileWatcher class provides an implemention of DBaseFileWatcher for monitoring files and directories for modifications. +*/ + +/*! + \~chinese \class DFileWatcher + \~chinese \brief DFileWatcher 类提供了对 DBaseFileWatcher 接口的实现,可供监视文件和目录的变动。 +*/ + +DFileWatcher::DFileWatcher(const QString &filePath, QObject *parent) + : DBaseFileWatcher(*new DFileWatcherPrivate(this), QUrl::fromLocalFile(filePath), parent) +{ + d_func()->path = DFileWatcherPrivate::formatPath(filePath); +} + +void DFileWatcher::onFileDeleted(const QString &path, const QString &name) +{ + if (name.isEmpty()) + d_func()->_q_handleFileDeleted(path, QString()); + else + d_func()->_q_handleFileDeleted(joinFilePath(path, name), path); +} + +void DFileWatcher::onFileAttributeChanged(const QString &path, const QString &name) +{ + if (name.isEmpty()) + d_func()->_q_handleFileAttributeChanged(path, QString()); + else + d_func()->_q_handleFileAttributeChanged(joinFilePath(path, name), path); +} + +void DFileWatcher::onFileMoved(const QString &from, const QString &fname, const QString &to, const QString &tname) +{ + QString fromPath, fpPath; + QString toPath, tpPath; + + if (fname.isEmpty()) { + fromPath = from; + } else { + fromPath = joinFilePath(from, fname); + fpPath = from; + } + + if (tname.isEmpty()) { + toPath = to; + } else { + toPath = joinFilePath(to, tname); + tpPath = to; + } + + d_func()->_q_handleFileMoved(fromPath, fpPath, toPath, tpPath); +} + +void DFileWatcher::onFileCreated(const QString &path, const QString &name) +{ + d_func()->_q_handleFileCreated(joinFilePath(path, name), path); +} + +void DFileWatcher::onFileModified(const QString &path, const QString &name) +{ + if (name.isEmpty()) + d_func()->_q_handleFileModified(path, QString()); + else + d_func()->_q_handleFileModified(joinFilePath(path, name), path); +} + +void DFileWatcher::onFileClosed(const QString &path, const QString &name) +{ + if (name.isEmpty()) + d_func()->_q_handleFileClose(path, QString()); + else + d_func()->_q_handleFileClose(joinFilePath(path, name), path); +} + +DCORE_END_NAMESPACE + +#include "moc_dfilewatcher.cpp" diff --git a/src/filesystem/dfilewatcher.h b/src/filesystem/dfilewatcher.h new file mode 100644 index 0000000..ba893a3 --- /dev/null +++ b/src/filesystem/dfilewatcher.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILEWATCHER_H +#define DFILEWATCHER_H + +#include "dbasefilewatcher.h" + +DCORE_BEGIN_NAMESPACE + +class DFileWatcherPrivate; +class LIBDTKCORESHARED_EXPORT DFileWatcher : public DBaseFileWatcher +{ + Q_OBJECT + +public: + explicit DFileWatcher(const QString &filePath, QObject *parent = 0); + +private Q_SLOTS: + void onFileDeleted(const QString &path, const QString &name); + void onFileAttributeChanged(const QString &path, const QString &name); + void onFileMoved(const QString &fromPath, const QString &fromName, + const QString &toPath, const QString &toName); + void onFileCreated(const QString &path, const QString &name); + void onFileModified(const QString &path, const QString &name); + void onFileClosed(const QString &path, const QString &name); + +private: + D_DECLARE_PRIVATE(DFileWatcher) +}; + +DCORE_END_NAMESPACE + +#endif // DFILEWATCHER_H diff --git a/src/filesystem/dfilewatchermanager.cpp b/src/filesystem/dfilewatchermanager.cpp new file mode 100644 index 0000000..128a40f --- /dev/null +++ b/src/filesystem/dfilewatchermanager.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dfilewatchermanager.h" +#include "dfilewatcher.h" +#include "base/private/dobject_p.h" + +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DFileWatcherManagerPrivate : public DObjectPrivate +{ +public: + DFileWatcherManagerPrivate(DFileWatcherManager *qq); + + QMap watchersMap; + + D_DECLARE_PUBLIC(DFileWatcherManager) +}; + +DFileWatcherManagerPrivate::DFileWatcherManagerPrivate(DFileWatcherManager *qq) + : DObjectPrivate(qq) +{ + +} + +/*! + \~english \class DFileWatcherManager + \~english \brief The DFileWatcherManager class can help you manage file watchers and get signal when file got changed. +*/ + +/*! + \~chinese \class DFileWatcherManager + \~chinese \brief DFileWatcherManager 类可以帮助管理一系列 DFileWatcher 文件监视器,并在文件变动时发送信号通知。 +*/ + +DFileWatcherManager::DFileWatcherManager(QObject *parent) + : QObject(parent) + , DObject(*new DFileWatcherManagerPrivate(this)) +{ + +} + +DFileWatcherManager::~DFileWatcherManager() +{ + +} + +/*! + * \~chinese \brief 为路径 \a filePatch 创建 DFileWatcher 并将其添加到 DFileWatcherManager 中. + * \~english \brief Add file watcher for \a filePatch to the file watcher manager. + * + * \~chinese \return 被创建并添加到 DFileWatcherManager 的 DFileWatcher + * \~english \return The file watcher which got created and added into the file watcher manager. + */ +DFileWatcher *DFileWatcherManager::add(const QString &filePath) +{ + Q_D(DFileWatcherManager); + + DFileWatcher *watcher = d->watchersMap.value(filePath); + + if (watcher) { + return watcher; + } + + watcher = new DFileWatcher(filePath, this); + + 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) { + Q_EMIT fileMoved(fromUrl.toLocalFile(), toUrl.toLocalFile()); + }); + connect(watcher, &DFileWatcher::subfileCreated, this, [this](const QUrl & url) { + Q_EMIT subfileCreated(url.toLocalFile()); + }); + + d->watchersMap[filePath] = watcher; + watcher->startWatcher(); + + return watcher; +} + +/*! + * \~chinese \brief 从当前 DFileWatcherManager 中移除监视 \a filePath 的 DFileWatcher. + * \~english \brief Remove file watcher for \a filePatch from the file watcher manager. + */ +void DFileWatcherManager::remove(const QString &filePath) +{ + Q_D(DFileWatcherManager); + + DFileWatcher *watcher = d->watchersMap.take(filePath); + + if (watcher) { + watcher->deleteLater(); + } +} + +DCORE_END_NAMESPACE diff --git a/src/filesystem/dfilewatchermanager.h b/src/filesystem/dfilewatchermanager.h new file mode 100644 index 0000000..4021495 --- /dev/null +++ b/src/filesystem/dfilewatchermanager.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILEWATCHERMANAGER_H +#define DFILEWATCHERMANAGER_H + +#include "dtkcore_global.h" +#include "dobject.h" + +#include + +DCORE_BEGIN_NAMESPACE + +class DFileWatcher; + +class DFileWatcherManagerPrivate; +class LIBDTKCORESHARED_EXPORT DFileWatcherManager : public QObject, public DObject +{ + Q_OBJECT + +public: + explicit DFileWatcherManager(QObject *parent = 0); + ~DFileWatcherManager(); + + DFileWatcher *add(const QString &filePath); + void remove(const QString &filePath); + +Q_SIGNALS: + void fileDeleted(const QString &filePath); + void fileAttributeChanged(const QString &filePath); + void fileMoved(const QString &fromFilePath, const QString &toFilePath); + void subfileCreated(const QString &filePath); + void fileModified(const QString &filePath); + void fileClosed(const QString &filePath); + +private: + QScopedPointer d_ptr; + + D_DECLARE_PRIVATE(DFileWatcherManager) + Q_DISABLE_COPY(DFileWatcherManager) +}; + +DCORE_END_NAMESPACE + +#endif // DFILEWATCHERMANAGER_H diff --git a/src/filesystem/dpathbuf.cpp b/src/filesystem/dpathbuf.cpp new file mode 100644 index 0000000..c36195d --- /dev/null +++ b/src/filesystem/dpathbuf.cpp @@ -0,0 +1,36 @@ +#include "dpathbuf.h" + +/*! + * \~english \class Dtk::Core::DPathBuf + * \brief Dtk::Core::DPathBuf cat path friendly and supoort multiplatform. + */ + +/*! + * \~chinese \class Dtk::Core::DPathBuf + * \brief Dtk::Core::DPathBuf是一个用于跨平台拼接路径的辅助类。 + * 它能够方便的写出链式结构的路径拼接代码。 +``` +DPathBuf logPath(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first()); +logPath = logPath / ".cache" / "deepin" / "deepin-test-dtk" / "deepin-test-dtk.log"; +``` + */ + + +DCORE_BEGIN_NAMESPACE + +/*! + * \brief Create Dtk::Core::DPathBuf from string. + * \param path + */ +DPathBuf::DPathBuf(const QString &path) +{ + m_path = QDir(path).absolutePath(); +} + +DPathBuf::DPathBuf() + : DPathBuf(QString()) +{ + +} + +DCORE_END_NAMESPACE diff --git a/src/filesystem/dpathbuf.h b/src/filesystem/dpathbuf.h new file mode 100644 index 0000000..23a8697 --- /dev/null +++ b/src/filesystem/dpathbuf.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "dtkcore_global.h" + +DCORE_BEGIN_NAMESPACE + +class LIBDTKCORESHARED_EXPORT DPathBuf +{ +public: + DPathBuf(); + DPathBuf(const QString &path); + + /*! + * \brief join path with operator / + * \param p is subpath + * \return a new DPathBuf with subpath p + */ + DPathBuf operator/(const QString &p) const + { + return DPathBuf(m_path + "/" + p); + } + + /*! + * \brief join path to self with operator /= + * \param p is subpath to join + * \return self object + */ + DPathBuf &operator/=(const QString &p) + { + return join(p); + } + + /*! + * \brief join path with operator / + * \param p is subpath + * \return a new DPathBuf with subpath p + * \sa Dtk::Core::DPathBuf::operator/(const QString &p) const + */ + DPathBuf operator/(const char *p) const + { + return operator /(QString(p)); + } + + /*! + * \brief join path to self with operator /= + * \param p is subpath to join + * \return self object + * \sa Dtk::Core::DPathBuf::operator/=(const QString &p) + */ + DPathBuf &operator/=(const char *p) + { + return operator /=(QString(p)); + } + + /*! + * \brief join add subpath p to self + * \param p is subpath to join + * \return slef object with subpath joined + */ + DPathBuf &join(const QString &p) + { + m_path += "/" + p; + m_path = QDir(m_path).absolutePath(); + return *this; + } + + /*! + * \brief toString export native separators format string. + * \return string with native separators + */ + QString toString() const + { + return QDir::toNativeSeparators(m_path); + } + +private: + QString m_path; +}; + +DCORE_END_NAMESPACE diff --git a/src/filesystem/dstandardpaths.cpp b/src/filesystem/dstandardpaths.cpp new file mode 100644 index 0000000..4177a9e --- /dev/null +++ b/src/filesystem/dstandardpaths.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dstandardpaths.h" + +#include + +DCORE_BEGIN_NAMESPACE + +class DSnapStandardPathsPrivate +{ +public: + inline static QString writableLocation(QStandardPaths::StandardLocation /*type*/) + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("SNAP_USER_COMMON"); + } + + inline static QStringList standardLocations(QStandardPaths::StandardLocation type) + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + switch (type) { + case QStandardPaths::GenericDataLocation: { + QString snapRoot = env.value("SNAP"); + QString genericDataDir = snapRoot + "/usr/share/"; + return QStringList() << genericDataDir; + } + default: + break; + } + + return QStringList() << env.value("SNAP_USER_COMMON"); + } + +private: + DSnapStandardPathsPrivate(); + ~DSnapStandardPathsPrivate(); + Q_DISABLE_COPY(DSnapStandardPathsPrivate) +}; + + +/*! + * \~chinese \class Dtk::Core::DStandardPaths + * \brief DStandardPaths提供兼容Snap/Dtk标准的路径模式。DStandardPaths实现了Qt的QStandardPaths主要接口。 + * \sa QStandardPaths + * + * \enum DStandardPaths::Mode + * \brief DStandardPaths支持的路径产生模式。 + * \var DStandardPaths::Mode DStandardPaths::Auto + * \brief 和Qt标准的行为表现一致。 + * \var DStandardPaths::Mode DStandardPaths::Snap + * \brief 读取SNAP相关的环境变量,支持将配置存储在SNAP对应目录。 + * \var DStandardPaths::Mode DStandardPaths::Test + * \brief 和Qt标准的行为表现一致,但是会开启测试模式,参考QStandardPaths::setTestModeEnabled。 + */ + + +static DStandardPaths::Mode s_mode = DStandardPaths::Auto; + +QString DStandardPaths::writableLocation(QStandardPaths::StandardLocation type) +{ + switch (s_mode) { + case Auto: + case Test: + return QStandardPaths::writableLocation(type); + case Snap: + return DSnapStandardPathsPrivate::writableLocation(type); + } + return QStandardPaths::writableLocation(type); +} + +QStringList DStandardPaths::standardLocations(QStandardPaths::StandardLocation type) +{ + switch (s_mode) { + case Auto: + case Test: + return QStandardPaths::standardLocations(type); + case Snap: + return DSnapStandardPathsPrivate::standardLocations(type); + } + return QStandardPaths::standardLocations(type); +} + +QString DStandardPaths::locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options) +{ + return QStandardPaths::locate(type, fileName, options); +} + +QStringList DStandardPaths::locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options) +{ + return QStandardPaths::locateAll(type, fileName, options); +} + +QString DStandardPaths::findExecutable(const QString &executableName, const QStringList &paths) +{ + return QStandardPaths::findExecutable(executableName, paths); +} + +void DStandardPaths::setMode(DStandardPaths::Mode mode) +{ + s_mode = mode; + QStandardPaths::setTestModeEnabled(mode == Test); +} + +DCORE_END_NAMESPACE diff --git a/src/filesystem/dstandardpaths.h b/src/filesystem/dstandardpaths.h new file mode 100644 index 0000000..5323fe4 --- /dev/null +++ b/src/filesystem/dstandardpaths.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DTK_CORE_FILESYSTEM_DSTANDARDPATHS_H +#define DTK_CORE_FILESYSTEM_DSTANDARDPATHS_H + +#include + +#include "dtkcore_global.h" + +DCORE_BEGIN_NAMESPACE + +class DStandardPathsPrivate; +class LIBDTKCORESHARED_EXPORT DStandardPaths +{ +public: + enum Mode { + Auto, + Snap, + Test, + }; + + static QString writableLocation(QStandardPaths::StandardLocation type); + static QStringList standardLocations(QStandardPaths::StandardLocation type); + + static QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile); + static QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = QStandardPaths::LocateFile); + static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList()); + static void setMode(Mode mode); + +private: + DStandardPaths(); + ~DStandardPaths(); + Q_DISABLE_COPY(DStandardPaths) +}; + +DCORE_END_NAMESPACE + +#endif // DTK_CORE_FILESYSTEM_DSTANDARDPATHS_H diff --git a/src/filesystem/dtrashmanager.h b/src/filesystem/dtrashmanager.h new file mode 100644 index 0000000..f192a4e --- /dev/null +++ b/src/filesystem/dtrashmanager.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DTRASHMANAGER_H +#define DTRASHMANAGER_H + +#include +#include + +#include + +DCORE_BEGIN_NAMESPACE + +class DTrashManagerPrivate; +class DTrashManager : public QObject, public DObject +{ +public: + static DTrashManager *instance(); + + bool trashIsEmpty() const; + bool cleanTrash(); + bool moveToTrash(const QString &filePath, bool followSymlink = false); + +protected: + DTrashManager(); + +private: + D_DECLARE_PRIVATE(DTrashManager) +}; + +DCORE_END_NAMESPACE + +#endif // DTRASHMANAGER_H diff --git a/src/filesystem/dtrashmanager_dummy.cpp b/src/filesystem/dtrashmanager_dummy.cpp new file mode 100644 index 0000000..054b7d7 --- /dev/null +++ b/src/filesystem/dtrashmanager_dummy.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dtrashmanager.h" + +#include "DObjectPrivate" + +#include +#include +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DTrashManager_ : public DTrashManager {}; +Q_GLOBAL_STATIC(DTrashManager_, globalTrashManager) + +static QString getNotExistsFileName(const QString &fileName, const QString &targetPath) +{ + QByteArray name = fileName.toUtf8(); + + int index = name.lastIndexOf('.'); + QByteArray suffix; + + if (index >= 0) + { + suffix = name.mid(index); + } + + if (suffix.size() > 200) + { + suffix = suffix.left(200); + } + + name.chop(suffix.size()); + name = name.left(200 - suffix.size()); + + while (QFile::exists(targetPath + "/" + name + suffix)) + { + name = QCryptographicHash::hash(name, QCryptographicHash::Md5).toHex(); + } + + return QString::fromUtf8(name + suffix); +} + +static bool renameFile(const QFileInfo &fileInfo, const QString &target, QString *errorString = NULL) +{ + if (fileInfo.isFile() || fileInfo.isSymLink()) + { + QFile file(fileInfo.filePath()); + + if (!file.rename(target)) + { + if (errorString) + { + *errorString = file.errorString(); + } + + return false; + } + + return true; + } + else + { + QDirIterator iterator(fileInfo.filePath(), + QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); + + while (iterator.hasNext()) + { + iterator.next(); + + const QString newFile = iterator.filePath().replace(0, fileInfo.filePath().length(), target); + + if (!QDir().mkpath(QFileInfo(newFile).path())) + { + if (errorString) + { + *errorString = QString("Make the %1 path is failed").arg(QFileInfo(newFile).path()); + } + + return false; + } + + if (!renameFile(iterator.fileInfo(), newFile, errorString)) + { + return false; + } + } + + if (!QDir().rmdir(fileInfo.filePath())) + { + if (errorString) + { + *errorString = QString("Cannot remove the %1 dir").arg(fileInfo.filePath()); + } + + return false; + } + } + + return true; +} + +class DTrashManagerPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DTrashManagerPrivate(DTrashManager *q_ptr) + : DObjectPrivate(q_ptr) {} + + D_DECLARE_PUBLIC(DTrashManager) +}; + +DTrashManager *DTrashManager::instance() +{ + return globalTrashManager; +} + +bool DTrashManager::trashIsEmpty() const +{ + return false; +} + +bool DTrashManager::cleanTrash() +{ + return false; +} + +bool DTrashManager::moveToTrash(const QString &filePath, bool followSymlink) +{ + return false; +} + +DTrashManager::DTrashManager() + : QObject() + , DObject(*new DTrashManagerPrivate(this)) +{ + +} + +DCORE_END_NAMESPACE diff --git a/src/filesystem/dtrashmanager_linux.cpp b/src/filesystem/dtrashmanager_linux.cpp new file mode 100644 index 0000000..38446a5 --- /dev/null +++ b/src/filesystem/dtrashmanager_linux.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "dtrashmanager.h" +#include "dstandardpaths.h" +#include "private/dobject_p.h" + +#include +#include +#include +#include +#include + +#define TRASH_PATH \ + DStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/Trash" +#define TRASH_INFO_PATH TRASH_PATH"/info" +#define TRASH_FILES_PATH TRASH_PATH"/files" + +DCORE_BEGIN_NAMESPACE + +class DTrashManager_ : public DTrashManager {}; +Q_GLOBAL_STATIC(DTrashManager_, globalTrashManager) + +static QString getNotExistsFileName(const QString &fileName, const QString &targetPath) +{ + QByteArray name = fileName.toUtf8(); + + int index = name.lastIndexOf('.'); + QByteArray suffix; + + if (index >= 0) { + suffix = name.mid(index); + } + + if (suffix.size() > 200) { + suffix = suffix.left(200); + } + + name.chop(suffix.size()); + name = name.left(200 - suffix.size()); + + while (QFile::exists(targetPath + "/" + name + suffix)) { + name = QCryptographicHash::hash(name, QCryptographicHash::Md5).toHex(); + } + + return QString::fromUtf8(name + suffix); +} + +static bool writeTrashInfo(const QString &fileBaseName, const QString &sourceFilePath, const QDateTime &datetime, QString *errorString = NULL) +{ + QFile metadata(TRASH_INFO_PATH"/" + fileBaseName + ".trashinfo"); + + if (metadata.exists()) { + if (errorString) { + *errorString = QString("The %1 file is exists").arg(metadata.fileName()); + } + + return false; + } + + if (!metadata.open(QIODevice::WriteOnly)) { + if (errorString) { + *errorString = metadata.errorString(); + } + + return false; + } + + QByteArray data; + + data.append("[Trash Info]\n"); + data.append("Path=").append(sourceFilePath.toUtf8().toPercentEncoding("/")).append("\n"); + data.append("DeletionDate=").append(datetime.toString(Qt::ISODate)).append("\n"); + + qint64 size = metadata.write(data); + metadata.close(); + + if (size <= 0) { + if (errorString) { + *errorString = metadata.errorString(); + } + + return false; + } + + return true; +} + +static bool renameFile(const QFileInfo &fileInfo, const QString &target, QString *errorString = NULL) +{ + if (fileInfo.isFile() || fileInfo.isSymLink()) { + QFile file(fileInfo.filePath()); + + if (!file.rename(target)) { + if (errorString) { + *errorString = file.errorString(); + } + + return false; + } + + return true; + } else { + QDirIterator iterator(fileInfo.filePath(), + QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); + + while (iterator.hasNext()) { + iterator.next(); + + const QString newFile = iterator.filePath().replace(0, fileInfo.filePath().length(), target); + + if (!QDir().mkpath(QFileInfo(newFile).path())) { + if (errorString) { + *errorString = QString("Make the %1 path is failed").arg(QFileInfo(newFile).path()); + } + + return false; + } + + if (!renameFile(iterator.fileInfo(), newFile, errorString)) { + return false; + } + } + + if (!QDir().rmdir(fileInfo.filePath())) { + if (errorString) { + *errorString = QString("Cannot remove the %1 dir").arg(fileInfo.filePath()); + } + + return false; + } + } + + return true; +} + +class DTrashManagerPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DTrashManagerPrivate(DTrashManager *q_ptr) + : DObjectPrivate(q_ptr) {} + + static bool removeFileOrDir(const QString &path); + static bool removeFromIterator(QDirIterator &iter); + + D_DECLARE_PUBLIC(DTrashManager) +}; + +DTrashManager *DTrashManager::instance() +{ + return globalTrashManager; +} + +bool DTrashManager::trashIsEmpty() const +{ + QDirIterator iterator(TRASH_INFO_PATH, +// QStringList() << "*.trashinfo", + QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden); + + return !iterator.hasNext(); +} + +bool DTrashManager::cleanTrash() +{ + QDirIterator iterator_info(TRASH_INFO_PATH, + QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden); + + QDirIterator iterator_files(TRASH_FILES_PATH, + QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, + QDirIterator::Subdirectories); + + return DTrashManagerPrivate::removeFromIterator(iterator_info) && + DTrashManagerPrivate::removeFromIterator(iterator_files); +} + +bool DTrashManager::moveToTrash(const QString &filePath, bool followSymlink) +{ + QFileInfo fileInfo(filePath); + + if (!fileInfo.exists() && (followSymlink || !fileInfo.isSymLink())) { + return false; + } + + QDir trashDir(TRASH_FILES_PATH); + QStorageInfo storageInfo(fileInfo.filePath()); + QStorageInfo trashStorageInfo(trashDir); + + if (storageInfo != trashStorageInfo) { + return false; + } + + if (!trashDir.mkpath(TRASH_INFO_PATH)) { + return false; + } + + if (!trashDir.mkpath(TRASH_FILES_PATH)) { + return false; + } + + if (followSymlink && fileInfo.isSymLink()) { + fileInfo.setFile(fileInfo.symLinkTarget()); + } + + const QString &fileName = getNotExistsFileName(fileInfo.fileName(), TRASH_FILES_PATH); + + if (!writeTrashInfo(fileName, fileInfo.filePath(), QDateTime::currentDateTime())) { + return false; + } + + const QString &newFilePath = TRASH_FILES_PATH"/" + fileName; + + return renameFile(fileInfo, newFilePath); +} + +DTrashManager::DTrashManager() + : QObject() + , DObject(*new DTrashManagerPrivate(this)) +{ + +} + +bool DTrashManagerPrivate::removeFileOrDir(const QString &path) +{ + QFileInfo fileInfo(path); + if (fileInfo.isDir() && !fileInfo.isSymLink()) { + QDir dir(path); + return dir.removeRecursively(); + } else { + return QFile::remove(path); + } +} + +bool DTrashManagerPrivate::removeFromIterator(QDirIterator &iter) +{ + bool ok = true; + while (iter.hasNext()) { + QString nextPath = iter.next(); +// qDebug() << iter.fileName() << iterator_info.filePath(); + if (!DTrashManagerPrivate::removeFileOrDir(nextPath)) { + ok = false; + } + } + return ok; +} + +DCORE_END_NAMESPACE diff --git a/src/filesystem/filesystem.pri b/src/filesystem/filesystem.pri new file mode 100644 index 0000000..d97756d --- /dev/null +++ b/src/filesystem/filesystem.pri @@ -0,0 +1,43 @@ +include($$PWD/private/private.pri) + +INCLUDEPATH += $$PWD/../base + +HEADERS += \ + $$PWD/dbasefilewatcher.h \ + $$PWD/dfilesystemwatcher.h \ + $$PWD/dfilewatcher.h \ + $$PWD/dfilewatchermanager.h \ + $$PWD/dpathbuf.h \ + $$PWD/dstandardpaths.h \ + $$PWD/dtrashmanager.h + +SOURCES += \ + $$PWD/dbasefilewatcher.cpp \ + $$PWD/dfilewatcher.cpp \ + $$PWD/dfilewatchermanager.cpp \ + $$PWD/dstandardpaths.cpp \ + $$PWD/dpathbuf.cpp + +linux { + SOURCES += \ + $$PWD/dfilesystemwatcher_linux.cpp \ + $$PWD/dtrashmanager_linux.cpp +} else:win* { + SOURCES += \ + $$PWD/dfilesystemwatcher_win.cpp \ + $$PWD/dtrashmanager_dummy.cpp +} else { + SOURCES += \ + $$PWD/dfilesystemwatcher_dummy.cpp \ + $$PWD/dtrashmanager_dummy.cpp +} + +includes.files += $$PWD/*.h +includes.files += \ + $$PWD/DFileWatcher \ + $$PWD/DBaseFileWatcher \ + $$PWD/DFileSystemWatcher \ + $$PWD/DFileWatcherManager \ + $$PWD/DPathBuf \ + $$PWD/DStandardPaths \ + $$PWD/DTrashManager diff --git a/src/filesystem/private/dbasefilewatcher_p.h b/src/filesystem/private/dbasefilewatcher_p.h new file mode 100644 index 0000000..f200e94 --- /dev/null +++ b/src/filesystem/private/dbasefilewatcher_p.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DBASEFILEWATCHER_P_H +#define DBASEFILEWATCHER_P_H + +#include "base/private/dobject_p.h" + +#include + +DCORE_BEGIN_NAMESPACE + +class DBaseFileWatcher; +class DBaseFileWatcherPrivate : public DObjectPrivate +{ +public: + DBaseFileWatcherPrivate(DBaseFileWatcher *qq); + + virtual bool start() = 0; + virtual bool stop() = 0; + + QUrl url; + bool started = false; + static QList watcherList; + + D_DECLARE_PUBLIC(DBaseFileWatcher) +}; + +DCORE_END_NAMESPACE + +#endif // DBASEFILEWATCHER_P_H diff --git a/src/filesystem/private/dfilesystemwatcher_dummy_p.h b/src/filesystem/private/dfilesystemwatcher_dummy_p.h new file mode 100644 index 0000000..ed97dd6 --- /dev/null +++ b/src/filesystem/private/dfilesystemwatcher_dummy_p.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILESYSTEMWATCHER_WIN_P_H +#define DFILESYSTEMWATCHER_WIN_P_H + +#include "base/private/dobject_p.h" + +DCORE_BEGIN_NAMESPACE + +class DFileSystemWatcher; +class DFileSystemWatcherPrivate : public DObjectPrivate +{ + Q_DECLARE_PUBLIC(DFileSystemWatcher) + +public: + DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq); + ~DFileSystemWatcherPrivate(); + + // private slots + void _q_readFromInotify(); +}; + +void DFileSystemWatcherPrivate::_q_readFromInotify() +{ + +} + +DCORE_END_NAMESPACE + +#endif // DFILESYSTEMWATCHER_WIN_P_H diff --git a/src/filesystem/private/dfilesystemwatcher_linux_p.h b/src/filesystem/private/dfilesystemwatcher_linux_p.h new file mode 100644 index 0000000..103c307 --- /dev/null +++ b/src/filesystem/private/dfilesystemwatcher_linux_p.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILESYSTEMWATCHER_P_H +#define DFILESYSTEMWATCHER_P_H + +#include "base/private/dobject_p.h" + +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DFileSystemWatcher; +class DFileSystemWatcherPrivate : public DObjectPrivate +{ + Q_DECLARE_PUBLIC(DFileSystemWatcher) + +public: + DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq); + ~DFileSystemWatcherPrivate(); + + QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); + QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); + + QStringList files, directories; + int inotifyFd; + QHash pathToID; + QMultiHash idToPath; + QSocketNotifier notifier; + + // private slots + void _q_readFromInotify(); + +private: + void onFileChanged(const QString &path, bool removed); + void onDirectoryChanged(const QString &path, bool removed); +}; + +DCORE_END_NAMESPACE + +#endif // DFILESYSTEMWATCHER_P_H diff --git a/src/filesystem/private/dfilesystemwatcher_win_p.h b/src/filesystem/private/dfilesystemwatcher_win_p.h new file mode 100644 index 0000000..ed97dd6 --- /dev/null +++ b/src/filesystem/private/dfilesystemwatcher_win_p.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef DFILESYSTEMWATCHER_WIN_P_H +#define DFILESYSTEMWATCHER_WIN_P_H + +#include "base/private/dobject_p.h" + +DCORE_BEGIN_NAMESPACE + +class DFileSystemWatcher; +class DFileSystemWatcherPrivate : public DObjectPrivate +{ + Q_DECLARE_PUBLIC(DFileSystemWatcher) + +public: + DFileSystemWatcherPrivate(int fd, DFileSystemWatcher *qq); + ~DFileSystemWatcherPrivate(); + + // private slots + void _q_readFromInotify(); +}; + +void DFileSystemWatcherPrivate::_q_readFromInotify() +{ + +} + +DCORE_END_NAMESPACE + +#endif // DFILESYSTEMWATCHER_WIN_P_H diff --git a/src/filesystem/private/private.pri b/src/filesystem/private/private.pri new file mode 100644 index 0000000..b31875f --- /dev/null +++ b/src/filesystem/private/private.pri @@ -0,0 +1,10 @@ +HEADERS += \ + $$PWD/dbasefilewatcher_p.h + +linux { + HEADERS += \ + $$PWD/dfilesystemwatcher_linux_p.h +} else:win* { + HEADERS += \ + $$PWD/dfilesystemwatcher_win_p.h +} diff --git a/src/log/AbstractAppender.cpp b/src/log/AbstractAppender.cpp new file mode 100644 index 0000000..2d01cf7 --- /dev/null +++ b/src/log/AbstractAppender.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + + // Local +#include "AbstractAppender.h" + +// Qt +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \class AbstractAppender + * + * \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() + */ + + +//! Constructs a AbstractAppender object. +AbstractAppender::AbstractAppender() + : m_detailsLevel(Logger::Debug) +{} + + +//! Destructs the AbstractAppender object. +AbstractAppender::~AbstractAppender() +{} + + +//! 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. + * + * \sa setDetailsLevel() + * \sa Logger::LogLevel + */ +Logger::LogLevel AbstractAppender::detailsLevel() const +{ + QMutexLocker locker(&m_detailsLevelMutex); + return m_detailsLevel; +} + + +//! Sets the current details level of appender. +/** + * Default details level is Logger::Debug + * + * \note This function is thread safe. + * + * \sa detailsLevel() + * \sa Logger::LogLevel + */ +void AbstractAppender::setDetailsLevel(Logger::LogLevel level) +{ + QMutexLocker locker(&m_detailsLevelMutex); + m_detailsLevel = level; +} + + + +//! Sets the current details 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)); +} + + +//! Tries to write the log record to this logger +/** + * This is the function called by Logger object to write a log message to the appender. + * + * \note This function is thread safe. + * + * \sa Logger::write() + * \sa detailsLevel() + */ +void AbstractAppender::write(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message) +{ + if (logLevel >= detailsLevel()) + { + QMutexLocker locker(&m_writeMutex); + append(timeStamp, logLevel, file, line, function, category, message); + } +} + + +/** + * \fn virtual void AbstractAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, + * int line, const char* function, const QString& message) + * + * \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. + * + * \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/AbstractAppender.h b/src/log/AbstractAppender.h new file mode 100644 index 0000000..91e9479 --- /dev/null +++ b/src/log/AbstractAppender.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +#ifndef ABSTRACTAPPENDER_H +#define ABSTRACTAPPENDER_H + +// Local +#include "CuteLogger_global.h" +#include + +// Qt +#include + +DCORE_BEGIN_NAMESPACE + +class CUTELOGGERSHARED_EXPORT AbstractAppender +{ +public: + AbstractAppender(); + virtual ~AbstractAppender(); + + Logger::LogLevel detailsLevel() const; + void setDetailsLevel(Logger::LogLevel level); + void setDetailsLevel(const QString &level); + + void write(const QDateTime &timeStamp, Logger::LogLevel logLevel, const char *file, int line, const char *function, + const QString &category, const QString &message); + +protected: + virtual void append(const QDateTime &timeStamp, Logger::LogLevel logLevel, const char *file, int line, + const char *function, const QString &category, const QString &message) = 0; + +private: + QMutex m_writeMutex; + + Logger::LogLevel m_detailsLevel; + mutable QMutex m_detailsLevelMutex; +}; + +DCORE_END_NAMESPACE + +#endif // ABSTRACTAPPENDER_H diff --git a/src/log/AbstractStringAppender.cpp b/src/log/AbstractStringAppender.cpp new file mode 100644 index 0000000..ef6ee8f --- /dev/null +++ b/src/log/AbstractStringAppender.cpp @@ -0,0 +1,462 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) Nikolay Matyunin (matyunin.n at gmail dot com) + + Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +// Local +#include "AbstractStringAppender.h" + +// Qt +#include +#include +#include +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \class AbstractStringAppender + * + * \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 = '%'; + + +//! Constructs a new string appender object +AbstractStringAppender::AbstractStringAppender() + : m_format(QLatin1String("%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n")) +{} + + +//! 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; +} + + +//! 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 \c QString::arg() \c fieldWidth argument (and uses it + * internally). For example, \c "%{type:-7}" will be replaced with the left padded debug level of the message + * (\c "Debug ") or something. For the more detailed description of it you may consider to look to the Qt + * Reference Documentation. + * + * Supported marker commands are: + * \arg \c %{time} - timestamp. You may specify your custom timestamp format using the second {} brackets after the marker, + * timestamp format here will be similar to those used in QDateTime::toString() function. For example, + * "%{time}{dd-MM-yyyy, HH:mm}" may be replaced with "17-12-2010, 20:17" depending on current date and time. + * The default format used here is "HH:mm:ss.zzz". + * \arg \c %{type} - Log level. Possible log levels are shown in the Logger::LogLevel enumerator. + * \arg \c %{Type} - Uppercased log level. + * \arg \c %{typeOne} - One letter log level. + * \arg \c %{TypeOne} - One uppercase letter log level. + * \arg \c %{File} - Full source file name (with path) of the file that requested log recording. Uses the \c __FILE__ + * preprocessor macro. + * \arg \c %{file} - Short file name (with stripped path). + * \arg \c %{line} - Line number in the source file. Uses the \c __LINE__ preprocessor macro. + * \arg \c %{Function} - Name of function that called on of the LOG_* macros. Uses the \c Q_FUNC_INFO macro provided with + * Qt. + * \arg \c %{function} - Similar to the %{Function}, but the function name is stripped using stripFunctionName + * \arg \c %{message} - The log message sent by the caller. + * \arg \c %{category} - The log category. + * \arg \c %{appname} - Application name (returned by QCoreApplication::applicationName() function). + * \arg \c %{pid} - Application pid (returned by QCoreApplication::applicationPid() function). + * \arg \c %{threadid} - ID of current thread. + * \arg \c %% - Convinient marker that is replaced with the single \c % mark. + * + * \note Format doesn't add \c '\\n' to the end of the 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; +} + + +//! 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. + * \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; +} + + +//! Returns the string to record to the logging target, formatted according to the format(). +/** + * \sa format() + * \sa setFormat(const QString&) + */ +QString AbstractStringAppender::formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, + int line, const char* function, const QString& category, const QString& message) 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 = timeStamp.toString(f.mid(i + 2, j)); + + i += j; + i += 2; + } + } + + if (chunk.isNull()) + chunk = timeStamp.toString(QLatin1String("HH:mm:ss.zzz")); + } + + // Log level + else if (command == QLatin1String("type")) + chunk = Logger::levelToString(logLevel); + + // Uppercased log level + else if (command == QLatin1String("Type")) + chunk = Logger::levelToString(logLevel).toUpper(); + + // One letter log level + else if (command == QLatin1String("typeOne")) + chunk = Logger::levelToString(logLevel).left(1).toLower(); + + // One uppercase letter log level + else if (command == QLatin1String("TypeOne")) + chunk = Logger::levelToString(logLevel).left(1).toUpper(); + + // Filename + else if (command == QLatin1String("File")) + chunk = QLatin1String(file); + + // Filename without a path + else if (command == QLatin1String("file")) + chunk = QString(QLatin1String(file)).section('/', -1); + + // Source line number + else if (command == QLatin1String("line")) + chunk = QString::number(line); + + // Function name, as returned by Q_FUNC_INFO + else if (command == QLatin1String("Function")) + chunk = QString::fromLatin1(function); + + // Stripped function name + else if (command == QLatin1String("function")) + chunk = stripFunctionName(function); + + // Log message + else if (command == QLatin1String("message")) + chunk = message; + + else if (command == QLatin1String("category")) + chunk = category; + + // Application pid + else if (command == QLatin1String("pid")) + chunk = QString::number(QCoreApplication::applicationPid()); + + // Application name + else if (command == QLatin1String("appname")) + chunk = QCoreApplication::applicationName(); + + // Thread ID (duplicates Qt5 threadid debbuging way) + else if (command == QLatin1String("threadid")) + chunk = QLatin1String("0x") + QString::number(qlonglong(QThread::currentThread()->currentThread()), 16); + + // We simply replace the double formatting marker (%) with one + else if (command == QString(formattingMarker)) + chunk = QLatin1Char(formattingMarker); + + // Do not process any unknown commands + else + { + chunk = QString(formattingMarker); + chunk.append(command); + } + + result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth)); + } + + ++i; + } + + return result; +} + +DCORE_END_NAMESPACE diff --git a/src/log/AbstractStringAppender.h b/src/log/AbstractStringAppender.h new file mode 100644 index 0000000..b79f194 --- /dev/null +++ b/src/log/AbstractStringAppender.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +#ifndef ABSTRACTSTRINGAPPENDER_H +#define ABSTRACTSTRINGAPPENDER_H + +// Local +#include "CuteLogger_global.h" +#include + +// Qt +#include + +DCORE_BEGIN_NAMESPACE + +class CUTELOGGERSHARED_EXPORT AbstractStringAppender : public AbstractAppender +{ + public: + AbstractStringAppender(); + + virtual QString format() const; + void setFormat(const QString&); + + static QString stripFunctionName(const char*); + + protected: + QString formattedString(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message) const; + + private: + static QByteArray qCleanupFuncinfo(const char*); + + QString m_format; + mutable QReadWriteLock m_formatLock; +}; + +DCORE_END_NAMESPACE + +#endif // ABSTRACTSTRINGAPPENDER_H diff --git a/src/log/ConsoleAppender.cpp b/src/log/ConsoleAppender.cpp new file mode 100644 index 0000000..417e888 --- /dev/null +++ b/src/log/ConsoleAppender.cpp @@ -0,0 +1,67 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +// Local +#include "ConsoleAppender.h" + +// STL +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \class ConsoleAppender + * + * \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 timestamp. + * + * 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; +} + + +//! Writes the log record to the std::cerr stream. +/** + * \sa AbstractStringAppender::format() + */ +void ConsoleAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message) +{ + std::cerr << qPrintable(formattedString(timeStamp, logLevel, file, line, function, category, message)); +} + +DCORE_END_NAMESPACE diff --git a/src/log/ConsoleAppender.h b/src/log/ConsoleAppender.h new file mode 100644 index 0000000..26fe8e5 --- /dev/null +++ b/src/log/ConsoleAppender.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +#ifndef CONSOLEAPPENDER_H +#define CONSOLEAPPENDER_H + +#include "CuteLogger_global.h" +#include + +DCORE_BEGIN_NAMESPACE + +class CUTELOGGERSHARED_EXPORT ConsoleAppender : public AbstractStringAppender +{ + public: + ConsoleAppender(); + virtual QString format() const; + void ignoreEnvironmentPattern(bool ignore); + + protected: + virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message); + + private: + bool m_ignoreEnvPattern; +}; + +DCORE_END_NAMESPACE + +#endif // CONSOLEAPPENDER_H diff --git a/src/log/CuteLogger_global.h b/src/log/CuteLogger_global.h new file mode 100644 index 0000000..aefc915 --- /dev/null +++ b/src/log/CuteLogger_global.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef CUTELOGGER_GLOBAL_H +#define CUTELOGGER_GLOBAL_H + +#include "dtkcore_global.h" + +#if defined(CUTELOGGER_LIBRARY) +# define CUTELOGGERSHARED_EXPORT Q_DECL_EXPORT +#else +#if defined(Q_OS_WIN32) +# define CUTELOGGERSHARED_EXPORT +#else +# define CUTELOGGERSHARED_EXPORT Q_DECL_IMPORT +#endif +#endif + +#endif // CUTELOGGER_GLOBAL_H diff --git a/src/log/DLog b/src/log/DLog new file mode 100644 index 0000000..774c2fc --- /dev/null +++ b/src/log/DLog @@ -0,0 +1,8 @@ +#include "CuteLogger_global.h" +#include "RollingFileAppender.h" +#include "Logger.h" +#include "LogManager.h" +#include "FileAppender.h" +#include "ConsoleAppender.h" +#include "AbstractStringAppender.h" +#include "AbstractAppender.h" diff --git a/src/log/FileAppender.cpp b/src/log/FileAppender.cpp new file mode 100644 index 0000000..b26273d --- /dev/null +++ b/src/log/FileAppender.cpp @@ -0,0 +1,112 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +// Local +#include "FileAppender.h" + +// STL +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \class FileAppender + * + * \brief Simple appender that writes the log records to the plain text file. + */ + + +//! Constructs the new file appender assigned to file with the given name. +FileAppender::FileAppender(const QString& fileName) +{ + setFileName(fileName); +} + + +FileAppender::~FileAppender() +{ + closeFile(); +} + + +//! 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(); +} + + +//! Sets the 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; +} + + +//! Write the log record to the file. +/** + * \sa fileName() + * \sa AbstractStringAppender::format() + */ +void FileAppender::append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message) +{ + QMutexLocker locker(&m_logFileMutex); + + if (openFile()) + { + m_logStream << formattedString(timeStamp, logLevel, file, line, function, category, message); + m_logStream.flush(); + m_logFile.flush(); + } +} + + +void FileAppender::closeFile() +{ + QMutexLocker locker(&m_logFileMutex); + m_logFile.close(); +} + +DCORE_END_NAMESPACE diff --git a/src/log/FileAppender.h b/src/log/FileAppender.h new file mode 100644 index 0000000..c122580 --- /dev/null +++ b/src/log/FileAppender.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2010 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +#ifndef FILEAPPENDER_H +#define FILEAPPENDER_H + +// Logger +#include "CuteLogger_global.h" +#include + +// Qt +#include +#include + +DCORE_BEGIN_NAMESPACE + +class CUTELOGGERSHARED_EXPORT FileAppender : public AbstractStringAppender +{ + public: + FileAppender(const QString& fileName = QString()); + ~FileAppender(); + + QString fileName() const; + void setFileName(const QString&); + + qint64 size() const; + + protected: + virtual void append(const QDateTime& timeStamp, Logger::LogLevel logLevel, const char* file, int line, + const char* function, const QString& category, const QString& message); + bool openFile(); + void closeFile(); + + private: + QFile m_logFile; + QTextStream m_logStream; + mutable QMutex m_logFileMutex; +}; + +DCORE_END_NAMESPACE + +#endif // FILEAPPENDER_H diff --git a/src/log/LICENSE b/src/log/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/src/log/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/src/log/LogManager.cpp b/src/log/LogManager.cpp new file mode 100644 index 0000000..5f8781c --- /dev/null +++ b/src/log/LogManager.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "LogManager.h" +#include +#include +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \class DLogManager + * + * \brief DLogManager is the deepin user application log manager + */ + +DLogManager::DLogManager() +{ + QString cachePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).at(0); + if (!QDir(cachePath).exists()){ + QDir(cachePath).mkpath(cachePath); + } + m_logPath = joinPath(cachePath, QString("%1.log").arg(qApp->applicationName())); + m_format = "%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [%{file:-20} %{function:-35} %{line}] %{message}\n"; +} + +void DLogManager::initConsoleAppender(){ + m_consoleAppender = new ConsoleAppender; + m_consoleAppender->setFormat(m_format); + logger->registerAppender(m_consoleAppender); +} + +void DLogManager::initRollingFileAppender(){ + m_rollingFileAppender = new RollingFileAppender(m_logPath); + m_rollingFileAppender->setFormat(m_format); + m_rollingFileAppender->setLogFilesLimit(5); + m_rollingFileAppender->setDatePattern(RollingFileAppender::DailyRollover); + logger->registerAppender(m_rollingFileAppender); +} + +//! Registers the appender to write the log records to the Console +/** + * \sa registerFileAppender + */ +void DLogManager::registerConsoleAppender(){ + DLogManager::instance()->initConsoleAppender(); +} + +//! Registers the appender to write the log records to the file +/** + * \sa getlogFilePath + * \sa registerConsoleAppender + */ +void DLogManager::registerFileAppender() { + DLogManager::instance()->initRollingFileAppender(); +} + +//! Return the path file log storage +/** + * \sa registerFileAppender + */ +QString DLogManager::getlogFilePath(){ + return QDir::toNativeSeparators(DLogManager::instance()->m_logPath); +} + +void DLogManager::setlogFilePath(const QString &logFilePath) +{ + DLogManager::instance()->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; +} + +QString DLogManager::joinPath(const QString &path, const QString &fileName){ + QString separator(QDir::separator()); + return QString("%1%2%3").arg(path, separator, fileName); +} + +DLogManager::~DLogManager() +{ + +} + +DCORE_END_NAMESPACE diff --git a/src/log/LogManager.h b/src/log/LogManager.h new file mode 100644 index 0000000..5f54903 --- /dev/null +++ b/src/log/LogManager.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef LOGMANAGER_H +#define LOGMANAGER_H + +#include + +#include "CuteLogger_global.h" + +DCORE_BEGIN_NAMESPACE + +class ConsoleAppender; +class RollingFileAppender; + +class LIBDTKCORESHARED_EXPORT DLogManager +{ +public: + static void registerConsoleAppender(); + static void registerFileAppender(); + + static QString getlogFilePath(); + + /*! + * \brief setlogFilePath will change log file path of registerFileAppender + * \param logFilePath is the full path of file appender log + */ + static void setlogFilePath(const QString& logFilePath); + + static void setLogFormat(const QString& format); + +private: + QString m_format; + QString m_logPath; + ConsoleAppender* m_consoleAppender; + RollingFileAppender* m_rollingFileAppender; + + void initConsoleAppender(); + void initRollingFileAppender(); + QString joinPath(const QString& path, const QString& fileName); + + inline static DLogManager* instance(){ + static DLogManager instance; + return &instance; + } + explicit DLogManager(); + ~DLogManager(); + DLogManager(const DLogManager &); + DLogManager & operator = (const DLogManager &); +}; + +DCORE_END_NAMESPACE + +#endif // LOGMANAGER_H diff --git a/src/log/Logger.cpp b/src/log/Logger.cpp new file mode 100644 index 0000000..df5c359 --- /dev/null +++ b/src/log/Logger.cpp @@ -0,0 +1,1060 @@ +/* + Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation and appearing in the file + LICENSE.LGPL included in the packaging of this file. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. +*/ +// Local +#include "Logger.h" +#include "AbstractAppender.h" +#include "AbstractStringAppender.h" + +// Qt +#include +#include +#include +#include +#include +#include + +#if defined(Q_OS_ANDROID) +# include +# include +#endif + +// STL +#include + +DCORE_BEGIN_NAMESPACE + +/** + * \file Logger.h + * \brief A file containing the description of Logger class and and additional useful macros for logging + */ + +/** + * \def 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::Logger::globalInstance() + */ + + +/** + * \def 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::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def 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 dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def 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 dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def 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 dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def 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 dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def 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 dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::write() + */ + + +/** + * \def dCTrace(category) + * + * \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). + * + * \param category category name string + * + * \sa dTrace() + * \sa Dtk::Logger::LogLevel + * \sa Dtk::Logger::registerCategoryAppender() + * \sa Dtk::Logger::write() + * \sa dCategory(), dGlobalCategory() + */ + + +/** + * \def 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 dCTrace() + */ + + +/** + * \def 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 dCTrace() + */ + + +/** + * \def 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 dCTrace() + */ + + +/** + * \def 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 dCTrace() + */ + + +/** + * \def 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 dCTrace() + */ + + +/** + * \def dCategory(category) + * + * \brief Create logger instance inside your custom class to log all messages to the specified category + * + * This macro is used to pass all log messages inside your custom class to the specific 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::Logger::write() + * \sa dTrace + * \sa Dtk::Logger::registerCategoryAppender() + * \sa Dtk::Logger::setDefaultCategory() + * \sa dGlobalCategory + */ + + +/** + * \def dGlobalCategory(category) + * + * \brief Create logger instance inside your custom class to log all messages both to the specified 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 category logger using dCategory macro and calling: + * \code logger->logToGlobalInstance(logger->defaultCategory(), true); \endcode + * + * \sa dCategory + * \sa Dtk::Logger::logToGlobalInstance() + * \sa Dtk::Logger::defaultCategory() + * \sa Dtk::Logger::registerCategoryAppender() + * \sa Dtk::Logger::write() + */ + + + +/** + * \def 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::Logger::writeAssert() + */ + + +/** + * \def 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