pax_global_header00006660000000000000000000000064152261541300014511gustar00rootroot0000000000000052 comment=ce6537ef4af41fe7457666b91ef29b7c94d962fe dtkgui-6.7.46/000077500000000000000000000000001522615413000131045ustar00rootroot00000000000000dtkgui-6.7.46/.github/000077500000000000000000000000001522615413000144445ustar00rootroot00000000000000dtkgui-6.7.46/.github/ISSUE_TEMPLATE/000077500000000000000000000000001522615413000166275ustar00rootroot00000000000000dtkgui-6.7.46/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000023651522615413000206250ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: BUG Report | 缺陷报告 url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=bug-report.yml about: Please create bug reports to the issue board in our dtk repo. - name: docs-update | 文档补充 url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=docs-update.yml about: Please create docs-update to the issue board in our dtk repo. - name: unit-test-report | å�•元测试报告 url: https://github.com/linuxdeepin/dtk/issues/new?assignees=&labels=&template=unit-test-report.yml about: Please create unit-test-report to the issue board in our dtk repo. - name: Feature Request | 特性请求 url: https://github.com/linuxdeepin/developer-center/discussions/new?category=features-request-ideas-%E7%89%B9%E6%80%A7%E8%AF%B7%E6%B1%82-%E5%A4%B4%E8%84%91%E9%A3%8E%E6%9A%B4 about: Please create feature requests to the discussion board in our developer-center repo. - name: General Discussion & Questions | 常规讨论与问答 url: https://github.com/linuxdeepin/developer-center/discussions/categories/q-a-%E9%97%AE%E7%AD%94%E6%9D%BF%E5%9D%97 about: Please use the discussion board in our developer-center repo. dtkgui-6.7.46/.github/workflows/000077500000000000000000000000001522615413000165015ustar00rootroot00000000000000dtkgui-6.7.46/.github/workflows/backup-to-gitlab.yml000066400000000000000000000005371522615413000223560ustar00rootroot00000000000000name: backup to gitlab on: [push] concurrency: group: ${{ github.workflow }} cancel-in-progress: true jobs: backup-to-gitlabwh: uses: linuxdeepin/.github/.github/workflows/backup-to-gitlabwh.yml@master secrets: inherit backup-to-gitee: uses: linuxdeepin/.github/.github/workflows/backup-to-gitee.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-api-check.yml000066400000000000000000000004351522615413000217630ustar00rootroot00000000000000name: apiCheck on: pull_request_target: types: [opened, synchronize, reopened] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: api-check: uses: linuxdeepin/.github/.github/workflows/api-check.yml@master secrets: inheritdtkgui-6.7.46/.github/workflows/call-auto-release.yml000066400000000000000000000025721522615413000225310ustar00rootroot00000000000000name: Auto Release on: workflow_dispatch: inputs: version: description: 'Release version (e.g., 1.0.0)' type: string required: false name: description: 'The name of the person to release the version' type: string required: false email: description: 'The email of the person to release the version' type: string required: false timezone: description: 'The timezone in the debian changelog file' required: false type: string default: 'Asia/Shanghai' workflow_call: inputs: version: description: 'Release version (e.g., 1.0.0)' type: string required: true name: description: 'The name of the person to release the version' type: string required: false email: description: 'The email of the person to release the version' type: string required: false timezone: description: 'The timezone in the debian changelog file' required: false type: string default: 'Asia/Shanghai' jobs: auto_release: uses: linuxdeepin/.github/.github/workflows/auto-release.yml@master secrets: inherit with: version: ${{ inputs.version }} name: ${{ inputs.name }} email: ${{ inputs.email }} timezone: ${{ inputs.timezone }} dtkgui-6.7.46/.github/workflows/call-auto-tag.yml000066400000000000000000000005171522615413000216610ustar00rootroot00000000000000name: auto tag on: pull_request_target: types: [opened, synchronize, closed] paths: - "debian/changelog" concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: auto_tag: uses: linuxdeepin/.github/.github/workflows/auto-tag.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-build-distribution.yml000066400000000000000000000004321522615413000237500ustar00rootroot00000000000000name: Call build-distribution on: push: paths-ignore: - ".github/workflows/**" pull_request_target: paths-ignore: - ".github/workflows/**" jobs: check_job: uses: linuxdeepin/.github/.github/workflows/build-distribution.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-chatOps.yml000066400000000000000000000002421522615413000215340ustar00rootroot00000000000000name: chatOps on: issue_comment: types: [created] jobs: chatopt: uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-clacheck.yml000066400000000000000000000005251522615413000216740ustar00rootroot00000000000000name: Call CLA check on: issue_comment: types: [created] pull_request_target: types: [opened, closed, synchronize] concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: clacheck: uses: linuxdeepin/.github/.github/workflows/cla-check.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-commitlint.yml000066400000000000000000000003641522615413000223170ustar00rootroot00000000000000name: Call commitlint on: pull_request_target: concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: check_job: uses: linuxdeepin/.github/.github/workflows/commitlint.yml@master dtkgui-6.7.46/.github/workflows/call-debian-check.yml000066400000000000000000000004461522615413000224360ustar00rootroot00000000000000name: debianCheck on: pull_request_target: types: [opened, synchronize, reopened] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: debian-check: uses: linuxdeepin/.github/.github/workflows/debian-check.yml@master secrets: inheritdtkgui-6.7.46/.github/workflows/call-deploy-dev-doc.yml000066400000000000000000000007401522615413000227510ustar00rootroot00000000000000name: deploy docs on: push: branches: ["master"] workflow_dispatch: inputs: tag: required: true type: string permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: "pages" cancel-in-progress: true jobs: deploydocs: uses: linuxdeepin/.github/.github/workflows/deploy-dev-doc.yml@master with: ref: ${{ inputs.tag }} secrets: inherit dtkgui-6.7.46/.github/workflows/call-doc-check.yml000066400000000000000000000004671522615413000217640ustar00rootroot00000000000000name: doxygen-check on: pull_request_target: paths-ignore: - ".github/workflows/**" concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: check_job: uses: linuxdeepin/.github/.github/workflows/doc-check.yml@master secrets: inherit dtkgui-6.7.46/.github/workflows/call-license-check.yml000066400000000000000000000005521522615413000226340ustar00rootroot00000000000000name: Call License and README Check on: pull_request_target: types: [opened, synchronize, reopened] permissions: pull-requests: write contents: read concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: license-check: uses: linuxdeepin/.github/.github/workflows/license-check.yml@master dtkgui-6.7.46/.github/workflows/call-static-check.yml000066400000000000000000000004461522615413000225030ustar00rootroot00000000000000name: staticCheck on: pull_request_target: types: [opened, synchronize, reopened] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: static-check: uses: linuxdeepin/.github/.github/workflows/static-check.yml@master secrets: inheritdtkgui-6.7.46/.github/workflows/cppcheck.yml000066400000000000000000000012651522615413000210100ustar00rootroot00000000000000name: cppcheck on: pull_request_target: paths-ignore: - ".github/workflows/**" concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: cppchceck: name: cppcheck runs-on: ubuntu-latest steps: - run: export - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - uses: linuxdeepin/action-cppcheck@main with: github_token: ${{ secrets.GITHUB_TOKEN }} repository: ${{ github.repository }} pull_request_id: ${{ github.event.pull_request.number }} allow_approve: false dtkgui-6.7.46/.github/workflows/dtkgui-archlinux-build.yml000066400000000000000000000055121522615413000236060ustar00rootroot00000000000000name: Build dtkgui on Arch Linux on: push: pull_request: jobs: container: runs-on: ubuntu-latest container: archlinux:latest strategy: matrix: include: - qt_version: 5 dtk5: "ON" - qt_version: 6 dtk5: "OFF" steps: - name: Initialize pacman and system update run: | pacman-key --init pacman --noconfirm --noprogressbar -Syu - name: Install base build tools run: | pacman -S --noconfirm --noprogressbar base-devel git cmake ninja pkgconf - name: Install dtkgui Qt5 system dependencies if: matrix.qt_version == 5 run: | pacman -S --noconfirm --noprogressbar \ qt5-base qt5-tools qt5-wayland qt5-svg qt5-imageformats \ extra-cmake-modules \ gtest \ librsvg libraw \ libqt5xdg \ icu uchardet dbus spdlog gsettings-qt \ dtkcommon dtklog \ treeland-protocols dtkcore - name: Install dtkgui Qt6 system dependencies if: matrix.qt_version == 6 run: | pacman -S --noconfirm --noprogressbar \ qt6-base qt6-tools qt6-wayland qt6-svg qt6-imageformats \ extra-cmake-modules \ gtest \ librsvg libraw \ libqtxdg \ icu uchardet dbus spdlog \ dtkcommon dtk6log \ treeland-protocols dtk6core - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Configure and build dtkgui run: | cmake -B build \ -GNinja \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_BUILD_TYPE=Release \ -DMKSPECS_INSTALL_DIR=lib/qt/mkspecs/modules \ -DBUILD_DOCS=OFF \ -DBUILD_EXAMPLES=OFF \ -DBUILD_TESTING=OFF \ -DDTK5=${{ matrix.dtk5 }} cmake --build build -j$(nproc) echo "✅ dtkgui Qt${{ matrix.qt_version }} built successfully!" - name: Install dtkgui to staging directory run: | DESTDIR=/tmp/dtkgui-install cmake --install build echo "Total: $(find /tmp/dtkgui-install -type f | wc -l) files" - name: Create installation package run: | tar -czf /tmp/dtkgui-archlinux-qt${{ matrix.qt_version }}-$(date +%Y%m%d-%H%M%S).tar.gz -C /tmp/dtkgui-install . ls -la /tmp/dtkgui-archlinux-qt${{ matrix.qt_version }}-*.tar.gz - name: Upload dtkgui Arch Linux build artifacts if: ${{ !env.ACT }} uses: actions/upload-artifact@v4 with: name: dtkgui-archlinux-qt${{ matrix.qt_version }}-build path: "/tmp/dtkgui-archlinux-qt${{ matrix.qt_version }}-*.tar.gz" if-no-files-found: error retention-days: 30 dtkgui-6.7.46/.github/workflows/dtkgui-deepin-build.yml000066400000000000000000000074331522615413000230610ustar00rootroot00000000000000name: Build dtkgui on Deepin crimson on: push: pull_request: jobs: container: runs-on: ubuntu-latest container: linuxdeepin/deepin:crimson strategy: matrix: include: - qt_version: 5 dtk_profile: nodtk6 - qt_version: 6 dtk_profile: nodtk5 steps: - uses: actions/checkout@v4 - name: Setup apt sources and build tools run: | set -euxo pipefail echo "deb [trusted=yes] http://mirrors.kernel.org/deepin/beige/ crimson main commercial community" > /etc/apt/sources.list echo "deb-src [trusted=yes] http://mirrors.kernel.org/deepin/beige/ crimson main commercial community" >> /etc/apt/sources.list rm -rf /etc/apt/sources.list.d apt-get update apt-get install -y devscripts equivs git - name: Build and install dtkcommon from source run: | set -euxo pipefail cd /tmp git clone --depth=1 https://github.com/linuxdeepin/dtkcommon.git cd dtkcommon mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control dpkg-buildpackage -uc -us -b dpkg -i ../*.deb 2>/dev/null || apt-get install -f -y echo "✅ dtkcommon installed" - name: Build and install dtklog from source run: | set -euxo pipefail cd /tmp git clone --depth=1 https://github.com/linuxdeepin/dtklog.git cd dtklog mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control dpkg-buildpackage -uc -us -b -P${{ matrix.dtk_profile }} dpkg -i ../*.deb 2>/dev/null || apt-get install -f -y echo "✅ dtklog installed" - name: Build and install treeland-protocols from source run: | set -euxo pipefail apt-get install -y --allow-unauthenticated wlr-protocols || true cd /tmp git clone --depth=1 https://github.com/linuxdeepin/treeland-protocols.git cd treeland-protocols mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control dpkg-buildpackage -uc -us -b dpkg -i ../*.deb 2>/dev/null || apt-get install -f -y echo "✅ treeland-protocols installed" - name: Build and install dtkcore from source run: | set -euxo pipefail cd /tmp git clone --depth=1 https://github.com/linuxdeepin/dtkcore.git cd dtkcore mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control dpkg-buildpackage -uc -us -b -P${{ matrix.dtk_profile }} dpkg -i ../*.deb 2>/dev/null || apt-get install -f -y echo "✅ dtkcore installed" - name: Install dtkgui build dependencies run: | set -euxo pipefail mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control - name: Build dtkgui deb packages run: | set -euxo pipefail dpkg-buildpackage -uc -us -b -P${{ matrix.dtk_profile }} echo "✅ dtkgui Qt${{ matrix.qt_version }} deb packages built successfully!" ls -la ../ - name: Collect deb artifacts run: | mkdir -p dist mv ../*.deb dist/ ls -la dist - name: Upload dtkgui deb packages as artifacts uses: actions/upload-artifact@v4 with: name: dtkgui-deepin-deb-packages-qt${{ matrix.qt_version }} path: dist/*.deb if-no-files-found: error retention-days: 30 dtkgui-6.7.46/.gitignore000066400000000000000000000012701522615413000150740ustar00rootroot00000000000000# C++ objects and libs *.slo *.lo *.o *.a *.la *.lai *.so *.dll *.dylib # Qt-es object_script.*.Release object_script.*.Debug *_plugin_import.cpp /.qmake.cache /.qmake.stash *.pro.user *.pro.user.* *.qbs.user *.qbs.user.* *.moc moc_*.cpp moc_*.h qrc_*.cpp ui_*.h *.qmlc *.jsc Makefile* *build-* # Qt unit tests target_wrapper.* # QtCreator *.autosave # QtCreator Qml *.qmlproject.user *.qmlproject.user.* # QtCreator CMake CMakeLists.txt.user* # vscode .vscode # idea .idea #clangformat .clang-format # build compile_commands.json bin DtkGuis dtkgui_config.h qt_lib_dtkgui*.pri build .cache dtkgui.pc DtkGuiConfig.cmake asan.* Testing # Ignore Doxygen theme files docs/doxygen-theme/ dtkgui-6.7.46/.gitlab-ci.yml000066400000000000000000000002271522615413000155410ustar00rootroot00000000000000include: - remote: 'https://gitlab.deepin.io/dev-tools/letmeci/raw/master/gitlab-ci/dde.yml' variables: CPPCHECK: "true" CODESPELL: "true" dtkgui-6.7.46/.obs/000077500000000000000000000000001522615413000137455ustar00rootroot00000000000000dtkgui-6.7.46/.obs/workflows.yml000066400000000000000000000023121522615413000165230ustar00rootroot00000000000000test_build: steps: - link_package: source_project: deepin:Develop:dde source_package: %{SCM_REPOSITORY_NAME} target_project: deepin:CI - configure_repositories: project: deepin:CI repositories: - name: deepin_develop paths: - target_project: deepin:CI target_repository: deepin_develop architectures: - x86_64 - aarch64 - name: debian paths: - target_project: deepin:CI target_repository: debian_sid architectures: - x86_64 - name: archlinux paths: - target_project: deepin:CI target_repository: archlinux architectures: - x86_64 filters: event: pull_request tag_build: steps: - branch_package: source_project: deepin:Develop:dde source_package: %{SCM_REPOSITORY_NAME} target_project: deepin:Unstable:dde filters: event: tag_push commit_build: steps: - trigger_services: project: deepin:Develop:dde package: %{SCM_REPOSITORY_NAME} filters: event: push dtkgui-6.7.46/.packit.yaml000066400000000000000000000007021522615413000153200ustar00rootroot00000000000000# See the documentation for more information: # https://packit.dev/docs/configuration/ specfile_path: rpm/dtkgui.spec # add or remove files that should be synced synced_files: - rpm/dtkgui.spec - .packit.yaml upstream_package_name: dtkgui # downstream (Fedora) RPM package name downstream_package_name: dtkgui actions: fix-spec-file: | bash -c "sed -i -r \"s/Version:(\s*)\S*/Version:\1${PACKIT_PROJECT_VERSION}/\" rpm/dtkgui.spec" dtkgui-6.7.46/.release.json000066400000000000000000000010451522615413000154750ustar00rootroot00000000000000{ "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" } } dtkgui-6.7.46/.reuse/000077500000000000000000000000001522615413000143055ustar00rootroot00000000000000dtkgui-6.7.46/.reuse/dep5000066400000000000000000000026401522615413000150670ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: dtkgui Upstream-Contact: UnionTech Software Technology Co., Ltd. <> Source: https://github.com/linuxdeepin/dtkgui # ci Files: .github/* .gitlab-ci.yml .obs/* Copyright: None License: CC0-1.0 # gitignore Files: .gitignore .syncexclude Copyright: None License: CC0-1.0 # json conf yaml Files: *.json *conf *.yaml Copyright: None License: CC0-1.0 #interface Files: include/DtkGui/D* Copyright: None License: CC0-1.0 # RPM/Arch Packaging Files: archlinux/* rpm/* Copyright: None License: CC0-1.0 # debian Files: debian/* Copyright: None License: LGPL-3.0-or-later # README Files: *README.md *README.zh_CN.md CHANGELOG.md Copyright: None License: CC-BY-4.0 # Documentations Files: docs/* Copyright: 2022-2023 deepin doc doc go SIG License: CC-BY-4.0 # DBus Files: src/dbus/*.xml Copyright: None License: CC0-1.0 # Project file Files: *.pro *.prf *.pri *.qrc *CMakeLists.txt *.cmake *.in VERSION Copyright: None License: CC0-1.0 # images: png svg dci webp Files: src/util/icons/actions/* src/util/icons/icons/* src/util/icons/texts/* src/util/icons/dci/* tests/images/* tests/actions/* tests/dcis/* examples/animation-dci/* Copyright: UnionTech Software Technology Co., Ltd. License: LGPL-3.0-or-later Files: toolGenerate/**/* Copyright: None License: CC0-1.0 Files: src/kernel/orgdeepindtkpreference.hpp Copyright: None License: CC0-1.0 dtkgui-6.7.46/.syncexclude000066400000000000000000000004121522615413000154300ustar00rootroot00000000000000# Paths that will be exclude from synchronize workflow # Please use relative path which use project directory as root # Notice that # * .git # * debian # * archlinux # * .obs # * .github # are always ignored linglong.yaml conanfile.py VERSION CHANGELOG.md dtkgui-6.7.46/CHANGELOG.md000066400000000000000000000173641522615413000147300ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [6.7.46] - 2026-07-16 ### Fixed - Fix decorator loss when setting clipboard windows visible - Prevent theme from being saved incorrectly in some applications ## [6.7.45] - 2026-07-09 ### Added - Add border and shadow support for TreeLand windows - Add window effect support for treeland platform ### Fixed - Align MoveWindowHelper with xcb - Prevent window blur loss on destruction in treeland platform - Prevent pending state failure in window platform interface ## [6.7.44] - 2026-06-17 ### Fixed - Adapt to treeland wallpaper protocol changes ## [6.7.43] - 2026-06-04 ### Added - Add missing DTK core binary packages to build dependencies - Add window radius control for treeland platform - Support system window menu on treeland/wayland - Add GitHub Actions CI workflows for Arch Linux and Deepin builds - Add HasInWindowBlur attribute to DGuiApplicationHelper ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 - Chore: New release 6.7.38 - Enable XdgIconLoader support for Qt6 builds - Chore: New release 6.7.39 - Chore: New release 6.7.40 - Chore: New release 6.7.41 - Forward XDG_ACTIVATION_TOKEN to single-instance server - New release 6.7.42 (#382) - Replace private access hacks with accessor pattern ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path - Use active color as fallback for dark active color in treeland ## [6.7.42] - 2026-05-20 ### Added - Add missing DTK core binary packages to build dependencies - Add window radius control for treeland platform - Support system window menu on treeland/wayland ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 - Chore: New release 6.7.38 - Enable XdgIconLoader support for Qt6 builds - Chore: New release 6.7.39 - Chore: New release 6.7.40 - Chore: New release 6.7.41 - Forward XDG_ACTIVATION_TOKEN to single-instance server ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path - Use active color as fallback for dark active color in treeland ## [6.7.41] - 2026-05-08 ### Added - Add missing DTK core binary packages to build dependencies - Add window radius control for treeland platform ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 - Chore: New release 6.7.38 - Enable XdgIconLoader support for Qt6 builds - Chore: New release 6.7.39 - Chore: New release 6.7.40 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path - Use active color as fallback for dark active color in treeland ## [6.7.40] - 2026-04-23 ### Added - Add missing DTK core binary packages to build dependencies - Add window radius control for treeland platform ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 - Chore: New release 6.7.38 - Enable XdgIconLoader support for Qt6 builds - Chore: New release 6.7.39 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.39] - 2026-04-09 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 - Chore: New release 6.7.38 - Enable XdgIconLoader support for Qt6 builds ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.38] - 2026-03-31 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 - Chore: New release 6.7.37 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.37] - 2026-03-25 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 - Chore: New release 6.7.36 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.36] - 2026-03-12 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 - Chore: New release 6.7.35 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.35] - 2026-03-05 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 - Chore: New release 6.7.34 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 - Use DTK_VERSION_MAJOR for private header install path ## [6.7.34] - 2026-02-27 ### Added - Add missing DTK core binary packages to build dependencies ### Changed - Chore: New release 6.7.33 ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 ## [6.7.33] - 2026-02-05 ### Added - Add missing DTK core binary packages to build dependencies ### Fixed - ä¿®å¤� DForeignWindow event方法返回值的问题 ## [6.7.32] - 2026-01-22 ### Removed - Delete workflow call-synchronize-to-dtk6 - Remove DTK version calculation and makeshlibs override ## [6.7.31] - 2026-01-06 ### Added - Add unified build system for DTK5 and DTK6 ## [5.7.30] - 2025-12-11 ## [5.7.28] - 2025-12-04 ## [5.7.27] - 2025-11-27 ### Added - Add reproducible build configuration ## [5.7.26] - 2025-11-06 ### Changed - Improve icon theme generation with scalable support - Chore: New release 5.7.25 ### Fixed - ä¿®å¤�DTKæ�œç´¢æ¡†å›¾æ ‡é¢œè‰²ä¸�è·Ÿéš�主题å�˜åŒ– - 没有匹é…�最佳尺寸的图标 ## [5.7.25] - 2025-10-30 ### Changed - Improve icon theme generation with scalable support ## [5.7.24] - 2025-10-16 ### Added - Support Qt 6.10 ### Changed - Improve icon size detection and duplicate handling ### Fixed - Correct lockfile path construction - Fix Qt6 compilation error with libxdg ## [5.7.23] - 2025-09-25 ### Fixed - 解决控制中心闪çƒ�问题 - Fix build for Qt 6.9 ## [5.7.22] - 2025-09-04 ### Added - Add T11 font size and adjust T5 default ### Fixed - Improve PID namespace detection in setSingleInstance ## [5.7.21] - 2025-08-14 ### Added - Add flags parameter to DDciIconPlayer play method ### Fixed - Resolve compilation warnings and deprecation issues ## [5.7.20] - 2025-07-31 ### Added - Add pid namespace isolation to setSingleInstance - Add concurrent processing for DCI icon conversion ### Changed - Update REUSE license file for CHANGELOG - Move icon finder functionality to separate tool - Switch to QGuiApplication for SVG rendering ## [5.7.19] - 2025-07-03 ### Fixed - Enhance build security hardening ## [5.7.18] - 2025-06-27 ### Fixed - Make version parameter optional in release workflow ## [5.7.17] - 2025-06-19 ### Added - Add missing header - Fix: add missing prefix for QTranslator::load() ### Changed - Chore: use another QTranslator::load overload to tidy code - Support VERSION file - Add auto release workflow - Update .syncexclude [5.7.17]: https://github.com/linuxdeepin/dtkgui/compare/5.7.16..5.7.17 dtkgui-6.7.46/CMakeLists.txt000066400000000000000000000014601522615413000156450ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.25) file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FILE_VERSION) string(STRIP "${FILE_VERSION}" FILE_VERSION) project(DtkGui VERSION ${FILE_VERSION} DESCRIPTION "DTK Gui module" HOMEPAGE_URL "https://github.com/linuxdeepin/dtkgui" LANGUAGES CXX C ) # 引入 DTK5/DTK6 构建选项 option(DTK5 "Build DTK5." ON) if(DTK5) set(DTK_VERSION_MAJOR "5") set(DTK_NAME_SUFFIX "") # DTK5 产å“�å��ç§°å�Žç¼€ä¸ºç©º else() set(DTK_VERSION_MAJOR "6") set(DTK_NAME_SUFFIX "6") # DTK6 产å“�å��ç§°å�Žç¼€ä¸º "6" endif() set(DTK_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(DTK_VERSION_PATCH ${PROJECT_VERSION_PATCH}) set(DTK_VERSION "${DTK_VERSION_MAJOR}.${DTK_VERSION_MINOR}.${DTK_VERSION_PATCH}") set(QT_VERSION_MAJOR ${DTK_VERSION_MAJOR}) include(dtkgui.cmake) dtkgui-6.7.46/LICENSE000066400000000000000000001221631522615413000141160ustar00rootroot00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. “This Licenseâ€� refers to version 3 of the GNU General Public License. “Copyrightâ€� also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Programâ€� refers to any copyrightable work licensed under this License. Each licensee is addressed as “youâ€�. “Licenseesâ€� and “recipientsâ€� may be individuals or organizations. To “modifyâ€� a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified versionâ€� of the earlier work or a work “based onâ€� the earlier work. A “covered workâ€� means either the unmodified Program or a work based on the Program. To “propagateâ€� a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “conveyâ€� a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Noticesâ€� to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source codeâ€� for a work means the preferred form of the work for making modifications to it. “Object codeâ€� means any non-source form of a work. A “Standard Interfaceâ€� means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Librariesâ€� of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Componentâ€�, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Sourceâ€� for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all noticesâ€�. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregateâ€� if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Productâ€� is either (1) a “consumer productâ€�, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally usedâ€� refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Informationâ€� for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissionsâ€� are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictionsâ€� within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transactionâ€� is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributorâ€� is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor versionâ€�. A contributor's “essential patent claimsâ€� are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “controlâ€� includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent licenseâ€� is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grantâ€� such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relyingâ€� means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatoryâ€� if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later versionâ€� applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS ISâ€� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyrightâ€� line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about boxâ€�. You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimerâ€� for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . dtkgui-6.7.46/LICENSES/000077500000000000000000000000001522615413000143115ustar00rootroot00000000000000dtkgui-6.7.46/LICENSES/CC-BY-4.0.txt000066400000000000000000000411771522615413000161600ustar00rootroot00000000000000Creative Commons Attribution 4.0 International Creative Commons Corporation (“Creative Commonsâ€�) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-isâ€� basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors. Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public. Creative Commons Attribution 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 – Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 – Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: A. reproduce and Share the Licensed Material, in whole or in part; and B. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 5. Downstream recipients. A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 – License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: A. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. Section 4 – Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 – Disclaimer of Warranties and Limitation of Liability. a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 – Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 – Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 – Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.â€� Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commonsâ€� or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. dtkgui-6.7.46/LICENSES/CC0-1.0.txt000066400000000000000000000156101522615413000157160ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. dtkgui-6.7.46/LICENSES/LGPL-3.0-or-later.txt000066400000000000000000001221621522615413000176350ustar00rootroot00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. “This Licenseâ€� refers to version 3 of the GNU General Public License. “Copyrightâ€� also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Programâ€� refers to any copyrightable work licensed under this License. Each licensee is addressed as “youâ€�. “Licenseesâ€� and “recipientsâ€� may be individuals or organizations. To “modifyâ€� a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified versionâ€� of the earlier work or a work “based onâ€� the earlier work. A “covered workâ€� means either the unmodified Program or a work based on the Program. To “propagateâ€� a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “conveyâ€� a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Noticesâ€� to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source codeâ€� for a work means the preferred form of the work for making modifications to it. “Object codeâ€� means any non-source form of a work. A “Standard Interfaceâ€� means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Librariesâ€� of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Componentâ€�, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Sourceâ€� for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all noticesâ€�. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregateâ€� if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Productâ€� is either (1) a “consumer productâ€�, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally usedâ€� refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Informationâ€� for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissionsâ€� are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictionsâ€� within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transactionâ€� is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributorâ€� is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor versionâ€�. A contributor's “essential patent claimsâ€� are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “controlâ€� includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent licenseâ€� is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grantâ€� such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relyingâ€� means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatoryâ€� if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later versionâ€� applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS ISâ€� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyrightâ€� line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about boxâ€�. You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimerâ€� for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . dtkgui-6.7.46/README.md000066400000000000000000000020531522615413000143630ustar00rootroot00000000000000## Deepin Tool Kit Gui Deepin Tool Kit (DtkGui) is the development graphical user interface of all C++/Qt Developer work on Deepin. You should read the Deepin Application Specification firstly. ## Dependencies ### Build dependencies * Qt >= 5.10 ## Installation ### Build from source code 1. Make sure you have installed all dependencies. 2. Build: ```bash mkdir build cd build cmake .. make ``` 3. Install: ```bash sudo make install ``` ## Getting help Any usage issues can ask for help via * [Telegram group](https://t.me/deepin) * [Matrix](https://matrix.to/#/#deepin-community:matrix.org) * [IRC (libera.chat)](https://web.libera.chat/#deepin-community) * [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). ## License deepin-tool-kit is licensed under [LGPL-3.0-or-later](LICENSE). dtkgui-6.7.46/README.zh_CN.md000066400000000000000000000017301522615413000153640ustar00rootroot00000000000000## Deepin Tool Kit Gui Deepin Tool Kit Gui(DtkGui) æ��供开å�‘图形用户界é�¢åº”用程åº�所需的功能. 您应该首先阅读 Deepin应用程åº�规范. ## ä¾�èµ– ### 编译ä¾�èµ– * Qt >= 5.10 ## 安装 ### 从æº�代ç �构建 1. ç¡®ä¿�å·²ç»�安装了所有的编译ä¾�èµ–. 2. 构建: ```bash mkdir build cd build cmake .. make ``` 3. 安装: ```bash sudo make install ``` ## 帮助 任何使用问题都å�¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼�寻求帮助: * [Telegram 群组](https://t.me/deepin) * [Matrix](https://matrix.to/#/#deepin-community:matrix.org) * [IRC (libera.chat)](https://web.libera.chat/#deepin-community) * [Forum](https://bbs.deepin.org) * [WiKi](https://wiki.deepin.org/) ## å�‚与贡献 我们鼓励您报告问题并作出更改 * [å¼€å�‘者代ç �贡献指å�—](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers) ## å��è®® DTK工具包é�µå¾ªå��è®® [LGPL-3.0-or-later](LICENSE). dtkgui-6.7.46/VERSION000066400000000000000000000000071522615413000141510ustar00rootroot000000000000006.7.46 dtkgui-6.7.46/VERSION.in000066400000000000000000000000121522615413000145520ustar00rootroot00000000000000@version@ dtkgui-6.7.46/archlinux/000077500000000000000000000000001522615413000151015ustar00rootroot00000000000000dtkgui-6.7.46/archlinux/PKGBUILD000066400000000000000000000022401522615413000162230ustar00rootroot00000000000000# Maintainer: justforlxz pkgname=dtkgui-git pkgver=6.7.46 pkgrel=1 sourcename=dtkgui sourcetars=("$sourcename"_"$pkgver".tar.xz) sourcedir="$sourcename" pkgdesc='Deepin Toolkit, gui module for DDE look and feel' arch=('x86_64' 'aarch64') url="https://github.com/linuxdeepin/dtkgui" license=('LGPL3') depends=('dtkcore-git' 'dtkcommon-git' 'qt5-svg' 'libqtxdg' 'freeimage' 'librsvg' 'qt5-wayland') # INFO: you can disable freeimage not to support RAW images # Then set DTK_DISABLE_EX_IMAGE_FORMAT=OFF makedepends=('git' 'qt5-tools' 'gtest' 'gmock' 'ninja' 'cmake' 'doxygen' 'extra-cmake-modules') conflicts=('dtkgui') provides=('dtkgui') groups=('deepin-git') source=("${sourcetars[@]}") sha512sums=('SKIP') build() { cd $sourcedir cmake -GNinja \ -DMKSPECS_INSTALL_DIR=lib/qt/mkspecs/modules/ \ -DBUILD_DOCS=ON \ -DQCH_INSTALL_DESTINATION=share/doc/qt \ -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_INSTALL_PREFIX=/usr \ -DDTK5=ON ninja # INFO: Another cmake option is DTK_DISABLE_EX_IMAGE_FORMAT # If you not want to support RAW images, set it to off } package() { cd $sourcedir DESTDIR="$pkgdir" ninja install } dtkgui-6.7.46/cmake/000077500000000000000000000000001522615413000141645ustar00rootroot00000000000000dtkgui-6.7.46/cmake/FindFreeImage.cmake000066400000000000000000000023721522615413000176170ustar00rootroot00000000000000# # Try to find the FreeImage library and include path. # Once done this will define # # FreeImage_FOUND # FreeImage_INCLUDE_PATH # FreeImage_LIBRARY # find_path(FreeImage_INCLUDE_DIR NAMES FreeImage.h PATHS /usr/include /usr/local/include /sw/include /opt/local/include ${CMAKE_INCLUDE_PATH} ${CMAKE_INSTALL_PREFIX}/include) find_library(FreeImage_LIBRARY NAMES FreeImage freeimage PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /sw/lib /opt/local/lib ${CMAKE_LIBRARY_PATH} ${CMAKE_INSTALL_PREFIX}/lib) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FreeImage FOUND_VAR FreeImage_FOUND REQUIRED_VARS FreeImage_LIBRARY FreeImage_INCLUDE_DIR ) if(FreeImage_FOUND) set(FreeImage_LIBRARIES ${FreeImage_LIBRARY}) set(FreeImage_INCLUDE_DIRS ${FreeImage_INCLUDE_DIR}) endif() if(FreeImage_FOUND AND NOT TARGET FreeImage::FreeImage) add_library(FreeImage::FreeImage UNKNOWN IMPORTED) set_target_properties(FreeImage::FreeImage PROPERTIES IMPORTED_LOCATION "${FreeImage_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${FreeImage_INCLUDE_DIR}" ) endif() mark_as_advanced( FreeImage_INCLUDE_DIR FreeImage_LIBRARY ) dtkgui-6.7.46/debian/000077500000000000000000000000001522615413000143265ustar00rootroot00000000000000dtkgui-6.7.46/debian/changelog000066400000000000000000000412461522615413000162070ustar00rootroot00000000000000dtkgui (6.7.46) unstable; urgency=medium * Release 6.7.46 -- yeshanshan Thu, 16 Jul 2026 20:55:24 +0800 dtkgui (6.7.45) unstable; urgency=medium * Release 6.7.45 -- yeshanshan Thu, 09 Jul 2026 20:10:11 +0800 dtkgui (6.7.44) unstable; urgency=medium * Release 6.7.44 -- yeshanshan Wed, 17 Jun 2026 11:14:27 +0800 dtkgui (6.7.43) unstable; urgency=medium * Release 6.7.43 -- yeshanshan Thu, 04 Jun 2026 19:42:48 +0800 dtkgui (6.7.42) unstable; urgency=medium * Release 6.7.42 -- yeshanshan Wed, 20 May 2026 14:28:38 +0800 dtkgui (6.7.41) unstable; urgency=medium * Release 6.7.41 -- yeshanshan Fri, 08 May 2026 13:57:28 +0800 dtkgui (6.7.40) unstable; urgency=medium * Release 6.7.40 -- yeshanshan Thu, 23 Apr 2026 21:36:48 +0800 dtkgui (6.7.39) unstable; urgency=medium * Release 6.7.39 -- mhduiy Thu, 09 Apr 2026 21:22:08 +0800 dtkgui (6.7.38) unstable; urgency=medium * Release 6.7.38 -- yeshanshan Tue, 31 Mar 2026 11:02:27 +0800 dtkgui (6.7.37) unstable; urgency=medium * Release 6.7.37 -- mhduiy Wed, 25 Mar 2026 17:05:08 +0800 dtkgui (6.7.36) unstable; urgency=medium * Release 6.7.36 -- yeshanshan Thu, 12 Mar 2026 20:20:47 +0800 dtkgui (6.7.35) unstable; urgency=medium * Release 6.7.35 -- yeshanshan Thu, 05 Mar 2026 17:53:51 +0800 dtkgui (6.7.34) unstable; urgency=medium * Release 6.7.34 -- mhduiy Fri, 27 Feb 2026 14:58:31 +0800 dtkgui (6.7.33) unstable; urgency=medium * Release 6.7.33 -- yeshanshan Thu, 05 Feb 2026 17:27:16 +0800 dtkgui (6.7.32) unstable; urgency=medium * Release 6.7.32 -- yeshanshan Thu, 22 Jan 2026 16:53:39 +0800 dtkgui (6.7.31) unstable; urgency=medium * Release 6.7.31 -- yeshanshan Tue, 06 Jan 2026 13:16:37 +0800 dtkgui (5.7.30) unstable; urgency=medium * Release 5.7.30 -- yeshanshan Thu, 11 Dec 2025 20:58:09 +0800 dtkgui (5.7.28) unstable; urgency=medium * Release 5.7.28 -- mhduiy Thu, 04 Dec 2025 19:53:02 +0800 dtkgui (5.7.27) unstable; urgency=medium * Release 5.7.27 -- mhduiy Thu, 27 Nov 2025 19:39:39 +0800 dtkgui (5.7.26) unstable; urgency=medium * Release 5.7.26 -- yeshanshan Thu, 06 Nov 2025 17:03:53 +0800 dtkgui (5.7.25) unstable; urgency=medium * Release 5.7.25 -- yeshanshan Thu, 30 Oct 2025 21:47:33 +0800 dtkgui (5.7.24) unstable; urgency=medium * Release 5.7.24 -- yeshanshan Thu, 16 Oct 2025 19:45:30 +0800 dtkgui (5.7.23) unstable; urgency=medium * Release 5.7.23 -- yeshanshan Thu, 25 Sep 2025 16:49:18 +0800 dtkgui (5.7.22) unstable; urgency=medium * Release 5.7.22 -- yeshanshan Thu, 04 Sep 2025 19:27:38 +0800 dtkgui (5.7.21) unstable; urgency=medium * Release 5.7.21 -- yeshanshan Thu, 14 Aug 2025 19:47:40 +0800 dtkgui (5.7.20) unstable; urgency=medium * Release 5.7.20 -- yeshanshan Thu, 31 Jul 2025 19:59:35 +0800 dtkgui (5.7.19) unstable; urgency=medium * Release 5.7.19 -- yeshanshan Thu, 03 Jul 2025 21:12:27 +0800 dtkgui (5.7.18) unstable; urgency=medium * Release 5.7.18 -- yeshanshan Fri, 27 Jun 2025 17:09:35 +0800 dtkgui (5.7.17) unstable; urgency=medium * Release 5.7.17 -- yeshanshan Thu, 19 Jun 2025 10:03:48 +0800 dtkgui (5.7.16) unstable; urgency=medium * Release 5.7.16 -- YeShanShan Mon, 19 May 2025 17:21:59 +0800 dtkgui (5.7.15) unstable; urgency=medium * fix: correct bitwise operation in preference handling * fix: prevent theme saving when DontSaveApplicationTheme is set * refactor: improve thread safety in OrgDeepinDTKPreference * fix: build failed in qt5 * feat: use dconfig2cpp for read/write the DConfig * fix: fix build on Qt 6.8 -- YeShanShan Thu, 08 May 2025 17:53:09 +0800 dtkgui (5.7.14) unstable; urgency=medium * build: compiling failed with Qt 6.9 -- YeShanShan Thu, 17 Apr 2025 21:51:32 +0800 dtkgui (5.7.13) unstable; urgency=medium * Release 5.7.13 -- YeShanShan Thu, 20 Mar 2025 17:05:55 +0800 dtkgui (5.7.12) unstable; urgency=medium * fix: palette refresh delayed in qt6 * feat: Add files generated by qdbusXML2cpp and DCONG2cpp -- YeShanShan Thu, 06 Mar 2025 17:29:35 +0800 dtkgui (5.7.11) unstable; urgency=medium * Release 5.7.11 -- YeShanShan Thu, 27 Feb 2025 20:47:39 +0800 dtkgui (5.7.10) unstable; urgency=medium * fix: icon is blurry -- YeShanShan Thu, 13 Feb 2025 17:18:19 +0800 dtkgui (5.7.9) unstable; urgency=medium [ root ] * UNRELEASED -- Deepin Packages Builder Thu, 23 Jan 2025 09:07:08 +0000 dtkgui (5.7.8) unstable; urgency=medium * fix: missing window decoration for treeland * chore: update default window corner size -- Deepin Packages Builder Tue, 14 Jan 2025 11:17:31 +0000 dtkgui (5.7.7) unstable; urgency=medium * fix: accessing wild pointer in qt6 * chore: correct typos about Dtk::Gui::DDciIcon::IconAttribute Thanks to Felix Yan -- Deepin Packages Builder Thu, 09 Jan 2025 09:28:38 +0000 dtkgui (5.7.6) unstable; urgency=medium * refact: refacting DPlatformHandle to adap treeland * Revert "refact: refacting DPlatformHandle to adap treeland" * refact: refacting DPlatformHandle to adapt treeland * fix: iterator out of bounds for dciicon * fix: set font family invalid -- Deepin Packages Builder Thu, 02 Jan 2025 05:43:53 +0000 dtkgui (5.7.5) unstable; urgency=medium * fix: availableSizes not work on Qt6 -- Deepin Packages Builder Thu, 12 Dec 2024 03:03:53 +0000 dtkgui (5.7.4) unstable; urgency=medium * chore(CI): add debian check workflow Thanks to kuchune * refactor: xcb platform theme interface * refactor: treeland platform theme interface 扩展Treeland的个性化接å�£ * fix: Possible null pointer dereference and Notitlebar input parameter error * feat: support treeland platform for wmHelper * fix: blur is invalid for treeland * feat: Limit maximum and minimum fonts * fix: app crashed when window destroyed in quick * fix: app crashed when window destroyed in quick * fix: linglong app load qt translations failed -- Deepin Packages Builder Tue, 03 Dec 2024 02:00:46 +0000 dtkgui (5.7.3) unstable; urgency=medium * fix: No judgment on the validity of the protocol(Bug: 286859) -- Deepin Packages Builder Wed, 20 Nov 2024 02:19:06 +0000 dtkgui (5.7.2) unstable; urgency=medium * chore: Correct the name of TreelandProtocols package in cmake * fix: Under treeland, the dialog has not disabled titlebar * fix: Print "load translate" debug log to channels(Bug: 284539) * chore: add IsWaylandPlatform attribute * chore: highlight color is inconsistency -- Deepin Packages Builder Wed, 13 Nov 2024 01:53:26 +0000 dtkgui (5.7.1) unstable; urgency=medium * Revert "feat: add close.dci"(Issue: https://github.com/linuxdeepin/developer-center/issues/10482) * feat: Add notitlebar function on wayland platform * feat: support qt5 and qt6 * fix: cannot move window on wayland * fix: remove treeland personalization protocols useless function * feat: add fixme note * chore: update license info * chore: add build dep * chore: update license * chore: add extra cmake modules * chore: add dtkgui namespace * fix: app crashed in x11 -- Deepin Packages Builder Wed, 16 Oct 2024 03:30:46 +0000 dtkgui (5.6.34) unstable; urgency=medium * feat: add close.dci Thanks to Yixue Wang * chore: animation-dci supports custom icon * fix: wrong judgment conditions * feat: support to change window effects(Bug: 244347) * feat: add window startup effect Type(Issue: https://github.com/linuxdeepin/developer-center/issues/10322) -- Deepin Packages Builder Tue, 20 Aug 2024 05:03:52 +0000 dtkgui (5.6.32) unstable; urgency=medium * Revert "fix: jagged edges on ddciicon"(Issue: https://github.com/linuxdeepin/developer-center/issues/9443) * chore: dci-icon-theme tool tweak -- Deepin Packages Builder Mon, 08 Jul 2024 02:29:21 +0000 dtkgui (5.6.31) unstable; urgency=medium * fix: jagged edges on ddciicon(Issue: https://github.com/linuxdeepin/developer-center/issues/8691) -- Deepin Packages Builder Thu, 27 Jun 2024 09:11:34 +0000 dtkgui (5.6.30) unstable; urgency=medium [ root ] * UNRELEASED -- Deepin Packages Builder Thu, 30 May 2024 02:46:31 +0000 dtkgui (5.6.29) unstable; urgency=medium [ root ] * UNRELEASED -- Deepin Packages Builder Mon, 13 May 2024 03:02:53 +0000 dtkgui (5.6.28) unstable; urgency=medium * chore: insert to cache when icon is not null * chore: add flag to disable noncache flag * fix: missing initialization for baseFont of fontManager(Issue: https://github.com/linuxdeepin/developer-center/issues/8040) * feat: dci-icon-theme support multiple icon size -- Deepin Packages Builder Mon, 29 Apr 2024 08:23:44 +0000 dtkgui (5.6.27) unstable; urgency=medium * fix: setWindowBlurAreaByWM only work once in qt6 -- Deepin Packages Builder Fri, 19 Apr 2024 08:55:34 +0000 dtkgui (5.6.26) unstable; urgency=medium * fix: wrong availableSizes for DIconProxyEngine * fix: PlaceholderText color tweak(Issue: https://github.com/linuxdeepin/developer-center/issues/7554) * feat: support to get specified palette -- Deepin Packages Builder Tue, 26 Mar 2024 05:47:35 +0000 dtkgui (5.6.25) unstable; urgency=medium * fix: icon doesn't update when iconTheme changed * fix: font can't follow changes in qt6 * fix: app refresh slowly * fix: changed paletteType's config value * fix: search icon can't change with theme change(Issue: #6230) -- Deepin Packages Builder Mon, 11 Mar 2024 01:16:27 +0000 dtkgui (5.6.22) unstable; urgency=medium * fix: menu icon incorrect in dark mode(Issue: https://github.com/linuxdeepin/developer-center/issues/6624) * feat: enable xdgIconLoader under Qt6 * chore: warning for connect -- Deepin Packages Builder Wed, 10 Jan 2024 02:30:59 +0000 dtkgui (5.6.21) unstable; urgency=medium * chore: update cmake version * fix: xdg icon loading failed with qt6(Issue: https://github.com/linuxdeepin/developer-center/issues/6459) * fix: debian build failed * fix: DIconProxyEngine read not ensureEngine * chore: fix ut_dciiconengine failed on dark theme -- Deepin Packages Builder Tue, 09 Jan 2024 01:45:43 +0000 dtkgui (5.6.20) unstable; urgency=medium * chore: add synchronization workflow * fix: indirect inclusion of QSharedPointer * feat: move ddesktopservices to dtkgui(Issue: #134) -- Deepin Packages Builder Tue, 28 Nov 2023 05:40:52 +0000 dtkgui (5.6.19) unstable; urgency=medium [ root ] * UNRELEASED -- Deepin Packages Builder Mon, 23 Oct 2023 07:33:18 +0000 dtkgui (5.6.18) unstable; urgency=medium * fix: Wrong value of DPalette::TextLively * chore: find qhelpgenerator from property * fix: svg with filter attribute rendering exception * fix: when iconName is absolute path * fix: missing link when disable librsvg * fix: Wrong IconName for DIconEngine(Issue: https://github.com/linuxdeepin/developer-center/issues/5760) -- Deepin Packages Builder Wed, 18 Oct 2023 06:01:44 +0000 dtkgui (5.6.17) unstable; urgency=medium * Release 5.6.17 -- Deepin Packages Builder Fri, 08 Sep 2023 15:15:39 +0800 dtkgui (5.6.16) unstable; urgency=medium * chore: ut build without source * fix: Compiling error in qt6.4 * chore: add DtkBuildHelper depends * fix(build): ut failed on Qt6.4 * fix: dci icon cache key miss theme name(Issue: https://github.com/linuxdeepin/developer-center/issues/4517) -- Deepin Packages Builder Tue, 22 Aug 2023 06:13:45 +0000 dtkgui (5.6.15) unstable; urgency=medium * chore: iconengine tweak and uint test * chore: do not show ui in ut * chore: add unit test * chore: Adaptation for Qt5.11 * refator: rewrite hasUserManual function -- Yixue Wang Fri, 11 Aug 2023 13:57:02 +0800 dtkgui (5.6.14) unstable; urgency=medium * chore: ignore doxygen-theme folder Thanks to syn(Task: 99) * chore: change OUTPUT_DIR variable in cmake (#163) Thanks to WangFei * chore: adjust builtiniconengine (#164) Thanks to WangFei * chore: adjust xdgiconproxyengine (#167) Thanks to WangFei * chore: add unit test about builtinengine * refactor!: deprecate some interfaces in dtk6 * chore: add dciiconengine * chore: adjust icontheme * chore: add unit test about dciiconengine * chore: reduce compilation warnings Thanks to SPUER(Issue: #96) * chore: Sync by https://github.com/linuxdeepin/.github/commit/559e91167d4919644f37bbcf123eb0651c1528ea(Influence: none) * chore: add proxyiconengine * refactor: Move dotsPerInch from normal function to slots * chore: remove unused pro files * fix: build failed in qt6 due to proxyengine * feat: DIconTheme::findQIcon add fallback icon * fix(build): DIconTheme ut failed * fix: DFileDragClient::serverDestroyed nerver emit * feat: add helper for high dpi pixmap * fix: dplatformtheme fetchPalette crash * feat: load app and qt Translation files -- Deepin Packages Builder Thu, 27 Jul 2023 06:56:34 +0000 dtkgui (5.6.12) unstable; urgency=medium * chore: Sync by https://github.com/linuxdeepin/.github/commit/2e5e092ba3f86b16d1aabbabcf0bfd2ae65b19c8(Influence: none) * fix: fix build failure due to metasystem change * fix(build): suport build with Qt6 && Qt5 * chore: Adapt Qt6 && Dtk6 compilation * fix: ut failed * chore: update dconfig appid -- Deepin Packages Builder Sun, 25 Jun 2023 14:43:42 +0800 dtkgui (5.6.11) unstable; urgency=medium * Release 5.6.11 * Fix developer-center#4117 * Fix bug-197713(App blocked by hasUserManual in live system) -- Deepin Packages Builder Mon, 08 May 2023 13:16:17 +0800 dtkgui (5.6.10) unstable; urgency=medium * Release 5.6.10 * support XDG_SESSION_DESKTOP set to DDE * add DontSaveApplciationTheme Attribute -- Deepin Packages Builder Mon, 17 Apr 2023 17:11:55 +0800 dtkgui (5.6.9) unstable; urgency=medium * Release 5.6.9 -- Deepin Packages Builder Mon, 03 Apr 2023 10:13:06 +0800 dtkgui (5.6.8) unstable; urgency=medium * Release 5.6.8 -- Deepin Packages Builder Wed, 22 Feb 2023 14:12:16 +0800 dtkgui (5.6.6) unstable; urgency=medium * Release 5.6.6 -- Deepin Packages Builder Tue, 21 Feb 2023 11:46:51 +0800 dtkgui (5.6.5) unstable; urgency=medium * Release 5.6.5 -- Deepin Packages Builder Thu, 02 Feb 2023 14:12:15 +0800 dtkgui (5.6.4) unstable; urgency=medium * Release 5.6.4 -- Deepin Packages Builder Mon, 09 Jan 2023 13:28:09 +0800 dtkgui (5.6.3) unstable; urgency=medium * Release 5.6.3 -- Deepin Packages Builder Mon, 12 Dec 2022 14:44:49 +0800 dtkgui (5.6.2.2) unstable; urgency=medium * Release 5.6.2.2 -- Deepin Packages Builder Wed, 30 Nov 2022 10:32:07 +0800 dtkgui (5.6.1.1) unstable; urgency=medium * snipe release 5.6.1.1 -- Deepin Packages Builder Wed, 22 Jun 2022 14:33:59 +0800 dtkgui (5.6.0.1) unstable; urgency=medium * Release 5.6.0.1 -- Deepin Packages Builder Tue, 14 Jun 2022 10:51:30 +0800 dtkgui (5.0.0) unstable; urgency=medium * Release 5.0.0 -- Deepin Packages Builder Tue, 03 Sep 2019 08:59:03 +0800 dtkgui (1.0.0-1) unstable; urgency=medium * Initial release -- Deepin Packages Builder Mon, 29 Jul 2019 16:58:07 +0800 dtkgui-6.7.46/debian/control000066400000000000000000000072471522615413000157430ustar00rootroot00000000000000Source: dtkgui Section: libdevel Priority: optional Maintainer: Shanshan Ye Build-Depends: debhelper-compat (= 12), cmake, pkg-config, libgtest-dev, libgmock-dev, libdtkcommon-dev, librsvg2-dev, libfreeimage-dev, libraw-dev, treeland-protocols (>>0.5.8), extra-cmake-modules, libdtkdata, libdtkcore-dev , libdtkcore5-bin , qtbase5-dev-tools , qtbase5-private-dev , qttools5-dev , libqt5xdg-dev , libqt5xdgiconloader-dev , libqt5waylandclient5-dev , qtwayland5-dev-tools , qtwayland5-private-dev , libkf5wayland-dev , qt5-image-formats-plugins , libdtk6core-dev , libdtk6core-bin , qt6-base-dev-tools , qt6-base-dev , qt6-base-private-dev , qt6-tools-dev , qt6-wayland-dev-tools , qt6-wayland-dev , qt6-wayland-private-dev , doxygen , graphviz Standards-Version: 3.9.8 Package: libdtk6gui Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, qt6-image-formats-plugins Multi-Arch: same Build-Profiles: Description: Development ToolKit Gui Library (DTK6 with Qt6) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the shared libraries for DTK6 applications. Package: libdtk6gui-bin Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libdtk6gui( =${binary:Version}) Build-Profiles: Description: Development ToolKit Gui Utilities (DTK6 with Qt6) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the utilities of DTK6 Gui. Package: libdtk6gui-dev Architecture: any Depends: libdtk6gui( =${binary:Version}), libdtkcommon-dev(>=5.6.16), libdtk6core-dev Build-Profiles: Description: Development ToolKit Gui Devel Library (DTK6 with Qt6) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the header files and development library symbolic links of DTK6 Gui. Package: libdtk6gui-doc Build-Profiles: Architecture: any Depends: ${misc:Depends} Description: Development ToolKit Gui (Document) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the qt Document of DTK6 Gui. Package: libdtkgui5 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, qt5-image-formats-plugins Multi-Arch: same Build-Profiles: Description: Development ToolKit Gui Library (DTK5 with Qt5) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the shared libraries for DTK5 applications. Package: libdtkgui5-bin Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkgui5( =${binary:Version}) Build-Profiles: Description: Development ToolKit Gui Utilities (DTK5 with Qt5) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the utilities of DTK5 Gui. Package: libdtkgui-dev Architecture: any Depends: libdtkgui5( =${binary:Version}), libdtkcommon-dev(>=5.6.16), libdtkcore-dev Build-Profiles: Description: Development ToolKit Gui Devel Library (DTK5 with Qt5) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the header files and development library symbolic links of DTK5 Gui. Package: libdtkgui-doc Build-Profiles: Architecture: any Depends: ${misc:Depends} Description: Development ToolKit Gui (Document) DTK Gui is the base library of deepin Qt/C++ applications. . This package contains the qt Document of DtkGui dtkgui-6.7.46/debian/copyright000066400000000000000000000017721522615413000162700ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: dtkgui Source: https://github.com/linuxdeepin/dtkgui Files: * Copyright: 2022 Uniontech Software 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". dtkgui-6.7.46/debian/libdtk6gui-bin.install000066400000000000000000000000341522615413000205250ustar00rootroot00000000000000usr/libexec/dtk6/DGui/bin/* dtkgui-6.7.46/debian/libdtk6gui-dev.install000066400000000000000000000001641522615413000205370ustar00rootroot00000000000000usr/lib/*/libdtk6gui.so usr/include/dtk6/* usr/lib/*/pkgconfig/dtk6gui.pc usr/lib/*/cmake/Dtk6Gui/* usr/lib/*/qt6/* dtkgui-6.7.46/debian/libdtk6gui-doc.install000066400000000000000000000000351522615413000205230ustar00rootroot00000000000000usr/share/qt6/doc/dtkgui.qch dtkgui-6.7.46/debian/libdtk6gui.install000066400000000000000000000000331522615413000177560ustar00rootroot00000000000000usr/lib/*/libdtk6gui.so.6* dtkgui-6.7.46/debian/libdtkgui-dev.install000066400000000000000000000001611522615413000204460ustar00rootroot00000000000000usr/lib/*/libdtkgui.so usr/include/dtk5/* usr/lib/*/pkgconfig/dtkgui.pc usr/lib/*/cmake/DtkGui/* usr/lib/*/qt5/* dtkgui-6.7.46/debian/libdtkgui-doc.install000066400000000000000000000000351522615413000204350ustar00rootroot00000000000000usr/share/qt5/doc/dtkgui.qch dtkgui-6.7.46/debian/libdtkgui5-bin.install000066400000000000000000000000341522615413000205240ustar00rootroot00000000000000usr/libexec/dtk5/DGui/bin/* dtkgui-6.7.46/debian/libdtkgui5.install000066400000000000000000000000321522615413000177540ustar00rootroot00000000000000usr/lib/*/libdtkgui.so.5* dtkgui-6.7.46/debian/rules000077500000000000000000000040471522615413000154130ustar00rootroot00000000000000#!/usr/bin/make -f DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/default.mk # 安全编译å�‚æ•° export DEB_BUILD_MAINT_OPTIONS = hardening=+all export DEB_CFLAGS_MAINT_APPEND = -Wall export DEB_CXXFLAGS_MAINT_APPEND = -Wall export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-E # reproducible编译å�‚æ•° DEB_CMAKE_EXTRA_FLAGS += -DCMAKE_SKIP_BUILD_RPATH=ON DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) BUILD_DOCS := $(if $(filter nodoc,$(DEB_BUILD_PROFILES)),OFF,ON) BUILD_DTK5 := $(if $(filter nodtk5,$(DEB_BUILD_PROFILES)),OFF,ON) BUILD_DTK6 := $(if $(filter nodtk6,$(DEB_BUILD_PROFILES)),OFF,ON) %: dh $@ override_dh_auto_configure: ifeq ($(BUILD_DTK5),ON) mkdir -p build5 QT_SELECT=qt5 dh_auto_configure --builddirectory=build5 -- \ $(DEB_CMAKE_EXTRA_FLAGS) \ -DBUILD_TESTING=OFF \ -DBUILD_DOCS=$(BUILD_DOCS) \ -DDTK5=ON endif ifeq ($(BUILD_DTK6),ON) mkdir -p build6 dh_auto_configure --builddirectory=build6 -- \ $(DEB_CMAKE_EXTRA_FLAGS) \ -DBUILD_TESTING=OFF \ -DBUILD_DOCS=$(BUILD_DOCS) \ -DDTK5=OFF endif override_dh_auto_build: ifeq ($(BUILD_DTK5),ON) QT_SELECT=qt5 dh_auto_build --builddirectory=build5 endif ifeq ($(BUILD_DTK6),ON) dh_auto_build --builddirectory=build6 endif override_dh_auto_install: ifeq ($(BUILD_DTK5),ON) QT_SELECT=qt5 dh_auto_install --builddirectory=build5 endif ifeq ($(BUILD_DTK6),ON) dh_auto_install --builddirectory=build6 endif override_dh_link: ifeq ($(BUILD_DTK5),ON) dh_link usr/lib/$(DEB_HOST_MULTIARCH)/libdtkgui.so.5 usr/lib/$(DEB_HOST_MULTIARCH)/libdtkgui.so -p libdtkgui-dev endif ifeq ($(BUILD_DTK6),ON) dh_link usr/lib/$(DEB_HOST_MULTIARCH)/libdtk6gui.so.6 usr/lib/$(DEB_HOST_MULTIARCH)/libdtk6gui.so -p libdtk6gui-dev endif override_dh_auto_test: ifeq ($(BUILD_DTK5),ON) QT_SELECT=qt5 dh_auto_test --builddirectory=build5 endif ifeq ($(BUILD_DTK6),ON) dh_auto_test --builddirectory=build6 endif override_dh_auto_clean: dh_auto_clean --builddirectory=build5 dh_auto_clean --builddirectory=build6 rm -rf build5 build6 dtkgui-6.7.46/debian/source/000077500000000000000000000000001522615413000156265ustar00rootroot00000000000000dtkgui-6.7.46/debian/source/format000066400000000000000000000000151522615413000170350ustar00rootroot000000000000003.0 (native) dtkgui-6.7.46/docs/000077500000000000000000000000001522615413000140345ustar00rootroot00000000000000dtkgui-6.7.46/docs/CMakeLists.txt000066400000000000000000000077731522615413000166120ustar00rootroot00000000000000cmake_minimum_required (VERSION 3.10) find_package (Doxygen REQUIRED) set (QCH_INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/qt${QT_VERSION_MAJOR}/doc CACHE STRING "QCH install location") set (DOXYGEN_GENERATE_HTML "YES" CACHE STRING "Doxygen HTML output") set (DOXYGEN_GENERATE_XML "YES" CACHE STRING "Doxygen XML output") set (DOXYGEN_GENERATE_QHP "YES" CACHE STRING "Doxygen QHP output") set (DOXYGEN_FILE_PATTERNS *.cpp *.h *.zh_CN.md *.zh_CN.dox CACHE STRING "Doxygen File Patterns") set (DOXYGEN_PROJECT_NUMBER ${DTK_VERSION} CACHE STRING "") # Should be the same as this project is using. set (DOXYGEN_EXTRACT_STATIC YES) set (DOXYGEN_OUTPUT_LANGUAGE "Chinese" CACHE STRING "Doxygen Output Language") set (DOXYGEN_IMAGE_PATH ${CMAKE_CURRENT_LIST_DIR}/images/) set (DOXYGEN_QHP_NAMESPACE "org.deepin.dtk.gui") set (DOXYGEN_QCH_FILE "dtkgui.qch") set (DOXYGEN_QHP_VIRTUAL_FOLDER "dtkgui") set (DOXYGEN_HTML_EXTRA_STYLESHEET "" CACHE STRING "Doxygen custom stylesheet for HTML output") set (DOXYGEN_TAGFILES "qtcore.tags=qthelp://org.qt-project.qtcore/qtcore/" CACHE STRING "Doxygen tag files") # find from cmake target property if("${QT_VERSION_MAJOR}" STREQUAL "5") find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Help) else() find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS ToolsTools) endif() get_target_property(_qhelpgenerator_location Qt${QT_VERSION_MAJOR}::qhelpgenerator IMPORTED_LOCATION) if("${_qhelpgenerator_location}" STREQUAL "") set(_qhelpgenerator_location "qhelpgenerator") endif() set (DOXYGEN_QHG_LOCATION ${_qhelpgenerator_location} CACHE STRING "Doxygen QHG path") set (DOXYGEN_PREDEFINED "D_DECL_DEPRECATED_X(x)=" "DCORE_BEGIN_NAMESPACE=namespace Dtk { namespace Core {" "DCORE_END_NAMESPACE=}}" "DCORE_USE_NAMESPACE=using namespace Dtk::Core\;" "DGUI_BEGIN_NAMESPACE=namespace Dtk { namespace Gui {" "DGUI_END_NAMESPACE=}}" "DGUI_USE_NAMESPACE=using namespace Dtk::Gui\;" ) set (BUILD_THEME OFF CACHE BOOL "Build doxgen theme") if(BUILD_THEME) if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/doxygen-theme") message(STATUS "doxygen-theme exists") else() execute_process(COMMAND git clone https://github.com/linuxdeepin/doxygen-theme.git --depth=1 WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} TIMEOUT 60 ) execute_process(COMMAND bash themesetting.sh WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/doxygen-theme/ ) endif() set (DOXYGEN_HTML_EXTRA_STYLESHEET "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome.css" "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-sidebar-only.css" "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css" ) set (DOXYGEN_HTML_EXTRA_FILES "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js" "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js" "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-paragraph-link.js" "docs/doxygen-theme/doxygen-awesome-css/doxygen-awesome-interactive-toc.js" ) set (DOXYGEN_GENERATE_TREEVIEW "YES") set (DOXYGEN_DISABLE_INDEX "NO") set (DOXYGEN_FULL_SIDEBAR "NO") set (DOXYGEN_HTML_HEADER "docs/doxygen-theme/doxygen-awesome-css/header.html") set (DOXYGEN_HTML_FOOTER "docs/doxygen-theme/doxygen-awesome-css/footer.html") endif() set (DOXYGEN_MACRO_EXPANSION "YES") set (DOXYGEN_EXPAND_ONLY_PREDEF "YES") # Exclude private classes. set (DOXYGEN_EXCLUDE_PATTERNS ${PROJECT_SOURCE_DIR}/src/util/private/dimagehandlerlibs_p.h ${PROJECT_SOURCE_DIR}/src/util/dimagehandlerlibs.cpp ) doxygen_add_docs (doxygen ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/docs ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT "Generate documentation via Doxygen" ) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/html/dtkgui.qch DESTINATION ${QCH_INSTALL_DESTINATION}) dtkgui-6.7.46/docs/images/000077500000000000000000000000001522615413000153015ustar00rootroot00000000000000dtkgui-6.7.46/docs/images/ddciicon-example1.jpg000066400000000000000000000251701522615413000212760ustar00rootroot00000000000000‰PNG  IHDRÈÐÍ¿¹? pHYsÄÄ•+ IDATxœí�w|ÅùÿŸÙÝ뺓tê]V¯n²dc[î½cƒMo�€!À|É7@‚“À7tBI 0&`c÷ŠåÞd[²ŠÕlY½Ÿ®ßîÎüþ8[¶ä«’ÎÒ)û~éÝÞîìÜíçž™yfæyЂ_U„Q@!LB §ÇœQ!ƒ 9ácF©Ej_Z­¢¤¸eètº[w3×ðññè*Ü:ô&ÜÔÎ6µ™k[ÌyM†ýÅ*µRÅHe< ŠBŒ˜P¢Ð¼_UPâyž¢€"„¡Á›X³&7'äöyQ‰bš°&kP�ê ì¡KuE5� ??F,Å@€ ˆ   @ ­$@cþ꥛Míɪ'îKH�àg°"kpRoâ¶V\éÔËU~€ „ !„ƒy( €ÌYL­Ï<’±x¦ÿ@×\`P&e“|ºI³%¿Dªò§Å" !D  Œ�æ,bªãíײU ¸HV°ï¯&ŒÂÚvÞlÆ0ËƘÇÆcLð¼YLkþ¾:gdªt k+àMDùˆWNÃë4˜5Ó4"„&`˜æ9sÛªßŽŽ eºžÞ‡¿˜¾ÿ¶‘†¶Vžã€ À"¬Eóô#é#Ód]Co%Z)Y4:Õ¤ÑBxL(L€çŒé‰ò%³ºnÞ͘pu¸RÊZ,c 0±˜4�?�2е Ì™lèìd(Â`Þ4)'$-áºÒ†.arñˆ0%)Ö¢[º`Ø@×G`è0;}˜Ø¨§R.3Eè³ ô¾RÉ©žÊ½-fç†$ÆÎ(*gTÈ@WC`¨1>3ˆ ºíýLˆ¿˜Qûö§«ýôÙâÝNW6·¶@P€FjÜÌ)9Y#Sûñ.ƒœ@_MX*A}/«¶¾ùí�¾ÕhuófNÈ•u -'ó‹·í>ì«ôyá7÷F„õ¢daÙŒ×a4ƒu‘C_)(*ý­Ïï[>wñÜIõ”)!dÓöƒk~Øþ‡—ÍLKp·pAXÞH?«¶¾ùÙß½ýûç5<ÙÁiùçKW¿óåûyÁ]»%ËéOÃÛ}{ßò¹ŽU£†'ß·|îÛ}Û÷; ô/Ó­ìõ»öè«°NŸ-Öhu‹çNråäÅs'i´ºÓg‹ûxS�þeßæOì©gÚ¢•û6Ò‹2û:$Ü}àļ™nîWÙ!4oæ„ÝNü—�Ú€Þ=˾`ÕV�ûöZUÐwaWÞsÇl „ì=x¦OÊ›ÿ#„²G¥nüù@o:pðÀz×ôô�Úꋪ ïÂjnm·zö<ùÆ;ÿî:nóÿ“sÂC­..�AH—¶ú¨*è—λÀP¢_T}·XAþu -Ñ‘¡ÖV®5öþ¯kh ¸¥[€Ýó¢ã6¯ý¿[S¯ ¿,V_…•‘w2¿8:2!4crN×q{ÿŸÌ/ÎH�ëãMÝBÐ�ëté©ïÚêkS8sJζ݇]ô²B¶í>›8hõzÝ& “нA˜+tJÿ \X6óüS÷D†÷¢dAXÞH¿ ËŠ'ú ÂòFúYXž@–7"xÞ<‚ ,� KÀ#Âð‚°<‚ ,� KÀ#Âð‚°<‚ ,� KÀ#Âð‚°<‚ ,� KÀ# �F3Ðu‚KÀ#ÂðŒ‹ˆÜB°XA–€GšB� X,� X,�àjPžçu:�Åbá8cÜ_Û\BE1 #‹}||hšî—bätŸ1!D¯×wvvR…¢iš¢ú³Åó<�1¥R©P(#:pÒB:;;µZ­L&ë_=uAÓ´ÕPñ<ßÑÑÁ󼯯¯ -oljVôz½V«U(RÕ�Ð4­P(´Z­^¯÷ô½<�#‹Åó|gg§\.¿•öC&“iµZ¹\.ô·¼G�w­Vëz�JÇ¢}5ÒÃõâ¢6Ñ-Ýi¡@%ÆÑJ>MÍN³L‹4)Dλü4Mó<¯Õjýüü\ü ƒd0ì½×ØØ ãdäØd >8¯\_.7pŽ ›œ!w&ž® ’aÇr!!BNa/�F{ïÕÔÔH$ËÌ£�Ïû|vÁGϺÚV*Dä‰ ÝSÃu"Ê®õÂ›ÍæÈÈHË„8²F„ªº¬e~½Ï¿¨MäÖýô,z;_™W'ùlj[ ÓEQÔà'àGý'O·¤]´t[ »ªêâD£xáÏA¥íve-ËÛq4*DÙ|·ÙH=´' ÉHC‹5z桽�[4ÛìrÙ»µ€·à¶wÊÌ£G÷ªkõýà ¨ÑÑ�íS[°  !ˆÛÂúðœÏéfq¯ï­ú!�j¿›¯ìuiƒ÷„Õd¤ÿq¡÷ƒÕ2Ø?츂ä×~Z¨¸¬|¡C ÷„õn¾�cg•£;!øf1 óƒi±0þO‹ÑÇ‚Ñj¸!,­­¯�;?ϯåÂÜx€·ŽÂ¦‹ÝÞÚX!Ó¹ì ú°%e-¯»!¬=5RcoÍÕ¼xe"ÀþËðê�žï8´¯FÚ»’Ü´ÿ½7_øª°ÃŸÊ×ÿõóo ôn•mÑkÚu,±óòÖㆰŽÔKzw�8?øf1Pj:áî�ÀÙr‹öºð‚bÄ"‰ˆ4f–½°võ£ß•±¶_n¤•ë�;TÊÀËÀ_ ,†{~‚&;+b.´õC‚»[˜ûäó¹]‹ë³Á ·ór pãq^ÑõfìöÉ\ ðün8tÅîiÕZ¯nÚºêÍ/‚\óäp9`ÛÎíÚ¹ñ—’rƒoÆmW,ÎæƒØ¶‹Û×ïÙ�_g 6iÎÜeãÃåÈzáßf?ñˆüÜO{ÎêÔ¹Ëîx 7Lz“écŠ~úçùýgêùð¤é‹æ-¡fÀ|êÓWWÕÌýxÕÔH €¯þî…÷¶g?õå]dÍÓÿü±•µà,ÞÒñ3ç–ÜÚõrÂ_=;ZɶœúyÛÆCeW htîÔ»çg†Š€/_÷ÆÿTÏ|kŽyÏÖcG*qüäù�ß1<¤—ó)Ýp¯ónï­P;.ˆ'FÃþ)€¿ŸrTx§ýÂ;|óÞ÷Þyecsø”ù+WŒô­*(îàpkþ‡¯|ú}cèÜû–Þ�Åûø½?üTmºÚåá‹Ö~úæQ”9{ö²ÃöOÿ³»îæÎ—¿yO¡<}ùC §«.ýæ¿6]²ß¬Q¡Ó³tn8’fÍÿËëO­^:zv·— r¾q×;ïüi¯)}Á’ÇÄöüû¹wÕrW¯¶œÞðò?ËUYSïŸreÓ·_ëp²øÄ5œLB»2g÷@&|<îØ;*ºÏ ‡wgœo‚•Û�‚ºÏzÑ\¡þüž�/yõ±GÒe`B.°%ßmÙ�s^néh™"ýhåÚG'?6Õ€J�ÿ§'Gˆ€ §.ZWP¥[¡êþâ‡ßÿøÿÎ e`„oGé§›^Zm»È'2%&\�¨€ˆ´´D1`tãKý™Ÿ¿:§\±ê¡{Å�ƒžeûÆ‚¬§F‰ÄiÏüáÁ\ p´áÌ…¯KêØ\¿¾wxݰX*±�‡ ƒwf‚\ë–Ám×�ÉaÝ2�ÐÐa‚eëÁà¬é+ñ%u‡¯½X¦‘%g%Ê®+·•i˜”¤…õ5’’i©(ª¾ú-Ðþþþ ’ÊU4ÖèL7}x$•I®>qPL¥©nê­%ákËÊ:¥ ±WçKÄщ#åÆü‹�WËû¨(ë=•*Š×Œýñ(ÜV´’»ù`«æ: (D°íî«Ý)«/4JàW?CE»óÂclçŒ9!zÌ¡#°e„]šiç,fB‰ÆzªûO�èÆ!›mBÎû»!¬tµm³s¼–®3¾Øv$©áÏS`VÀêC°±´O…zèðø8¹¡¼°Êrõ!„ HHU±¥UW×Pâæ²²ZQ\Z”[½â«žtT�«‚è”H_ÄÈ}$Dg°Ú7¾³¥þúÎ=Z$°î¡ëù’OHP+Н\ý†ÙšŠszéÈÄ�n�qc,6!̼¦Taó­=Up×�°n+ ïA”쬄?t£p×k2¨PŽœ~oÊ_¼÷%Ü96Q¦+ýåDçôGŸ˜=RÞwï| }`ZŒ¤åÂúï«ã–¹nSÐä Î›÷6õÆVëÞÊߟOùÓê‘™þÝ^Ÿ~úŸ}°†¾#+Š4äý¸·!cá‹Ãåx�}+îX¬é‘&û»!6]„‡·&$PÝ ÷oìÚ÷¨“)&×k2¸G,úŸç^ž,.ؼþýoOÔDÜ63QAŽù«»ÝïòÆýðåaý¨GŸ]u{¬Ìõ††VÏ[2œÏßýÉ—y—B§ýyÕŠ?€|G/xñöðÚ]›¿þ¥1ú¾•ÏdwÙIÚÂ+ª¾x÷Û¯÷]j#Ý_2asûÜÿND§Öÿðá†b4áþ÷^˜äžõtd2Ù}¢—/_V(º™¨?žðý¢ÈÑê†'³à£9`â ÷k8]ïj%NÕ¯Ûqã½^ãêõƒ÷Ü’Ï ×þP®pàÐúø4¨$ÐbpCURš<‘¡u«ƒ÷:pj)^éL=ŸŸu£Ì§†kÃlì·G+3uãCû­£=1Ìü›LÁ\ A܃ÈgSÛbûÃí­äÿ>¹�b¿ EzóTý$øß3Z£}ú¤­%÷Í̵´_&¦Ž„åÀïËm]ØÜkçSNˆå§yÍq*»Òö~y;N„uÝ—{~¼fVëK£;•¶æí¡á—³:¿ŸÓbo4`Œay;ŽüXuuu!§AAZMÔ‡çU?”+¯[÷ቆ§3;�6ÇBÂÃß&0˜q$¬ææf³Ù,‘¸´†ÂÈ¡}5Ò# ’Â6ñ£1#ð•�h.Cmfži’Ò.Ù6ëMƒ‚‚\ü ƒGÂ2 ­­­"‘èVÆ@ãyžeÙ€€¹|@—Ö ô G},©TªP((ϘL&…B!•zÕ¦�›pÔ¢(J.—ó<¯×ë¥R©§íÏóVUÉåò[òTÀ£8é˜K¥RŒ1MÓz½žçyêýXŒ±5"7!D¥RI¥RÁ\ õ±º0›Íf³Ùd2qg²õcëÀ“a©T*‘H\+ r\`ŒY–µÚ•þÝé`ÕMÓ"‘Hh‡ ® K@À- !àa xAXA–€G„%à\ÝLÑånŽãúË/€1¶®žÜ C —Ü ,ËZ,ë©~�ÀÞå#„ˆÅb‘ÈÃÞn Î-–Åb±X,4M{hñ]—R !f³c,8߇Nš«­b˜[‘“Ü:·Ã²,Ëzi�ë8ÆØj«nYm€¦i‹Åâ`I´€Wà¨)dYÖõ‡Q�Žj0ÐífJÏ"k"1E|DÄ_ŠCä|¤3öSÉua½Çqbqïó_ 8Ž:ïz½!ät¤fäPA«¨RCsÄ‘Dâýø 5+cœÈ cLé6BÀ»p²4Ù±Åâ1\hµ1œË‰–Фùs鬃HÖÖq¢°4Ù«qÔ:n�´,:X+i7»çyâ0:ß*ª7P“Ã-R;¦ !$ôß½G²pÐv˜©]ÕRwUÕE³‘Þ^-ÕXì^.xJ½�Þüà‹÷Žj¬¬ÖaÀš“ß­ÛÝ8vÑÒçïIÖï]ûkVÃyÚK¾éøÛ¯|sX<â�•w?4^zâ£|Wl$ÚÂM¿}[‰z̯_0]]wº¼ç—L4ç>ÿË–òè¿}nùÒ4þbY‡,sÎoïH”ÐÁKž~òo¼wr(©?ôã?O±Ã&ÌzzåŒÄú}«??Ù =’k&ÈÙÚ-o½ÿI©ßŒîyvYŠeÿ¿þ²µÆA+Ù‰0“©)±ôö2®ZÓíäšC@«�¸ä÷\ÉŒYfOžàk݉ÄמÊ;^”_t©´†Å‘Fãµ l¥½Lôï*·U^Ô›Ê~|xÅ�]ǤcôFý• $áîø k Ï͵¡#r^x~õÛo”çŒ�7cüäÌ ¹¢Ú\saßáó§ *ŠªZÍ$^oè–3 ×WT �«}îú1Y¶Ž³« 7„å#&&cÏJ™8øù"·8™Ѱ0™ù©„kÖ03žñ#ØWÉkl4=Q0Þ±s í¬!‰ÿâÿ%�:µgç�Ïo9öë×�©?ñù'Õ&ÝûÌg–4nzãÕó6Í2g1Jv-íåU±¤9ËÞ¾/¥KH¢ôåÏ[0ÐŽ¢”jÄ=Ïüs|ñá¼#?ýí­Í“\ýpF÷9W{à«W°L¿{Ú½Ó¨Ê|ìC¹B‰ùfÿîõY‰×úUI¤øu£�å/±ýìud{ÇÓ°0‰ñ“¢qQt”/€Su¸²Ý%ÅØ+|°! �§:Š/]Í£KXÖæ¯†c9�¦çÎyö�ÝíW¾öÀeË•“k�ùÞ>kdt˜Ÿ˜êét¹9íå oRþIü¥†NUPXèÕ¿P)­ ŽU“ª‹uWÛ Â™o® áXžñ�Íœwÿ¯ß|"¥aï/'[ ÅÐ4à«ÓÿlÕεÅ!Kî¸;7yX�R„ºD·lšɉþúšz“ïõ „¨¤ö;ÆnX¬WÖaûü+�dg9?'�–‰`iÚÕ©Àj 9q“/Ôa^’§‰ µè¶½]óÍçì¤á>Ú‚Ý»ö˜ ¡û9ÄXùýëßVŽš5D�XS\Ô*JŽRÓ’z%ÒäÍOщš �|»Ó×ShÛN{IÄ9®\n1FÇM_0sÿW{‡y`NJÕYv¼T¶ðžùQQSÅoü|Ã;úYqLSþ/kò9}c]pSÞ¿·C±dIV¢/ù\˜©D4 O¦N?t.:�’Çø)|È¥3§N„ÅàÚ ›×!à¦äšiS}þƒw¿ÂËÇ¥ù⦒ü²ðEOäªíY&ú•W^±÷%Z,–Ü)ÅPÒÁ`;Î÷é4CœšQZ ÙRÊ9íZYQdlKÝPðàÝ]ˆ¤Q#Ò‡Y.åí9zø 6yÊhSImø¸ÙÉJÒxa}žføÌñiʰ0º¡0Ûæ{ËpÚâ�N‹�+ÃS# çwíÿù\+�½l´åØ%ÿY³ü-u‡wÔf.G�=°~_Ÿ�ûÌÓ ²Ô4 ¥B|ùÜŽ|zÌô„yȨœ(æÊ…½;òv]hcbÒsÒ#ƒåŒ*.#;¨óü¡#;Ï´J’&.Œo<­¶pB¤üê—‰dÁ�Æêãû®ÛYÔ¤ýë'f�òg(ypœkÞæ½ÛÎ5«Ò§,šèß~*oÝþÊyì¼¹QM§5 ³rL`t”Yûs~¹)${\òð1i±–ê#{ó6¹Ô!�—£–Ø–£5ïZ­¶Gö€ÓÍâ’vGÆÁÔäXšÇ°¡˜k¶1Ka›$?6;ØrãŽã”J¥‹— BÜ[“¡f+4ŒŸSaÓ`âÀuUшxm¦q»¸7‘"¡IºÚÉ$ë™z\ÔìFO<#€“;Û&àu¸=C—êo ‘÷[G;TΧù[œŸ'àm¸-, An˜Ù­Œ_öð‘‰afÊKærÜ¢7k $4™nôõI[J™a”x‰Ã]À]œ±÷–JLæDC{Û&ÉøYQF•}³'ñv¹t:EQ¶ØcÅíâ mŽÆ‰=Q$#€Kñ³8h !c»g zœ6%›xTØ*ªètÁAD‘x_.CÍ:mþ¬æJ âÕ8–ÑhÄ»¸Û�'¨ÖÆÈBëXÄòD4Q0X-Á¡r>ÂÓÈ¥Ïó4MËd2?ƒÀ Ä‘°8Ž3™LŽ[Ã~ÇÚJ¥R§)ƒ3ެ‘5’±5Rò-ƒçù[œÓUÀ8ÉboMøfM%çéªB8Ž£iúÖ„<ð(Nš›®ðëÖ€UèýXr ‹Å4M æjà¼cµ!žç»²¡öck oúú¥d��Å¥2MÓEÑ4Ýé¿kЕ—à�<Š«#/«QñhU†^¿ÿX`p"KÀ#Âð‚°<‚ ,�àê¨P£5•_nlhÑê f–s/¶˜cD £�KB• 1!¾Ji?–,0€8O„‰19[R[ZQOÑô5oSÚ9B¬nWBNŽ ™A «•½'˜ä�ª¨mh•H¥ý«'[÷³)"4 wL¼ -oljVΕÔÕ6´Ie „häÑ?Š¢¥2EmCÛ¹Òº[óá<‡#ait¦’Êz‰ô–ö{ÄiieƒFç˜\4n+<Ø—î­¹ÚV>05þ4¥ç» M…©zW²nÏßôê›Ê�ÇÜä M§ÉÉıèÛ;ìåÿs7Ü Á½Œ�]Ù÷oL RßÝ6½ôÁJÁÝàqøš�¯¬þè”Îá¾P¢9ùÝ£¯ì©ê›ýsÃõÎjâ`ùh7�ˆ‚µK ØÎ€²×¾V7Àf½ ‰€MCßã)º*HÑ+ßÕÊíp¦à�™01Êîi^60ÄM[Wým_ÚÝKEE;•VÓac§Í¾gVœ/ìùïïz~ûZBùÆ=;ˆ½ðÞò‘ÄFþH›™2»g¬œ1wD 1ÚN?ɶmúÏîÝgñyÚ IDATqtæµÉFÒÄÖÒŸرýL6nÒ”Åq—þºzg‰�åß-ï}zÔc/¿>Ît¢GþKµéøgo½õK§™«|ö®½ ÿæ—ˇ#}åÁ�ßí<_¤Q$g�[±lB²Ê¹=r”ò¤ðb#ºî^ÏL ··¾A>¶T÷éxã0Àý™ðÆTGõ **oèzÉqlFR¸ãª$D_öKÞÖ_.\Q¥Îž•=ʧvëw{JÔ£rãä¤ñÂú½ùÇO^‘¿mî¤ÔôpÃî·>üª-þöeS§¥H+¶®ßΦNM–_Þüñï÷Ê?²h~¦J[|’Òbñù¿¿º¡zÄ•KGÅ1uçšF§HØÚ-oÞ|¹ µ�ýðÕ/w“Ô; 9~ ´ž ›ºpxD×ãÂ-»ßýh�)ëñ§Ž ã.é‡å G]9^rûƒ/Þ5!'!ÐxtÍßNHsrÇΚi<¾sM©ßÔñÑA!QAúâSÚô§ÿgÙ�““béŠ>zyÎ]2kÑm¨p×''$ÇGù8ëª8²XÖ‘¿S¾.€'·Ãúe0'¾ÛñuðÜ.€áÁðÉ\çåÜx/¯ˆá ͹cõ39þÀ¸Dißÿ²ýÌ•©³"øÄe�¾4'„¢9ö•�ü‘sgioÊ”É_¹9c%ÑœÙm+ýd(³wÛ>ËÈß¿pç8_02Õ®\Û½rDS…÷›”82=QŽ’ÇL I¡~…"ãÒÓTlå¿Ô��,Bbu|jb ¸1ïÛ-º9/?³"SŠF„™Î½tôxݸőNŒ–M!ËñqÏó[�ðün0°pçØu/Üv-£U³îÜfü¤°á»¹}»°°ƒi¬ìH&•XH«†“õ Ö”^TPVZ`7$o#S¦­Œ•v.g;ZŠÚ˜”™Éªk©˜nþÒ1óÉ>õѧ��˜7kÂÌÛâonRlæ¿ì>:·ÔV—X:Ϭzyc×!Ê7Å…|6î$7˜oV€ ¶®€™kAg�yßÁÞû`tèU_è•N@_,€x›åõ,Üõš >kf ²±,Í^þH™2£oÎX™jûr±a—…€Êq�&xì]ï$Ž;uäĶï?Ù°{ꪗç§v;Á¥ü—”HDÓÁ+^úÕìð®ÏF)$ï:Éá»ÝÆÿZÛëÐÇFÀ�w€„�æý.¶Á+`W%Àï'ÂíÉNëС5z±»�o..h¥ ‹é9±›?òæL™¼�Œ•”íË)¿ÈX Wq©úê�‘XÌìM6³,«cÇ/Xþú« “*ÙQd 4#¸ºÄÒnþKĈ„‰õµ(*>KÚ^Ö‚‚C»rp¨\X×â†ÅjjÑÆGØ|kÆ0øÏR¸s4é!÷+h1ÌŽƒ?Nr£p×k2H0Þô^ nÊ0Qãɽߔ/}mT =Ö.Êlå�||LÇM™2ýZòþýû›2VÊÔ¶ÓO¦OË�ß¿çý�e÷LÅ5g×m¨ãènsùì•_þðfAü’©ã¢d†‹eµ((;TBɃ†…៎Ÿ8éB)$r›ù/FFJÛKIЉDQٙ˗zñ›/Þ7Íœî ËláJ+›2’©æåñîÕ ¤²É`2¬5ÜÎþPZÕ¨ V÷O¥¦Vm±7š+*xþßž?е̸½™8š©_ÜNz£åعjBlߨïå ½Y_eaùC§«ô†>¥ÜÕ,y§*Ív¶ x;”Å`· ЍžK“»þtóÞc›Út½»kK»~ÿñ2�Ál¯|GLð,F ¦Œmv…ÅÐ4!vWæXXþЩʲz–scš�åøÂ‹õOV8°U„`Fˆ)ïÍ´j-Œ¶…õ�´½J&™Ì˜¶—RRÙTUÓ–¡vÁ�åøKµí%•�N›?Ìc™´O»a––N#ÓÑ`ŒÛ ô—W×k�š³…;[R[PV¨ Pú«d ™Øêëb9^o°´wšÚt -Zžwie"Æ8È_ÈÛëÅ44é˜Â£—3æøÙ|;6<àr�ÆÅ$«<�k55�š>Ö cL€ÄFØž”ð Îok¥N(±ÙEí§ˆ W[ÌfO‰¼ñÏb6ÇF¨ý}…„ÐÞ ÆÐÖQF™;ñ•³›gP•äk6ÁvGpýôG6› !A¾iqAý•¶NàÖS_câ9B�Xº{íy{'ÉdÒ¬Ôи¨@Že9ÖÂsœƒqbï óÇZ,ËÆEf¥†ÊdB´w/fÿ®1£`Z%ÔÁƒes FFdÚ~œ …<=�ö©iдjŒFËñ|¿Í¿"`hZ&ø*"C}ýUr‰Ä«¶ët§¡Æ|îÔ%¹Â—B%ò/><ôÚ?fØ;["‘ˆüUržç»ÒìöÖô­]9‚û±d�[ÏÆNÈä>@Q A„Bâ3…�{7ÔN_a["à˜ÓGª*šdR €˜V|ôöž’ü^NÑÔT¿ûz¿T¬¤(P!@!š¡|ÿôÒ–Æai”€ÛhÚøO?Ø¡�©B@(DÑ€D!Êb”>ÿȺâ|ý@×SÀ›¨½d|kÕO‹¢)ŠBAtjÄ]„�«JÌ2»Î �K&Uœ“´åŸo—ˆ|iJ„„E( éÔˆWwó„¢hJz,¯¸ðtkl|˜�ÛKLþKhªe×þëøþ½ç2@…(@ˆ` (ðõ§Ðí9ÉU“„@€ [ÌœnòŒÌEw¦'dÊ(a‹ 5惻KO» “ù2"†BSÈå”o¨‚)±¡Û³7`B0 k*DAá±™Ç&…3-wDÖ˜(ÿP©2�ñ ¤Ärg÷*p,õÄ ã:;,¥êŽ-4-bF&–ÊxMIDà€|@æO!AbÚb@ÿ¥&ÖÊh‘åÞIEND®B`‚dtkgui-6.7.46/docs/kernel/000077500000000000000000000000001522615413000153145ustar00rootroot00000000000000dtkgui-6.7.46/docs/kernel/dpalette.zh_CN.dox000066400000000000000000000110201522615413000206240ustar00rootroot00000000000000/*! @~chinese @file dpalette.h @ingroup palette @brief DPaletteæ��供了调色æ�¿ç›¸å…³æ“�作 @sa [qpalette](https://doc.qt.io/qt-6/qpalette.html) @class Dtk::Gui::DPalette @brief DPalette继承并且扩展了 QPalette ç±», æ��供了dtk特有的特性. @enum Dtk::Gui::DPalette::ColorType DPalette::ColorType 定义了 DPalette 颜色类型 @details | **é”®** | **值** | **å�«ä¹‰** | |:-----------------:|:-----:|:-------------------------------------------------:| | NoType | 0 | 无类型 | | ItemBackground | 1 | 列表项的背景色 | | TextTitle | 2 | 标题型文本的颜色 | | TextTips | 3 | æ��示性文本的颜色 | | TextWarning | 4 | 警告类型的文本颜色 | | TextLively | 5 | 活跃å¼�文本颜色(ä¸�å�—活动色影å“�) | | LightLively | 6 | 活跃å¼�按钮(recommend button)背景色中的亮色(ä¸�å�—活跃色影å“�) | | DarkLively | 7 | 活跃å¼�按钮(recommend button)背景色中的暗色,会从亮色æ¸�å�˜åˆ°æš—色(ä¸�å�—活跃色影å“�) | | FrameBorder | 8 | 控件边框颜色 | | PlaceholderText | 9 | å� ä½�类型的文本颜色,å�¯ç”¨äºŽè¾“入框å� ä½�内容等æ��示性文字 | | FrameShadowBorder | 10 | 用于跟阴影å� åŠ çš„è¾¹æ¡†é¢œè‰² | | ObviousBackground | 11 | 明显的背景色 | | NColorTypes | 12 | 无颜色类型 | @fn Dtk::Gui::DPalette::DPalette() @brief 构造一个 DPalette 对象 @fn Dtk::Gui::DPalette::DPalette(const DPalette &palette) @brief 构造一个 DPalette 对象 @param[in] palette è¦�å¤�制的 DPalette 对象 @fn Dtk::Gui::DPalette::DPalette(const QPalette &palette) @brief 构造一个 DPalette 对象 @param[in] palette è¦�å¤�制的 QPalette 对象 @fn const QColor Dtk::Gui::DPalette::clore(ColorGroup cg, ColorType ct) const @brief 获å�–指定颜色组和颜色类型的颜色 @param[in] cg 颜色组 @param[in] ct 颜色类型 @fn void Dtk::Gui::DPalette::brush(ColorGroup cg, ColorType ct, const QColor &color) @brief 设置指定颜色组和颜色类型的笔刷 @param[in] cg 颜色组 @param[in] ct 颜色类型 @param[in] color 颜色 @fn void Dtk::Gui::DPalette::setColor(ColorGroup cg, ColorType ct, const QColor &color) @brief 设置指定颜色组和颜色类型的颜色 @param[in] cg 颜色组 @param[in] ct 颜色类型 @param[in] color 颜色 @fn void Dtk::Gui::DPalette::setColor(ColorType ct, const QColor &color) @brief 设置指定颜色类型的颜色 @param[in] ct 颜色类型 @param[in] color 颜色 @fn void Dtk::Gui::DPalette::setBrush(ColorType ct, const QBrush &brush) @brief 设置指定颜色类型的笔刷 @param[in] ct 颜色类型 @param[in] brush 笔刷 @fn void Dtk::Gui::DPalette::setBrush(ColorGroup cg, ColorType ct, const QBrush &brush) @brief 设置指定颜色组和颜色类型的笔刷 @param[in] cg 颜色组 @param[in] ct 颜色类型 @param[in] brush 笔刷 @fn const QBrush & Dtk::Gui::DPalette::itemBackground() const @brief 获å�–列表项的背景色 @fn const QBrush & Dtk::Gui::DPalette::textTitle() const @brief 获å�–标题型文本的颜色 @fn const QBrush & Dtk::Gui::DPalette::textTips() const @brief 获å�–æ��示性文本的颜色 @fn const QBrush & Dtk::Gui::DPalette::textWarning() const @brief 获å�–警告类型的文本颜色 @fn const QBrush & Dtk::Gui::DPalette::textLively() const @brief 获å�–活跃å¼�文本颜色(ä¸�å�—活动色影å“�) @fn const QBrush & Dtk::Gui::DPalette::lightLively() const @brief 获å�–活跃å¼�按钮(recommend button)背景色中的亮色,会从暗色æ¸�å�˜åˆ°äº®è‰²ï¼ˆä¸�å�—活跃色影å“�) @fn const QBrush & Dtk::Gui::DPalette::darkLively() const @brief 获å�–活跃å¼�按钮(recommend button)背景色中的暗色,会从暗色æ¸�å�˜åˆ°äº®è‰²ï¼ˆä¸�å�—活跃色影å“�) @fn const QBrush & Dtk::Gui::DPalette::frameBorder() const @brief 获å�–边框颜色 @fn const QBrush & Dtk::Gui::DPalette::placeholderText() const @brief 获å�–å� ä½�符文本颜色 @fn const QBrush & Dtk::Gui::DPalette::frameShadowBorder() const @brief 获å�–阴影边框颜色 */ dtkgui-6.7.46/docs/kernel/index.zh_CN.md000066400000000000000000000002101522615413000177360ustar00rootroot00000000000000@page kernel kernel--dtkgui核心组件 # Dtk-Gui kernel TODO:添加组件说明 @defgroup palette @brief 调色æ�¿å·¥å…· @detailsdtkgui-6.7.46/docs/src/000077500000000000000000000000001522615413000146235ustar00rootroot00000000000000dtkgui-6.7.46/docs/src/dguiapplicationhelper.zh_CN.dox000066400000000000000000000047611522615413000227230ustar00rootroot00000000000000/*! @~chinese @file dguiapplicationhelper.h @class Dtk::Gui::DGuiApplicationHelper @ingroup dtkgui @brief DGuiApplicationHelperç±»æ��供了一个gui应用程åº�的应用帮助类,å�¯æ��ä¾›widgetå’Œdeclarativeçš„ 公共gui功能,例如调色æ�¿ã€�字体ã€�主题等功能。 @details @enum Dtk::Gui::DGuiApplicationHelper::SizeMode @brief 控件大å°�模å¼�枚举包å�« dtk支æŒ�的控件大å°�模å¼�ç§�ç±». | **值** | **å�«ä¹‰** | |:-----------:|:---------------------:| | NormalMode | 普通模å¼�,为默认模å¼� | | CompactMode | 紧凑模å¼� | @fn void DGuiApplicationHelper::newProcessInstance(qint64 pid, const QStringList &arguments) @brief 通知新进程的信æ�¯ã€‚ @details å�•例程åº�情况下,å°�试å�¯åŠ¨æ–°çš„ç¨‹åº�实例将触å�‘此信å�·ï¼Œä»¥ä¾¿èŽ·å�–所传入的å�‚数列表等信æ�¯ï¼Œæ�¥è¿›è¡Œè¿›ä¸€æ­¥å¤„ç�†ã€‚ @param pid 进程 ID. @param arguments å�¯åŠ¨è¿›ç¨‹æ—¶æ‰€ä¼ å…¥çš„å�‚数列表. @fn DGuiApplicationHelper::SizeMode DGuiApplicationHelper::sizeMode() const @brief 当å‰�应用的控件大å°�模å¼�。 @details - 若应用没有设置控件大å°�模å¼�,则跟éš�系统的控件大å°�模å¼� - 用户也å�¯ä»¥è®¾ç½®çŽ¯å¢ƒå�˜é‡� D_DTK_SIZEMODE æ�¥å½±å“�应用的大å°�模å¼�的支æŒ�,`D_DTK_SIZEMODE=1`为指定为普通模å¼�, 当应用没有显示设置控件大å°�模å¼�,则会采用普通模å¼�。 - 优先级为 `DGuiApplicationHelper::setSizeMode` > `D_DTK_SIZEMODE` > `System's SizeMode`。 @fn void DGuiApplicationHelper::setSizeMode(const DGuiApplicationHelper::SizeMode sizeMode) @brief 设置应用控件大å°�模å¼�,应用使用的为此模å¼�,ä¸�å†�å“�应系统的控件大å°�模å¼�。 @param sizeMode 需è¦�设置的控件大å°�模å¼�. @fn void DGuiApplicationHelper::resetSizeMode() @brief é‡�置设置应用控件大å°�模å¼�,跟éš�系统的控件大å°�模å¼�。 @fn static inline bool DGuiApplicationHelper::isCompactMode() @brief 当å‰�控件大å°�模å¼�是å�¦ä¸ºç´§å‡‘模å¼�。 @fn void DGuiApplicationHelper::applicationPaletteChanged() @brief 通知调色æ�¿å¯¹è±¡çš„æ”¹å�˜ã€‚ @sa windowPalette() @fn void DGuiApplicationHelper::sizeModeChanged(DGuiApplicationHelper::SizeMode sizeMode) @brief 通知控件大å°�模å¼�å�‘生改å�˜ã€‚ @fn static QStringList DGuiApplicationHelper::userManualPaths(const QString &appName) @brief 获å�–帮助手册已存在目录 @param appName 目标应用å��ç§° @detail 目录深度具体到appName层级,例:一个典型的目录路径为:/usr/share/deepin-manual/manual-assets/application/appName */ dtkgui-6.7.46/docs/src/dimagehandler.zh_CN.dox000066400000000000000000000263621522615413000211340ustar00rootroot00000000000000/*! @~chinese @file dimagehandler.h dimagehandler.h æ��供图åƒ�处ç�†ç±» DImageHandler @class Dtk::Gui::DImageHandler @brief DImageHandler æ��供图åƒ�处ç�†ï¼Œè¯»å�–ã€�ä¿�å­˜ã€�旋转ã€�滤镜等。 @details ## 概述 æ��供多ç§�æ ¼å¼�图片的读å�–ã€�ä¿�存,å…�许对部分格å¼�进行旋转。æ��供多ç§�滤镜ã€�é”�化ã€�二值化等图åƒ�处ç�†ç®—法。 通过 `DImageHandler::setFileName` 设置当å‰�处ç�†çš„图片文件路径,通过 `DImageHandler::readImage` å�–得图片数æ�®ï¼Œé€šè¿‡ `DImageHandler::thumbnail` å�–得图片缩略图。设置文件路径将ä¸�会立å�³åŠ è½½å›¾ç‰‡ï¼Œ 将在需è¦�图片数æ�®æ—¶è¯»å�–,当ä¸�需è¦�缓存数æ�®æ—¶ï¼Œå�¯é€šè¿‡ `DImageHandler::clearCache` 清除缓存数æ�®ã€‚ @note 拓展的图片格å¼�ä¾�èµ– FreeImage å’Œ LibRaw 公共库,DImageHandler 通过动æ€�加载的方å¼�è§£æž�公共库接å�£ã€‚ å�¯é€šè¿‡ DImageHandler::supportFormats() 获å�–当å‰�支æŒ�的图片格å¼�类型。 ## 编译 支æŒ�拓展的图片格å¼�,编译时会判断环境是å�¦å­˜åœ¨ä¾�赖包,安装 libfreeimage-dev å�Š libraw-dev , 设置编译选项 DTK_DISABLE_EX_IMAGE_FORMAT=OFF å�Žå°†å¼€å�¯æ‹“展图片格å¼�支æŒ�。 ä¸�å�ŒåŒ…构建环境默认策略ä¸�å�Œï¼Œåœ¨ **debian** å’Œ **linglong** 构建环境默认ä¾�èµ– libfreeimage-dev å�Š libraw-dev , 支æŒ�拓展图片格å¼�,其它环境需手动安装。 ## image-handler 工具示例 å�¯åœ¨ç¨‹åº�根目录 ./tools/image-handler 中查看 image-handler 工具项目。 image-handler 工具å�¯ç”¨äºŽæ��å�–图åƒ�ä¿¡æ�¯ã€�旋转图åƒ�ã€�设置图åƒ�滤镜等。 ```shell image-handler [options] [file...] ``` ### image-handler 选项 | **选项** | **æ��è¿°** | |---|---| | -h, --help | 显示工具帮助信æ�¯ | | -r, --rotate | æ ¹æ�®è®¾ç½®è§’度旋转图片,旋转角度需为 **90度** çš„å€�æ•° | | -o, --output | ä¿�存处ç�†å�Žçš„æ–‡ä»¶åˆ°æŒ‡å®šè·¯å¾„ | | -f | 为图片设置滤镜,å�¯é€‰å›¾ç‰‡æ»¤é•œåŒ…括 old, warm, cool, gray, anticolor, metal | | -l, --list | 列出所有图片的格å¼� | | -e | 列出所有图片的详细信æ�¯ï¼Œç»“å�ˆ **-l** 使用 | @fn Dtk::Gui::DImageHandler::DImageHandler(QObject *parent) @brief 构造 DImageHandler 实例,并指定父控件 @param[in] parent 作为实例的父控件 @fn Dtk::Gui::DImageHandler::~DImageHandler() @brief 销æ¯� DImageHandler 实例 @fn void Dtk::Gui::DImageHandler::setFileName(const QString &fileName) @brief 设置当å‰�处ç�†çš„图片文件路径 @param[in] fileName 图片文件路径 @fn QString Dtk::Gui::DImageHandler::fileName() const @brief 返回当å‰�处ç�†çš„图片文件路径 @return 图片文件路径 @fn QImage Dtk::Gui::DImageHandler::readImage() @brief 从设置的图片文件路径中读å�–图片 @details 从 fileName() 设置的图片文件中读å�–图片,若读å�–失败,将返回空图片实例, 错误信æ�¯é€šè¿‡ lastError() 获å�– @return 图片实例 @fn QImage Dtk::Gui::DImageHandler::thumbnail(const QSize &size, Qt::AspectRatioMode mode) @brief 获å�–当å‰�处ç�†å›¾ç‰‡æŒ‡å®šå¤§å°�的缩略图,å�¯è°ƒæ•´å®½é«˜æ¯”适é…�模å¼� @param[in] 缩略图大å°� @return 缩略图实例 @fn QString Dtk::Gui::DImageHandler::imageFormat() const @brief 返回当å‰�设置图片文件的格å¼�,若未设置文件路径,返回空字符串 @return 图片格å¼� @fn QSize Dtk::Gui::DImageHandler::imageSize() @brief 返回当å‰�处ç�†çš„图片尺寸,若未设置图片文件或加载失败,返回空图片尺寸 (-1, -1) @return 图片大å°� @fn QHash Dtk::Gui::DImageHandler::findAllMetaData() @brief 查询图片包å�«çš„æ‰€æœ‰å…ƒæ•°æ�®ï¼Œåœ¨åЍæ€�加载 FreeImage 库å�Žæœ‰æ•ˆ @return 图片信æ�¯è¡¨ @fn void Dtk::Gui::DImageHandler::clearCache() @brief 清空缓存数æ�®ï¼Œé‡Šæ”¾ç¼“存的图片和错误信æ�¯ @fn bool Dtk::Gui::DImageHandler::saveImage(const QString &fileName, const QString &format = QString()) @brief ä¿�存当å‰�处ç�†çš„图片至文件,å�¯æŒ‡å®šä¿�存的图片格å¼�, 若存在错误,将返回 false ,错误信æ�¯é€šè¿‡ lastError() 获å�– @param[in] fileName ä¿�存的文件路径 @param[in] format 指定ä¿�存图片格å¼�,默认为空,表示ä¿�æŒ�原格å¼� @return 是å�¦æˆ�功ä¿�存图片 @fn bool Dtk::Gui::DImageHandler::saveImage(const QImage &image, const QString &fileName, const QString &format) @brief ä¿�存图片至文件,å�¯æŒ‡å®šä¿�存的图片格å¼�, 若存在错误,将返回 false ,错误信æ�¯é€šè¿‡ lastError() 获å�– @param[in] image 图片实例 @param[in] fileName ä¿�存的文件路径 @param[in] format 指定ä¿�存图片格å¼�,默认为空,表示ä¿�æŒ�原格å¼� @return 是å�¦æˆ�功ä¿�存图片 @fn bool Dtk::Gui::DImageHandler::rotateImage(QImage &image, int angle) @brief 顺时针旋转图片,若存在错误,将返回 false ,错误信æ�¯é€šè¿‡ lastError() 获å�– @param[in,out] image 图片实例 @param[in] angle 图片旋转角度,必须以90度为å€�æ•° @return 是å�¦æˆ�功旋转图片 @fn bool Dtk::Gui::DImageHandler::rotateImageFile(const QString &fileName, int angle) @brief 顺时针旋转图片文件中的图片 @details 读å�– fileName 图片文件,顺时针旋转图片 angle 度,并将图片数æ�®å†™å›žæ–‡ä»¶ï¼Œ 若存在错误,将返回 false ,错误信æ�¯é€šè¿‡ lastError() 获å�– @param[in] fileName 图片文件路径 @param[in] angle 图片旋转角度,必须以90度为å€�æ•° @return 是å�¦æˆ�功旋转并ä¿�存图片文件 @fn bool Dtk::Gui::DImageHandler::isReadable() const @brief 返回当å‰�设置的图片文件是å�¦å�¯è¯»å�–,判断基于图片格å¼�,fileName() 为空时返回 false @return 是å�¦å�¯è¯»å�– @fn bool Dtk::Gui::DImageHandler::isWriteable() const @brief 返回当å‰�设置的图片文件是å�¦å�¯å†™å…¥ï¼Œåˆ¤æ–­åŸºäºŽå›¾ç‰‡æ ¼å¼�,fileName() 为空时返回 false @return 是å�¦å�¯å†™å…¥ @fn bool Dtk::Gui::DImageHandler::isRotatable() const @brief 返回当å‰�设置的图片文件是å�¦å�¯æ—‹è½¬ï¼Œåˆ¤æ–­åŸºäºŽå›¾ç‰‡æ ¼å¼�,fileName() 为空时返回 false @return 是å�¦å�¯æ—‹è½¬ @fn static QStringList Dtk::Gui::DImageHandler::supportFormats() @brief 返回当å‰�环境下 DImageHandler å�¯æ”¯æŒ�的图片格å¼�,å�¯åЍæ€�加载 FreeImage 库以支æŒ�更多图片格å¼� @return 支æŒ�的图片格å¼� @fn static QString Dtk::Gui::DImageHandler::detectImageFormat(const QString &fileName) @brief æ ¹æ�®æ–‡ä»¶å��ç§°å�Šæ–‡ä»¶å†…容检测图片格å¼� @param[in] fileName 图片文件路径 @return 图片格å¼� @fn QString Dtk::Gui::DImageHandler::lastError() const; @brief 返回最近一次错误的详细信æ�¯ @return 错误信æ�¯ @fn static QImage Dtk::Gui::DImageHandler::oldColorFilter(const QImage &img) @brief 为图片设置è€�照片滤镜并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::warmColorFilter(const QImage &img, int intensity = 30) @brief 为图片设置暖色滤镜并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @param[in] intensity 滤镜处ç�†å¼ºåº¦ï¼Œå�–值范围 -255 ~ 255 ,默认30 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::coolColorFilter(const QImage &img, int intensity = 30) @brief 为图片设置冷色滤镜并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @param[in] intensity 滤镜处ç�†å¼ºåº¦ï¼Œå�–值范围 -255 ~ 255 ,默认30 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::grayScaleColorFilter(const QImage &img) @brief 为图片设置ç�°è‰²æ»¤é•œå¹¶è¿”回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::antiColorFilter(const QImage &img) @brief 为图片设置å��色滤镜并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::metalColorFilter(const QImage &img) @brief 为图片设置金属风格滤镜并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::bilateralFilter(const QImage &img, double spatialDecay, double photometricStandardDeviation) @brief 对图片进行å�Œè¾¹æ»¤æ³¢å¤„ç�†ï¼Œå�¯ä¿�æŒ�边界并去除噪点,å�¯ç”¨äºŽç£¨çš®ç­‰å¤„ç�† @param[in] img 待处ç�†çš„图片实例 @param[in] spatialDecay 空间衰å‡�值,用于å�Œè¾¹æ»¤æ³¢çš„空域信æ�¯ï¼Œé»˜è®¤ 0.02 @param[in] photometricStandardDeviation 光度标准差值,用于å�Œè¾¹æ»¤æ³¢çš„值域信æ�¯, 默认 10 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::contourExtraction(const QImage &img) @brief æ��å�–图片轮廓 @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::binaryzation(const QImage &img) @brief 对图片进行二值化处ç�† @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::grayScale(const QImage &img) @brief å�–å¾—ç�°é˜¶å›¾ç‰‡ @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::laplaceSharpen(const QImage &img) @brief 拉普拉斯é”�化处ç�† @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::sobelEdgeDetector(const QImage &img) @brief sobel边缘检测处ç�†ï¼Œç”¨äºŽå›¾ç‰‡é”�化 @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::changeLightAndContrast(const QImage &img, int light = 100, int contrast = 150) @brief å�˜æ›´å›¾ç‰‡çš„亮度和对比度并返回处ç�†å›¾ç‰‡å®žä¾‹ @param[in] img 待处ç�†çš„图片实例 @param[in] light 调整图片亮度,å�–值范围 0 ~ 300 @param[in] constrase 调整图片对比度,å�–值范围 0 ~ 300 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::changeBrightness(const QImage &img, int brightness) @brief 调整图片亮度并返回处ç�†å›¾ç‰‡å®žä¾‹ï¼Œå�–值范围 -255 ~ 255 @param[in] img 待处ç�†çš„图片实例 @param[in] brightness 图片亮度 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::changeTransparency(const QImage &img, int transparency) @brief 调整图片é€�明度并返回处ç�†å›¾ç‰‡å®žä¾‹ï¼Œå�–值范围 0 ~ 255 @param[in] img 待处ç�†çš„图片实例 @param[in] transparency 图片é€�明度 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::changeStauration(const QImage &img, int saturation) @brief 调整图片饱和度并返回处ç�†å›¾ç‰‡å®žä¾‹ï¼Œå�–值范围 -100 ~ 100 @param[in] img 待处ç�†çš„图片实例 @param[in] saturation 图片饱和度 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::replacePointColor(const QImage &img, QColor oldColor, QColor newColor) @brief é��历图片所有åƒ�素点,替æ�¢å›¾ç‰‡åƒ�素点颜色 @param[in] img 待处ç�†çš„图片实例 @param[in] oldColor æ—§åƒ�素颜色 @param[in] newColor æ–°åƒ�素颜色 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::flipHorizontal(const QImage &img) @brief 水平翻转图片 @param[in] img 待处ç�†çš„图片实例 @return 处ç�†å®Œæˆ�的图片实例 @fn static QImage Dtk::Gui::DImageHandler::flipVertical(const QImage &img) @brief 垂直翻转图片 @param[in] img 待处ç�†çš„图片 @return 处ç�†å®Œæˆ�的图片实例 */dtkgui-6.7.46/docs/src/dplatformtheme.zh_CN.dox000066400000000000000000000005661522615413000213610ustar00rootroot00000000000000/*! @~chinese @file dplatformtheme.h @class Dtk::Gui::DPlatformTheme @ingroup dtkgui @brief DPlatformThemeç±»æ��供了一个应用程åº�的主题é…�置管ç�†ç±»,å�¯ä»¥åœ¨å¤–部控制应用的默认主题行为, 达到个性化主题的设置,所有的设置是实时å“�应的。 @property DPlatformTheme::sizeMode @brief 从é…�置中获å�–当å‰�控件大å°�模å¼� */ dtkgui-6.7.46/docs/util/000077500000000000000000000000001522615413000150115ustar00rootroot00000000000000dtkgui-6.7.46/docs/util/ddciicon.zh_CN.dox000066400000000000000000000367441522615413000203170ustar00rootroot00000000000000/*! @~chinese @file include/util/ddciicon.h @ingroup dci @brief DCI图标类 @class Dtk::Gui::DDciIconImage ddciicon.h @details 用于获å�– dci 图标æŸ�ç§�状æ€�的图片资æº�(ä½�图数æ�®ï¼‰ï¼Œå�Œæ—¶æ”¯æŒ�é�™æ€�图和动æ€�图,接å�£çš„设计类似于 QImageReader,一般通过调用 DDciIcon::image 构造此对象。与 DDciIcon é…�å�ˆä½¿ç”¨ï¼Œå…¶æ‰€æ”¯æŒ�的图片格å¼�与 DDciIcon::pixmap 接å�£ä¸€è‡´ï¼Œéƒ½å�–决于 Qt 图片æ�’件系统(å�³ QImageReader)所æ��供的能力。 @sa DDciIcon::image @fn Dtk::Gui::DDciIconImage::DDciIconImage() @details 构造一个空的对象。 @fn Dtk::Gui::DDciIconImage::DDciIconImage(const DDciIconImage &other) @details æ ¹æ�® other 对象构造一个新的 DDciIconImage 对象,这个新的对象将与 other 共享 DDciIconImagePrivate 对象。 @fn Dtk::Gui::DDciIconImage::operator=(const DDciIconImage &other) @details 对当å‰�对象进行赋值,这将导致此对象与 other 共享 DDciIconImagePrivate 对象。 @fn Dtk::Gui::DDciIconImage::operator=(DDciIconImage &&other) @details 对当å‰�对象进行赋值,这将导致此对象与 other 两者的 DDciIconImagePrivate 对象被交æ�¢ã€‚ @sa DDciIconImage::swap @fn Dtk::Gui::DDciIconImage::swap(DDciIconImage &other) @details 交æ�¢ä¸¤ä¸ªå¯¹è±¡çš„æ•°æ�®ï¼Œè¿™å°†å¯¼è‡´ä¸¤è€…çš„ DDciIconImagePrivate 对象被交æ�¢ã€‚ @fn Dtk::Gui::DDciIconImage::operator ==(const DDciIconImage &other) const @details 如果两个对象引用了相å�Œçš„ DDciIconImagePrivate æ•°æ�®å¯¹è±¡ï¼Œåˆ™è¿”回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::operator !=(const DDciIconImage &other) const @details 如果两个对象引用了ä¸�å�Œçš„ DDciIconImagePrivate æ•°æ�®å¯¹è±¡ï¼Œåˆ™è¿”回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::isNull() const @details 如果此对象为空,则返回 true,å�¦åˆ™è¿”回 false。当对象为空时,调用其它æˆ�员函数将获得一个无效的结果。 @fn Dtk::Gui::DDciIconImage::reset() @details é‡�置数æ�®çš„状æ€�,将清ç�†æ‰€æœ‰çš„内部缓存数æ�®ï¼Œå¹¶ä¸”é‡�置所有的状æ€�记录,与é‡�新调用 DDciIcon::image 获å�–一个新的对象å�Žçš„状æ€�相å�Œã€‚对于动画图片而言,这会导致 DDciIconImage::atBegin å�˜æˆ� true,å�³åŠ¨ç”»å°†ä»Žç¬¬ä¸€å¸§é‡�新开始。 @fn Dtk::Gui::DDciIconImage::toImage(const DDciIconPalette &palette) const @details 对于é�™æ€�图片,将读å�–图片数æ�®ï¼Œå¹¶åŠ è½½ä¸º QImage 对象返回。对于动æ€�图片,将返回当å‰�帧的ä½�图数æ�®ï¼Œä¸”多次调用时ä¸�会é‡�新加载,将返回缓存的 QImage 对象,å�¦å¤–需è¦�注æ„�的时,与 QImageReader::read çš„ä¸�å�Œï¼Œåœ¨è°ƒç”¨æ­¤å‡½æ•°è¯»å�–当å‰�帧å�Žï¼Œå¹¶ä¸�会自动跳转到下一帧,å�³åœ¨æœªè°ƒç”¨ DDciIconImage::jumpToNextImage 时,多次调用此函数将返回å�Œä¸€å¸§ã€‚ @param[in] palette 如果此图片支æŒ�指定调色æ�¿ï¼Œåˆ™å°†æ ¹æ�®ä¼ å…¥çš„ DDciIconPalette 中指定的颜色对图片进行加工。详情请å�‚è§� DSG 标准中的 DCI 图片格å¼�设计。 @sa DDciIconImage::hasPalette DDciIconImage::paint @fn Dtk::Gui::DDciIconImage::paint(QPainter *painter, const QRectF &rect, Qt::Alignment alignment, const DDciIconPalette &palette) const @details 将图片的ä½�图数æ�®é€šè¿‡ä¼ å…¥çš„画笔进行绘制。 @param[in] painter 指定画笔对象。 @param[in] rect 指定绘制区域,此区域相对于画笔所对应的 QPainter::paintDevice(),如果此区域的宽度比图片的宽度å°�,则会在绘制时将图片缩å°�到此区域的大å°�,å��之则ä¿�æŒ�图片自身大å°�,而ä¸�会知é�“图片被放大。 @param[in] alignment 指定绘制时图片相对于 rect 所指定区域的ä½�置,å�³å½“图片宽度å°�于 rect 所指定的宽度时,将根æ�®æ­¤å�‚数决定图片的显示ä½�置。 @param[in] palette 如果此图片支æŒ�指定调色æ�¿ï¼Œåˆ™å°†æ ¹æ�®ä¼ å…¥çš„ DDciIconPalette 中指定的颜色对图片进行加工。详情请å�‚è§� DSG 标准中的 DCI 图片格å¼�设计。 @sa DDciIconImage::toImage @fn Dtk::Gui::DDciIconImage::hasPalette() const @details 如果此图片支æŒ�指定调色æ�¿ï¼Œåˆ™è¿”回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::supportsAnimation() const @details 如果此图片支æŒ�动画,则返回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::atBegin() const @details 如果此图片支æŒ�动画且动画处于第一帧,则返回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::atEnd() const @details 如果此图片支æŒ�动画且动画处于最å�Žä¸€å¸§ï¼Œåˆ™è¿”回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::jumpToNextImage() @details 将动画跳转到下一帧,如果此图片支æŒ�动画且当å‰�ä¸�是最å�Žä¸€å¸§ï¼Œåˆ™è¿”回 true,å�¦åˆ™è¿”回 false。 @fn Dtk::Gui::DDciIconImage::loopCount() const @details 返回动画的轮播次数,如果此图片ä¸�支æŒ�动画,则返回值无效。如果返回值为 -1,则表明此动画需è¦�æ— é™�循环播放。 @fn Dtk::Gui::DDciIconImage::maxImageCount() const @details 返回动画的最大帧数,如果当å‰�图片有多层且æ¯�一层都支æŒ�动画,则是所有动画帧数的累加,因此多个动画的播放时间会å�¯èƒ½ä¼šæœ‰é‡�å� çš„帧,所以无法确ä¿�播放此图片时一定能显示这么多帧,动画是å�¦ç»“æ�Ÿéœ€è¦�以 DDciIconImage::atEnd 的返回结果为准。如果此图片ä¸�支æŒ�动画,则返回值无效。 @fn Dtk::Gui::DDciIconImage::currentImageDuration() const @details 返回当å‰�动画帧的æŒ�续时间,å�•ä½�为毫秒。如果此图片ä¸�支æŒ�动画,则返回值无效。 @fn Dtk::Gui::DDciIconImage::currentImageNumber() const @details 返回动画已ç»�播放到的帧的åº�å�·ï¼Œæ­¤å€¼ä¸€å®šå°�于 DDciIconImage::maxImageCount - 1。如果此图片ä¸�支æŒ�动画,则返回值无效。 @class Dtk::Gui::DDciIcon ddciicon.h @details 如果需è¦�详细dci相关介ç»�以å�Šè§„范文档, å�¯ä»¥å�‚è§�[dci文件图标规范](https://github.com/linuxdeepin/deepin-specifications/blob/master/unstable/%E5%9B%BE%E6%A0%87%E6%96%87%E4%BB%B6%E8%A7%84%E8%8C%83.md) ## DDciIcon示例 项目目录结构在å�Œä¸€ç›®å½•下 ## CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.1.0) # 指定cmake最低版本 project(ddciicon-example VERSION 1.0.0 LANGUAGES CXX) # 指定项目å��ç§°, 版本, 语言 cxx就是c++ set(CMAKE_CXX_STANDARD 11) # 指定c++标准 set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定c++标准è¦�求,至少为11以上 set(CMAKE_AUTOMOC ON) # 支æŒ�qt moc set(CMAKE_AUTORCC ON) # support qt resource file # 支æŒ�qt资æº�文件 set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 支æŒ� clangd if (CMAKE_VERSION VERSION_LESS "3.7.0") # 如果cmake版本å°�于3.7.0 set(CMAKE_INCLUDE_CURRENT_DIR ON) # 设置包å�«å½“å‰�目录 endif() find_package(Qt5 REQUIRED COMPONENTS Core) # 寻找Qt5组件Core find_package(Qt5 REQUIRED COMPONENTS Gui) # 寻找Qt5组件Core find_package(Qt5 REQUIRED COMPONENTS Widgets) # 寻找Qt5组件Widgets find_package(DtkCore REQUIRED) # 寻找Dtk组件Core find_package(Dtk REQUIRED COMPONENTS Gui) # 寻找Dtk组件Gui find_package(Dtk REQUIRED COMPONENTS Widget) # 寻找Dtk组件Widget add_executable(${PROJECT_NAME} # 生æˆ�å�¯æ‰§è¡Œæ–‡ä»¶ main.cpp qml.qrc ) target_link_libraries(${PROJECT_NAME} PRIVATE # 添加需è¦�链接的共享库 Qt5::Core Qt5::Gui Qt5::Widgets Dtk::Core dtkgui dtkwidget ) ``` ## main.cpp ```cpp #include #include #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE int main(int argc, char *argv[]) { DApplication a(argc, argv); DMainWindow win; QWidget w; QFormLayout* layout = new QFormLayout(&w); // fromTheme表示从图标主题中寻找资æº�。 DDciIcon dci = DDciIcon::fromTheme("select_indicator"); auto icon = dci.matchIcon(0, DDciIcon::Light, DDciIcon::Hover); qDebug() << "DCI图标的实际大å°�" << dci.actualSize(icon); // 定义一个函数,传入DIconButton,以å�Šæ��示信æ�¯ auto addBtnRow = [&](DIconButton *iconBtn, const QString name){ iconBtn->setIconSize(QSize(32,32)); QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->addWidget(iconBtn); QLabel *btnLabel = new QLabel(name); hlayout->addWidget(btnLabel); return hlayout; }; // å°†DDciIconä¼ å…¥DIconButton DIconButton *iconBtn1 = new DIconButton(dci); layout->addRow(addBtnRow(iconBtn1, "icon button")); DIconButton *iconBtn2 = new DIconButton(dci); iconBtn2->setDisabled(true); layout->addRow(addBtnRow(iconBtn2, "disabled state")); DIconButton *iconBtn3 = new DIconButton(dci); iconBtn3->setDown(true); layout->addRow(addBtnRow(iconBtn3, "pressed state")); win.setCentralWidget(&w); win.resize(200,100); win.show(); Dtk::Widget::moveToCenter(&win); return a.exec(); } ``` ## qml.qrc ```xml select_indicator.dci ``` ## select_indicator.dci 下载dci-demo解压获å�–,这是个用qml编写的例å­�,使用DDciIconæ›´ç�µæ´» [dci-demo](https://github.com/linuxdeepin/deepin-specifications/blob/master/unstable/dci-demo.zip) 编译和è¿�行程åº� ```bash cmake -B build cmake --build build ./build/ddciicon-example ``` 程åº�è¿�行效果如下: ![ddciicon-example](/docs/images/ddciicon-example1.jpg) @enum Dtk::Gui::DDciIcon::Mode @brief DCI图标模å¼� @details | é”® | 值 | |:--------:|:---:| | Normal | 0 | | Disabled | 1 | | Hover | 2 | | Pressed | 3 | @enum Dtk::Gui::DDciIcon::Theme @brief DCI图标主题 @details | é”® | 值 | |:-----:|:---:| | Light | 0 | | Dark | 1 | @enum Dtk::Gui::DDciIcon::IconAttribute @brief DCI图标属性 @details | é”® | 值 | |:-----:|:---:| | HasPalette | 0x001 | 这个属性为了获å�–dci图标的图层是å�¦åŒ…å�«è°ƒè‰²æ�¿é¢œè‰²è°ƒæ•´, 比如æŸ�一个图层的图片的需è¦�用高亮色的填充就是 HasPalette, 这个高亮色还å�¯ä»¥è°ƒæ•´äº®åº¦é¥±å’Œåº¦rgbaç­‰å�‚æ•° @enum Dtk::Gui::DDciIcon::IconMatchedFlag @brief DCI图标匹é…�å�‚æ•° @var DDciIcon::None @brief 空,无å�«ä¹‰ @var DDciIcon::DontFallbackMode @brief 在查找图片资æº�时,如果指定的 mode ä¸�存在,则ç¦�止回退,直接当作查找ä¸�到处ç�† @var DDciIcon::RegardPaddingsAsSize @brief 将图层中æ�ºå¸¦çš„ paddings 属性算作图层大å°�的一部分,这会影å“�图片匹é…�时的大å°�判断 @fn Dtk::Gui::DDciIcon::DDciIcon() @brief 构造函数 @fn Dtk::Gui::DDciIcon::DDciIcon(const DCORE_NAMESPACE::DDciFile *dciFile) @brief 指定DCI文件的构造函数 @fn Dtk::Gui::DDciIcon(const QString &fileName) @brief 指定DCI文件å��的构造函数 @fn Dtk::Gui::DDciIcon::DDciIcon(const QByteArray &data) @brief 指定DCI文件数æ�®çš„æž„造函数 @fn Dtk::Gui::DDciIcon::DDciIcon(const DDciIcon &other) @brief æ‹·è´�构造函数,é‡�载赋值è¿�算符 @fn Dtk::Gui::DDciIcon::swap(DDciIcon &other) @brief 交æ�¢ä¸¤ä¸ªDDciIcon对象 @fn bool Dtk::Gui::DDciIcon::isNull() const @brief 判断DCI图标是å�¦ä¸ºç©º @fn DDciIconMatchResult Dtk::Gui::DDciIcon::matchIcon(int size, Theme theme, Mode mode, IconMatchedFlags flags = None) const @brief 获å�–DCI图标匹é…�元信æ�¯, 元信æ�¯ä»…能作为传入å�‚数使用 @param[in] size 图标大å°� @param[in] theme 图标主题 @param[in] mode 图标模å¼� @param[in] flags 图标匹é…�标志 @fn int Dtk::Gui::DDciIcon::actualSize(DDciIconMatchResult result) const @brief 获å�–DCI图标实际大å°� @param[in] result DCI图标匹é…�结果 @fn int Dtk::Gui::DDciIcon::actualSize(int size, Theme theme, Mode mode =Normal) const @brief 获å�–DCI图标实际大å°� @details 该函数会根æ�®ä¼ å…¥çš„å�‚数获å�–DCI图标匹é…�结果,ç„¶å�Žè°ƒç”¨actualSize(DDciIconMatchResult result)函数获å�–DCI图标实际大å°� @sa DDciIcon::actualSize(DDciIconMatchResult result) @fn QList Dtk::Gui::DDciIcon::availableSizes(Theme theme, Mode mode=Normal) const @brief 获å�–DCI图标å�¯ç”¨å¤§å°�列表 @param[in] theme 图标主题 @param[in] mode 图标模å¼�,默认为Normal @fn bool Dtk::Gui::DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr) @brief 判断DCI图标是å�¦æ”¯æŒ�指定属性 @param[in] result DCI图标匹é…�结果 @param[in] attr 图标属性 @fn QPixmap Dtk::Gui::DDciIcon::pixmap(qreal devicePixelRatio, int iconSize, Theme theme, Mode mode = Normal,const DDciIconPalette &palette = DDciIconPalette()) const @brief 获å�–DCI图标的QPixmap @param[in] devicePixelRatio 设备åƒ�素比 @param[in] iconSize 图标大å°� @param[in] theme 图标主题 @param[in] mode 图标模å¼�, 默认为Normal @param[in] palette 图标调色æ�¿,默认为无(空)调色æ�¿ @fn QPixmap Dtk::Gui::DDciIcon::pixmap(qreal devicePixelRatio, int iconSize, DDciIconMatchResult result, const DDciIconPalette &palette = DDciIconPalette()) const @brief 获å�–DCI图标的QPixmap @param[in] devicePixelRatio 设备åƒ�素比 @param[in] iconSize 图标大å°� @param[in] result DCI图标匹é…�结果 @param[in] palette 图标调色æ�¿, 默认为无(空)调色æ�¿ @fn void Dtk::Gui::DDciIcon::paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, Theme theme, Mode mode = Normal, Qt::Alignment alignment = Qt::AlignCenter, const DDciIconPalette &palette = DDciIconPalette()) const @brief 绘制DCI图标 @param[in] painter QPainter对象 @param[in] rect 绘制区域 @param[in] devicePixelRatio 设备åƒ�素比 @param[in] theme 图标主题 @param[in] mode 图标模å¼�, 默认为Normal @param[in] alignment 对é½�æ–¹å¼�, 默认为Qt::AlignCenter @param[in] palette 图标调色æ�¿, 默认为无(空)调色æ�¿ @fn void Dtk::Gui::DDciIcon::paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, DDciIconMatchResult result, Qt::Alignment alignment = Qt::AlignCenter, const DDciIconPalette &palette = DDciIconPalette()) const @brief 绘制DCI图标 @param[in] painter QPainter对象 @param[in] rect 绘制区域 @param[in] devicePixelRatio 设备åƒ�素比 @param[in] result DCI图标匹é…�结果 @param[in] alignment 对é½�æ–¹å¼�, 默认为Qt::AlignCenter @param[in] palette 图标调色æ�¿, 默认为无(空)调色æ�¿ @fn Dtk::Gui::DDciIcon::image(DDciIconMatchResult result, int size, qreal devicePixelRatio) const @details 构造一个 DDciIconImage 对象 @param[in] result 匹é…�到的图片结果,将根æ�®æ­¤åŒ¹é…�结果查找对应的图片数æ�®ã€‚ @param[in] size 期望获å�–到的图片大å°�,将根æ�®æ­¤å¤§å°�寻找最为接近的图片资æº�,当图片大å°�与传入的大å°�ä¸�一致时,将优先返回一个ç¨�大的图片。 @param[in] devicePixelRatio 期望获å�–到的图片的缩放比例,将根æ�®å…¶å¯»æ‰¾æœ€ä¸ºæŽ¥è¿‘的图片资æº�,当无法找到指定比例的图片时,将优先返回一个ç¨�大比例的图片。 @sa DDciIcon::matchIcon @fn static DDciIcon Dtk::Gui::DDciIcon::fromTheme(const QString &name) @brief 从dci图标主题(包括内置dci图标资æº�)中获å�–图标å��字为name的图标 @param[in] name DCI图标å��ç§° @fn static DDciIcon Dtk::Gui::DDciIcon::fromTheme (const QString &name, const DDciIcon &fallback) @brief 从dci图标主题(包括内置dci图标资æº�)中获å�–图标å��字为name的图标 @param[in] name DCI图标å��ç§° @param[in] fallback 当图标å��为 name 的图标找ä¸�到时, fallback 到 fallback 的这个dci图标 */ dtkgui-6.7.46/docs/util/ddciiconpalette.zh_CN.dox000066400000000000000000000056441522615413000216710ustar00rootroot00000000000000/*! @~chinese @file include/util/ddciiconpalette.h @ingroup dci @brief DCI图标调色æ�¿ @class Dtk::Gui::DDciIconPalette ddciiconpalette.h @brief DCI图标调色æ�¿ @fn Dtk::Gui::DDciIconPalette::DDciIconPalette (QColor foreground=QColor::Invalid, QColor background=QColor::Invalid, QColor highlight=QColor::Invalid, QColor highlightForeground=QColor::Invalid) @brief 构造函数 @param[in] foreground å‰�景色, 默认值为无效色 @param[in] background 背景色, 默认值为无效色 @param[in] highlight 高亮色, 默认值为无效色 @param[in] highlightForeground 高亮å‰�景色, 默认值为无效色 @property Dtk::Gui::DDciIconPalette::foreground() @brief foreground()属性 @sa READ方法: QColor Dtk::Gui::DDciIconPalette::foreground() @sa WRITE方法: void Dtk::Gui::DDciIconPalette::setForeground(const QColor &foreground) @fn QColor Dtk::Gui::DDciIconPalette::foreground() const @brief 返回å‰�景色 @sa DDciIconPalette::foreground @fn void Dtk::Gui::DDciIconPalette::setForeground(const QColor &foreground) @brief 设置å‰�景色 @sa DDciIconPalette::foreground @property Dtk::Gui::DDciIconPalette::background @brief background()属性 @sa READ方法: QColor Dtk::Gui::DDciIconPalette::background() @sa WRITE方法: void Dtk::Gui::DDciIconPalette::setBackground(const QColor &background) @fn QColor Dtk::Gui::DDciIconPalette::background() const @brief 返回背景色 @sa DDciIconPalette::background @fn void Dtk::Gui::DDciIconPalette::setBackground(const QColor &background) @brief 设置背景色 @sa DDciIconPalette::background @property Dtk::Gui::DDciIconPalette::highlightForeground @brief highlightForeground()属性 @sa READ方法: QColor Dtk::Gui::DDciIconPalette::highlightForeground() @sa WRITE方法: void Dtk::Gui::DDciIconPalette::setHighlightForeground(const QColor &highlightForeground) @fn QColor Dtk::Gui::DDciIconPalette::highlightForeground() const @brief 返回高亮å‰�景色 @sa DDciIconPalette::highlightForeground @fn void Dtk::Gui::DDciIconPalette::setHighlightForeground(const QColor &highlightForeground) @brief 设置高亮å‰�景色 @sa DDciIconPalette::highlightForeground @property Dtk::Gui::DDciIconPalette::highlight @brief highlight()属性 @sa READ方法: QColor Dtk::Gui::DDciIconPalette::highlight() @sa WRITE方法: void Dtk::Gui::DDciIconPalette::setHighlight() @fn QColor Dtk::Gui::DDciIconPalette::highlight() const @brief 返回高亮色 @sa DDciIconPalette::highlight @fn void Dtk::Gui::DDciIconPalette::setHighlight() @brief 设置高亮色 @sa DDciIconPalette::highlight @fn static QString Dtk::Gui::DDciIconPalette::convertToString(const DDciIconPalette &palette) @brief å°†DDciIconPalette转æ�¢ä¸ºå­—符串 @fn static DDciIconPalette Dtk::Gui::DDciIconPalette::convertFromString(const QString &data) @brief 将字符串转æ�¢ä¸ºDDciIconPalette @fn static DDciIconPalette Dtk::Gui::DDciIconPalette::fromQPalette(const QPalette &pa) @brief å°†QPalette转æ�¢ä¸ºDDciIconPalette @sa QPalette */ dtkgui-6.7.46/docs/util/ddciiconplayer.zh_CN.dox000066400000000000000000000300211522615413000215120ustar00rootroot00000000000000/*! @~chinese @file include/util/ddciiconplayer.h @ingroup dci @brief DCI 图标播放工具 @class Dtk::Gui::DDciIconImagePlayer ddciiconplayer.h @details 用于 DDciIconImage 的动画播放,功能设计类似于 QMovie。支æŒ�æ— ç¼�顺åº�播放播放多个图片ã€�倒åº�播放等高级功能。 @enum Dtk::Gui::DDciIconImagePlayer::State @brief 播放状æ€� @var DDciIconImagePlayer::NotRunning @brief 未播放动画 @var DDciIconImagePlayer::WaitingRead @brief 正在播放动画,且等待读å�–当å‰�帧 @var DDciIconImagePlayer::Running @brief 正在播放动画,此时处于等待下一帧到æ�¥çš„状æ€� @enum Dtk::Gui::DDciIconImagePlayer::Flag @brief 播放å�‚æ•° @details 缓存的帧被判断为无效时将会被自动清ç�†ï¼Œå¦‚调用 DDciIconImagePlayer::setImage 改å�˜äº†è¦�播放的图片资æº�。 @var DDciIconImagePlayer::Continue @brief 接ç�€ä¸Šä¸€æ¬¡åŠ¨ç”»å�œæ­¢æ—¶çš„状æ€�继续播放,一般会é…�å�ˆ InvertedOrder å�Œæ—¶ä½¿ç”¨ @var DDciIconImagePlayer::CacheAll @brief 缓存本次播放中的所有动画帧 @var DDciIconImagePlayer::InvertedOrder @brief 倒åº�播放 @var DDciIconImagePlayer::IgnoreLastImageLoop @brief 忽略最å�Žä¸€ä¸ªå›¾ç‰‡çš„动画循环次数,å�³æ— è®º DDciIconImage::loopCount 的值是什么,动画都å�ªæ’­æ”¾ä¸€æ¬¡ @var DDciIconImagePlayer::AllowNonLastImageLoop @brief å…�许é�žæœ€å�Žä¸€ä¸ªå›¾ç‰‡å¾ªçŽ¯æ’­æ”¾ï¼Œé»˜è®¤æ—¶ä¸�å…�许,以确ä¿�所有图片都有机会被播放,é�¿å…�动画在å‰�é�¢çš„图片中无é™�循环进行播放 @var DDciIconImagePlayer::ClearCacheOnStop @brief 在动画å�œæ­¢æ—¶æ¸…ç�†ç¼“存的帧,无论动画是播放完æˆ�时的自动å�œæ­¢è¿˜æ˜¯è¢«åЍå�œæ­¢ @fn Dtk::Gui::DDciIconImagePlayer::DDciIconImagePlayer(QObject *parent) @details 构造此对象。 @param[in] parent 指定此 QObject 对象的父对象 @fn Dtk::Gui::DDciIconImagePlayer::setImages(const QVector &images) @details 指定待播放的图片åº�列,如果当å‰�的状æ€�ä¸�是 NotRunning,并且与上一次指定的图片åº�列ä¸�å�Œï¼Œåˆ™å�œæ­¢åŠ¨ç”»ã€‚ @param[in] images 图片åº�列,当为多个时,将无ç¼�顺åº�播放所有图片。 @fn Dtk::Gui::DDciIconImagePlayer::images() const @details 返回当å‰�已指定的图片åº�列。 @fn Dtk::Gui::DDciIconImagePlayer::currentImage() const @details 返回当å‰�正在播放的图片对象,如果当å‰�的状æ€�是 NotRunning,则会返回一个空的 DDciIconImage。 @fn Dtk::Gui::DDciIconImagePlayer::currentLoopForever() const @details 如果当å‰�正在播放的图片陷入了无é™�循环,则返回 true,å�¦åˆ™è¿”回 false。 @sa DDciIconImagePlayer::Flag::IgnoreLastImageLoop DDciIconImagePlayer::Flag::AllowNonLastImageLoop @fn Dtk::Gui::DDciIconImagePlayer::setPalette(const DDciIconPalette &palette) @details 指定读å�–动画帧时所使用的调色æ�¿ï¼Œå¦‚果图片支æŒ�此功能,则能控制获å�–到的图片的æŸ�些颜色。如果设置æˆ�功,并且当å‰�的状æ€�是 NotRunning,则会立å�³æ¸…ç�†ç¼“存帧,å�¦åˆ™ä¼šåœ¨åŠ¨ç”»å�œæ­¢æ—¶æ¸…ç�†ç¼“存帧。 @param[out] 如果新的 DDciIconPalette 与当å‰�çš„ DDciIconPalette 相å�Œï¼Œåˆ™è¿”回 false,å�¦åˆ™è¿”回 true。 @sa DDciIconImagePlayer::palette @fn Dtk::Gui::DDciIconImagePlayer::palette() const @details 返回当å‰�已指定的调色æ�¿ï¼Œå¦‚果未设置过调色æ�¿ï¼Œåˆ™è¿”回一个空的 DDciIconPalette。 @sa DDciIconImagePlayer::setPalette @fn Dtk::Gui::DDciIconImagePlayer::setLoopCount(int count) @details 指定动画的循环次数,当从调用 DDciIconImagePlayer::start 到收到 DDciIconImagePlayer::finished ä¿¡å�·ä¸ºä¸€æ¬¡å¾ªçŽ¯ï¼Œé™¤é�žè°ƒç”¨ DDciIconImagePlayer::stop,å�¦åˆ™ä¸�会终止此循环。å�¦å¤–,需è¦�注æ„�的是,此循环与 DDciIconImage::loopCount 无关,他们相互独立,且会å� åŠ ç”Ÿæ•ˆã€‚ @sa DDciIconImagePlayer::loopCount @fn Dtk::Gui::DDciIconImagePlayer::loopCount() const @details 返回动画循环次数。 @sa DDciIconImagePlayer::setLoopCount @fn Dtk::Gui::DDciIconImagePlayer::abortLoop() const @details 终止本次播放中的所有动画循环,å�³å�Žç»­çš„动画都仅播放一é��,这会导致忽略 DDciIconImage::loopCount å’Œ DDciIconImagePlayer::loopCount。 @fn Dtk::Gui::DDciIconImagePlayer::readImage() @details 读å�–当å‰�动画帧,这是一个“生产者-消费者â€�模型,å�ªæœ‰å½“状æ€�为 WaitingRead æ—¶æ‰�能读å�–,且æ¯�一帧å�ªèƒ½è¯»å�–一次。 @sa DDciIconImagePlayer::updated @fn Dtk::Gui::DDciIconImagePlayer::state() const @details 返回当å‰�的状æ€�。 @sa DDciIconImagePlayer::stateChanged @fn Dtk::Gui::DDciIconImagePlayer::clearCache() @details ç«‹å�³æ¸…ç�†æ‰€æœ‰çš„缓存帧。 @fn Dtk::Gui::DDciIconImagePlayer::start(float speed, DDciIconImagePlayer::Flags flags) @details ç«‹å�³å�¯åŠ¨åŠ¨ç”»ï¼Œåº”å½“åœ¨æ­¤ä¹‹å‰�调用 DDciIconImagePlayer::setImages。如果å�¯åЍæˆ�功,将å�‘é€� started ä¿¡å�·ã€‚在å�¯åЍå�Žï¼Œä¼šæ ¹æ�®æ¯�一帧的间隔自动触å�‘ updated ä¿¡å�·ï¼Œä»¥é€šçŸ¥ä½¿ç”¨æ–¹åœ¨å�ˆé€‚的时候显示新的帧。在动画播放完æˆ�å�Žï¼Œå°†å�‘é€� finished ä¿¡å�·ï¼Œåœ¨åŠ¨ç”»æœªæ’­æ”¾ç»“æ�Ÿå‰�调用了 stop 主动结æ�ŸåŠ¨ç”»åˆ™ä¸�会å�‘é€�ä¿¡å�·ã€‚ @param[in] speed 本次动画的播放速度,其表示的是å€�速,值越大动画播放的越快。设置为 0 时与设置为 1.0 等价。 @param[in] flags 控制本次动画播放时的一些行为。 @param[out] 如果动画å�¯åЍæˆ�功则返回 true,å�¦åˆ™è¿”回 false。动画å�¯åŠ¨å¤±è´¥çš„åŽŸå› ä¸€èˆ¬æ˜¯å› ä¸ºæ­¤æ—¶å·²ç»�在播放动画ã€�没有设置任何图片或所有图片都ä¸�支æŒ�动画。 @sa DDciIconImagePlayer::started DDciIconImagePlayer::updated DDciIconImagePlayer::readImage DDciIconImagePlayer::finished DDciIconImagePlayer::stateChanged @fn Dtk::Gui::DDciIconImagePlayer::stop() @details ç«‹å�³å�œæ­¢å½“å‰�动画的播放。这ä¸�会å�‘é€� finished ä¿¡å�·ã€‚ @fn Dtk::Gui::DDciIconImagePlayer::started() @details 通知动画已开始播放。 @fn Dtk::Gui::DDciIconImagePlayer::updated() @details 通知动画的当å‰�帧已ç»�å�‘生å�˜åŒ–,在收到此信å�·å�Žéœ€è¦�ç«‹å�³è°ƒç”¨ readImage,å�¦åˆ™åŠ¨ç”»ä¼šè¢«æš‚å�œï¼Œä¸�会自动到下一帧。 @sa DDciIconImagePlayer::readImage @fn Dtk::Gui::DDciIconImagePlayer::finished() @details 在本次动画播放结æ�Ÿæ—¶å�‘é€�ä¿¡å�·é€šçŸ¥ã€‚因为调用 DDciIconImagePlayer::stop 导致的动画å�œæ­¢ä¸�会触å�‘此信å�·ã€‚ @sa DDciIconImagePlayer::start @fn Dtk::Gui::DDciIconImagePlayer::stateChanged() @details 在状æ€�改å�˜æ—¶å�‘é€�ä¿¡å�·é€šçŸ¥ã€‚ @sa DDciIconImagePlayer::state @class Dtk::Gui::DDciIconPlayer ddciiconplayer.h @details 实现根æ�® DDciIcon::Mode çš„å�˜åŒ–,自动化计算è¦�显示的图标内容,支æŒ�动æ€�图标,在 DDciIcon::Mode 被设置时通过 updated ä¿¡å�·é€šçŸ¥æŽ§ä»¶ç»˜åˆ¶æ–°çš„内容。对于动æ€�图标的动画播放先å�Žé¡ºåº�ã€�播放速度等规则é�µå®ˆ DSG 规范中所æ��出的 DCI 图标文件标准。有几æ�¡ç‰¹æ€§ï¼š 1. 支æŒ�动画的倒åº�播放,如从 Hover 状æ€�å�˜ä¸º Normal 时,å�¯ä»¥å€’åº�播放 Hover 状æ€�所对应的 DDciIconImage。此功能ä¾�赖于 DDciIconImagePlayer 的实现。 2. 支æŒ�动画无ç¼�衔接播放,如从 Normal 状æ€�å�˜åŒ–为 Hover 时,在播放 Hover 动画的途中å�ˆå�˜ä¸º Pressed 状æ€�,则ä¸�会立å�³å°† Hover 的动画打断,将把 Pressed 动画在当å‰�动画播放接å�—å�Žè‡ªåŠ¨æ’­æ”¾ã€‚ 3. 支æŒ�动画记忆播放,如从 Normal 状æ€�å�˜åŒ–为 Hover 时,在播放 Hover 动画的途中å�˜å›žäº† Normal 状æ€�,则会从当å‰�å·²ç»�播放到的这一帧开始倒åº�播放 Hover 动画。 @enum Dtk::Gui::DDciIconPlayer::State @brief 工作状æ€� @var DDciIconPlayer::Idle @brief 处于空闲状æ€�,一般表示此时未播放动画 @var DDciIconPlayer::Busy @brief 处于忙碌状æ€�,此时å�¯èƒ½æ­£åœ¨æ’­æ”¾åŠ¨ç”» @fn Dtk::Gui::DDciIconPlayer::DDciIconPlayer @details 构造此对象。 @param[in] parent 指定此 QObject 对象的父对象 @fn Dtk::Gui::DDciIconPlayer::state() const @details 返回当å‰�的状æ€�。 @sa DDciIconPlayer::State @fn Dtk::Gui::DDciIconPlayer::setIcon(const DDciIcon &icon) @details 设置è¦�处ç�†çš„图标对象,这会导致当å‰�动画å�œæ­¢æ’­æ”¾ï¼Œå¹¶ä¸”释放上一个 icon 相关的所有资æº�。会触å�‘ updated ä¿¡å�·ã€‚ @fn Dtk::Gui::DDciIconPlayer::icon() const @details 返回已设置的图标对象。 @fn Dtk::Gui::DDciIconPlayer::setTheme(DDciIcon::Theme theme) @details 为图标指定è¦�使用的主题,如果值å�‘生å�˜åŒ–,会导致当å‰�动画å�œæ­¢æ’­æ”¾ï¼Œå¹¶ä¸”释放图标相关的所有资æº�。会触å�‘ updated ä¿¡å�·ã€‚ @fn Dtk::Gui::DDciIconPlayer::theme() const @details 返回已设置的图标主题。 @fn Dtk::Gui::DDciIconPlayer::setMode(DDciIcon::Mode mode) @details 指定图标当å‰�è¦�使用的模å¼�,如果值å�‘生å�˜åŒ–,会根æ�®æ–°æ—§æ¨¡å¼�的过渡规则计算接下æ�¥æ˜¯å�¦éœ€è¦�播放动画,以å�Šå½“动画ä¸�存在或动画å�œæ­¢å�Žæ‰€å�œç•™çš„内容。动画播放规则é�µå®ˆ DSG 中 DCI 图标格å¼�规范中的定义。 @sa DDciIconPlayer::modeChanged DDciIconPlayer::updated @fn Dtk::Gui::DDciIconPlayer::mode() const @details 返回已设置的图标模å¼�。 @fn Dtk::Gui::DDciIconPlayer::setIconSize(int size) @details 为图标指定è¦�渲染的大å°�,如果值å�‘生å�˜åŒ–,会导致当å‰�动画å�œæ­¢æ’­æ”¾ï¼Œå¹¶ä¸”释放图标相关的所有资æº�。会触å�‘ updated ä¿¡å�·ã€‚ @fn Dtk::Gui::DDciIconPlayer::iconSize() const @details 返回已设置的图标大å°�。 @fn Dtk::Gui::DDciIconPlayer::setDevicePixelRatio(qreal devicePixelRatio) @details 为图标指定渲染时的缩放比例,如果值å�‘生å�˜åŒ–,会导致当å‰�动画å�œæ­¢æ’­æ”¾ï¼Œå¹¶ä¸”释放图标相关的所有资æº�。会触å�‘ updated ä¿¡å�·ã€‚ @fn Dtk::Gui::DDciIconPlayer::devicePixelRatio() const @details 返回已设置的图标缩放比例。 @fn Dtk::Gui::DDciIconPlayer::setPalette(const DDciIconPalette &palette) @details 为图标指定渲染时所使用的调色æ�¿ï¼Œå¦‚果值å�‘生å�˜åŒ–,并且当å‰�模å¼�所对应的图片支æŒ�指定调色æ�¿ï¼Œåœ¨ Busy 状æ€�下,会导致接下æ�¥æ–°çš„动画帧的颜色å�‘生å�˜åŒ–,在 Idle 状æ€�下,则会é‡�新为当å‰�模å¼�计算应该显示的内容,这å�¯èƒ½ä¼šè§¦å�‘ updated ä¿¡å�·ã€‚ @sa DDciIconImage::hasPalette DDciIconImage::toImage DDciIconImage::paint @fn Dtk::Gui::DDciIconPlayer::currentImage() const @details 返回当å‰�图标在当å‰�时刻应该显示的ä½�图数æ�®ã€‚当此数æ�®å�˜åŒ–时会å�‘é€� updated ä¿¡å�·ã€‚ @sa DDciIconPlayer::setIcon DDciIconPlayer::updated @fn Dtk::Gui::DDciIconPlayer::play(DDciIcon::Mode mode) @details 为指定的图标模å¼�计算è¦�显示的内容,这å�¯èƒ½ä¼šå¯¼è‡´ currentImage å�‘生å�˜åŒ–。这是个一次性行为,ä¸�会影å“�下一次调用 setMode å�Žçš„结果。 @param[in] mode 指定è¦�播放的图标模å¼�,如果此模å¼�支æŒ�动画,会触å�‘此模å¼�自身的动画播放(与 setMode 导致的动画ä¸�å�Œçš„æ˜¯ï¼Œæ­¤åŠ¨ç”»ä¸�涉å�Šä¸¤ç§�模å¼�å�˜åŒ–时的过渡规则),å�¦åˆ™å°†ä¿®æ”¹ currentImage 为此模å¼�对应的é�™æ€�图片资æº�。 @fn Dtk::Gui::DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags) @details 为指定的图标模å¼�和播放å�‚数计算è¦�显示的内容。 @param[in] mode 指定è¦�播放的图标模å¼�。 @param[in] flags 播放å�‚æ•° @fn Dtk::Gui::DDciIconPlayer::stop() @details 如果当å‰�正在播放动画,则å�œæ­¢å½“å‰�动画的播放,但ä¸�会影å“�队列中下一个动画的播放。å�¯èƒ½ä¼šå¯¼è‡´ DDciIconPlayer::state å�‘生å�˜åŒ–。 @sa DDciIconPlayer::abort @fn Dtk::Gui::DDciIconPlayer::abort() @details 如果当å‰�正在播放动画,则å�œæ­¢å½“å‰�动画的播放,并å�–消队列中所有计划播放的动画。å�¯èƒ½ä¼šå¯¼è‡´ DDciIconPlayer::state å�‘生å�˜åŒ–。 @sa DDciIconPlayer::stop @fn Dtk::Gui::DDciIconPlayer::stateChanged() @details 通知状æ€�å�‘生å�˜åŒ–。 @sa DDciIconPlayer::state @fn Dtk::Gui::DDciIconPlayer::updated() @details 通知 DDciIconPlayer::currentImage å�‘生å�˜åŒ–。 @sa DDciIconPlayer::currentImage @fn Dtk::Gui::DDciIconPlayer::modeChanged(DDciIcon::Mode oldMode, DDciIcon::Mode newMode) @details 通知图标的模å¼�å�‘生å�˜åŒ–。 @param[in] oldMode å�˜åŒ–之å‰�çš„ mode @param[in] newMode å�˜åŒ–之å�Žçš„ mode @sa DDciIconPlayer::setMode DDciIconPlayer::setMode */ dtkgui-6.7.46/docs/util/ddesktopservices.h.zh_CN.dox000066400000000000000000000201041522615413000223310ustar00rootroot00000000000000/*! @~chinese @file include/util/ddesktopservices.h @ingroup DesktopServices @brief Dtk æ��供常è§�桌é�¢æœ�务的方法工具类 @namespace Dtk::Gui::DDesktopServices ddesktopservices.h @details 用于æ��供一些接å�£ï¼ŒåŒ…括在文件管ç�†å™¨ä¸­æ˜¾ç¤ºç›®å½•,显示文件,显示文件属性,移入回收站,播放系统音效等。 @enum Dtk::Gui::DDesktopServices::SystemSoundEffect @brief 系统音效的枚举 @var Dtk::Gui::DDesktopServices::SSE_Notifications @brief 显示通知的音效 @var Dtk::Gui::DDesktopServices::SEE_Screenshot @brief 截å±�的音效 @var Dtk::Gui::DDesktopServices::SSE_EmptyTrash @brief 清空回收站的音效 @var Dtk::Gui::DDesktopServices::SSE_SendFileComplete @brief 完æˆ�å�‘é€�文件(到桌é�¢ï¼‰çš„音效 @var Dtk::Gui::DDesktopServices::SSE_BootUp @brief 开机的音效 @var Dtk::Gui::DDesktopServices::SSE_Shutdown @brief 关机的音效 @var Dtk::Gui::DDesktopServices::SSE_Logout @brief 注销的音效 @var Dtk::Gui::DDesktopServices::SSE_WakeUp @brief 唤醒的音效 @var Dtk::Gui::DDesktopServices::SSE_VolumeChange @brief 音é‡�调节的音效 @var Dtk::Gui::DDesktopServices::SSE_LowBattery @brief 低电é‡�的音效 @var Dtk::Gui::DDesktopServices::SSE_PlugIn @brief 电æº�接入的音效 @var Dtk::Gui::DDesktopServices::SSE_PlugOut @brief 电æº�移除的音效 @var Dtk::Gui::DDesktopServices::SSE_DeviceAdded @brief 移动设备接入的音效 @var Dtk::Gui::DDesktopServices::SSE_DeviceRemoved @brief 移动设备移除的音效 @var Dtk::Gui::DDesktopServices::SSE_Error @brief 错误æ��示的音效 @fn Dtk::Gui::DDesktopServices::showFolder(const QString &localFilePath, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºç›®å½• @param[in] localFilePath è¦�显示的目录路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFolders(const QList &localFilePaths, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºå¤šä¸ªç›®å½• @param[in] localFilePaths è¦�显示的目录路径列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFolder(const QUrl &url, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºç›®å½• @param[in] url è¦�显示的目录 QUrl å½¢å¼�路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFolders(const QList &urls, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºå¤šä¸ªç›®å½• @param[in] urls è¦�显示的目录路径 url 列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItemProperty(const QString &localFilePath, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºæ–‡ä»¶çš„属性 @param[in] localFilePath è¦�显示的文件路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItemProperties(const QList &localFilePaths, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºå¤šä¸ªæ–‡ä»¶çš„属性 @param[in] localFilePaths è¦�显示的文件路径列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItemProperty(const QUrl &url, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºæ–‡ä»¶çš„属性 @param[in] url è¦�显示的文件 QUrl å½¢å¼�路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItemProperties(const QList &urls, const QString &startupId = QString()) @details 通过文件管ç�†å™¨æ˜¾ç¤ºå¤šä¸ªæ–‡ä»¶çš„属性 @param[in] urls è¦�显示的目录路径 url 列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItem(const QString &localFilePath, const QString &startupId = QString()) @details 通过文件管ç�†å™¨åœ¨çˆ¶ç›®å½•中显示并选中文件(目录) @param[in] localFilePath è¦�显示(选中)的文件(目录)路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItems(const QList &localFilePaths, const QString &startupId = QString()) @details 通过文件管ç�†å™¨çˆ¶ç›®å½•中显示并选中多个文件(目录) @param[in] localFilePaths è¦�显示(选中)的文件(目录)路径列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItem(const QUrl &url, const QString &startupId = QString()) @details 通过文件管ç�†å™¨åœ¨çˆ¶ç›®å½•中显示并选中文件(目录) @param[in] url è¦�显示(选中)的文件(目录)QUrl å½¢å¼�路径 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::showFileItems(const QList &urls, const QString &startupId = QString()) @details 通过文件管ç�†å™¨çˆ¶ç›®å½•中显示并选中多个文件(目录) @param[in] urls è¦�显示选中)的文件(目录)路径 url 列表 @param[in] startupId 本次å�¯åŠ¨çš„id, 默认为空 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::trash(const QString &localFilePath) @details 通过文件管ç�†å™¨å°†æ–‡ä»¶ç§»å…¥å›žæ”¶ç«™ @param[in] localFilePath è¦�移入回收站的文件路径 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::trash(const QList &localFilePaths) @details 通过文件管ç�†å™¨å°†å¤šä¸ªæ–‡ä»¶ç§»å…¥å›žæ”¶ç«™ @param[in] localFilePaths è¦�移入回收站的文件路径列表 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::trash(const QUrl &url) @details 通过文件管ç�†å™¨å°†æ–‡ä»¶ç§»å…¥å›žæ”¶ç«™ @param[in] url è¦�移入回收站的文件 url 路径 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::trash(const QList &urls) @details 通过文件管ç�†å™¨å°†å¤šä¸ªæ–‡ä»¶ç§»å…¥å›žæ”¶ç«™ @param[in] urls è¦�移入回收站的文件路径 url 列表 @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::playSystemSoundEffect(const SystemSoundEffect &effect) @details 播放系统音效。如果系统音效被ç¦�用或者è¦�播放音效被ç¦�用将播放失败 @param[in] effect è¦�播放的音效,è§�枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::playSystemSoundEffect(const QString &name) @details æ ¹æ�®éŸ³æ•ˆå��播放系统音效。如果系统音效被ç¦�用或者è¦�播放音效被ç¦�用将播放失败 @param[in] name è¦�播放的音效å��称,è§� Dtk::Gui::DDesktopServices::getNameByEffectType @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::previewSystemSoundEffect(const SystemSoundEffect &effect) @details 系统音效预览。 @param[in] effect è¦�播放的音效,è§�枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::previewSystemSoundEffect(const QString &name) @details æ ¹æ�®éŸ³æ•ˆå��预览系统音效。 @param[in] name è¦�播放的音效å��称,è§� Dtk::Gui::DDesktopServices::getNameByEffectType @return 调用æˆ�功返回 true, å�¦åˆ™è¿”回 false @fn Dtk::Gui::DDesktopServices::getNameByEffectType(const SystemSoundEffect &effect) @details æ ¹æ�®éŸ³æ•ˆå��预览系统音效。 @param[in] effect è¦�获å�–å��称的音效,è§�枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect @return QString effect 对应的音效å��ç§° @fn Dtk::Gui::DDesktopServices::errorMessage() @details 文件管ç�†å™¨ç›¸å…³è°ƒç”¨å‡ºé”™æ—¶å�¯ä»¥é€šè¿‡æ­¤æŽ¥å�£èŽ·å�–错误信æ�¯ @return 错误信æ�¯ */ dtkgui-6.7.46/docs/util/dicontheme.zh_CN.dox000066400000000000000000000124241522615413000206470ustar00rootroot00000000000000/*! @~chinese @file include/util/dicontheme.h @ingroup dci @brief Dtk 图标主题工具类 @namespace Dtk::Gui::DIconTheme dicontheme.h @details 用于æ��供一些接å�£ï¼ŒåŒ…括查找图标(包括 QIcon å’Œ DCI 图标 ),图标æ�œç´¢è·¯å¾„等。 @enum Dtk::Gui::DIconTheme::Option @brief 查找图标时的选项 @var Dtk::Gui::DIconTheme::DontFallbackToQIconFromTheme @brief 是å�¦**ä¸�使用** QIcon::fromTheme 的方å¼�去查找图标,当设置此 flag 时查找图标失败时直接返回空图标对象,å�¦åˆ™å›žé€€åˆ°é€šè¿‡ QIcon::fromTheme 查找图标 @var Dtk::Gui::DIconTheme::IgnoreBuiltinIcons @brief 是å�¦å¿½ç•¥é€šè¿‡å†…置图标引擎方å¼�查找图标资æº�,当设置此 flag 时查找图标会跳过内置图标引擎的方å¼�查找图标资æº�,å�¦åˆ™ä¼˜å…ˆå°�试内置图标引擎查找资æº�。 @class Dtk::Gui::DIconTheme::Cached @details 图标查找缓存类,æ��供的查找图标接å�£ï¼Œå¦‚果找到会加入缓存,下次查找会更快。 @fn Dtk::Gui::DIconTheme::Cached::Cached() @details 图标缓存构造函数 @fn Dtk::Gui::DIconTheme::Cached::~Cached() @details 图标缓存æž�构函数 @fn Dtk::Gui::DIconTheme::Cached::maxCost() const @details 返回å…�许的最大缓存数é‡� @fn Dtk::Gui::DIconTheme::Cached::setMaxCost(int cost) @details 将最大å…�许的缓存数é‡�设置为 cost 。如果当å‰�的缓存数é‡�大于 cost ,则æŸ�些缓存对象会立å�³åˆ é™¤ã€‚ @fn Dtk::Gui::DIconTheme::Cached::clear() @details 清ç�†æ‰€æœ‰ç¼“å­˜ @fn Dtk::Gui::DIconTheme::Cached::findQIcon(const QString &iconName, Options options, const QIcon &fallback) @details 通过 iconName 查找 QIcon 的接å�£ï¼Œæ‰¾åˆ°æ—¶ä¼šåŠ å…¥ç¼“å­˜ @param[in] iconName è¦�查找的图标å��ç§° @param[in] options è¦�查找的选项 @param[in] fallback 图标查找失败时å�¯ä»¥è¿”回用户指定的 fallback 对象,默认为空 @sa DIconTheme::findQIcon @fn Dtk::Gui::DIconTheme::Cached::findDciIconFile(const QString &iconName, const QString &themeName, const QString &fallback) @details 通过指定图标å�� iconName 和主题å�� themeName 查找 DCI 图标文件路径的接å�£ï¼Œæ‰¾åˆ°æ—¶ä¼šåŠ å…¥ç¼“å­˜ @param[in] iconName è¦�查找的图标å��ç§° @param[in] options 指定 DCI 图标主题 @param[in] fallback 图标查找失败时å�¯ä»¥è¿”回用户指定的 fallback ,默认为空 @fn Dtk::Gui::DIconTheme::cached() @details 获å�–(首次次调用时构造)缓存对象。 @fn Dtk::Gui::DIconTheme::findQIcon(const QString &iconName, Options options) @details 返回 DIconTheme::createIconEngine 接å�£åˆ›å»ºçš„图标引擎构造 QIcon,当没有设置 DontFallbackToQIconFromTheme å’Œ createIconEngine 失败时回退到 QIcon::fromTheme @param[in] iconName è¦�查找的图标å��ç§° @param[in] options è¦�查找的选项, 选项默认为空 @sa DIconTheme::Cached::findQIcon @sa DIconTheme::createIconEngine @fn Dtk::Gui::DIconTheme::findQIcon(const QString &iconName, const QIcon &fallback, Options options) @details é‡�è½½ DIconTheme::findQIcon, 当查找图标失败时返回调用者中æ��供的 fallback 图标 @param[in] iconName è¦�查找的图标å��ç§° @param[in] options è¦�查找的选项, 选项默认为空 @param[in] fallback 如果 iconName 无法找到, 返回此图标 @sa DIconTheme::Cached::findQIcon @sa DIconTheme::createIconEngine @fn Dtk::Gui::DIconTheme::createIconEngine(const QString &iconName, Options options) @details 通过图标å��构造图标引擎, 如果未设置 IgnoreBuiltinIcons 标志则优先å°�试 qrc:/icons/deepin/builtin 目录查找图标æ�¥æž„造内置图标引擎,å�¦åˆ™æž„造 XDG 图标引擎。 @param[in] iconName 图标å��ç§° @param[in] options 选项, 选项默认为 DIconTheme::DontFallbackToQIconFromTheme @return QIconEngine 对象指针,注æ„�图标查找失败时返回 nullptr。 @fn Dtk::Gui::DIconTheme::findDciIconFile(const QString &iconName, const QString &themeName) @details 通过指定图标å�� iconName 和主题å�� themeName 查找 DCI 图标文件路径的接å�£ @param[in] iconName è¦�查找的图标å��ç§° @param[in] options 指定 DCI 图标主题 @return 返回找到的 DCI 图标文件路径 @sa DDciIcon::fromTheme @sa DIconTheme::dciThemeSearchPaths() @fn Dtk::Gui::DIconTheme::dciThemeSearchPaths() @details 返回 DCI 图标的æ�œç´¢è·¯å¾„。默认会从这些路径查找 /usr/share/dsg/icons/$theme_name, qrc:/dsg/icons/$theme_name, qrc:/dsg/built-in-icons @sa DIconTheme::findDciIconFile @fn Dtk::Gui::DIconTheme::setDciThemeSearchPaths(const QStringList &path) @details 设置查找 DCI 图标的æ�œç´¢è·¯å¾„ @sa DIconTheme::dciThemeSearchPaths @fn Dtk::Gui::DIconTheme::isBuiltinIcon(const QIcon &icon) @details 返回 QIcon 是å�¦ä¸ºå†…置图标,`内置图标` 是 DTK 中规定的一类集æˆ�在二进制内部的图标资æº�,其一般放置于 qrc:/icons/deepin/builtin 的路径下,在使用 findQIcon 或 createIconEngine 时,如找到此路径下对应的图标文件,则会为其使用一个自定义的 QIconEngine 进行渲染。此方法å�³é€šè¿‡åˆ¤æ–­ icon 所使用的 QIconEngine 确认其是å�¦ä¸ºå†…置图标。 @fn Dtk::Gui::DIconTheme::isXdgIcon(const QIcon &icon) @details 返回 QIcon 是å�¦ä¸º XDG 图标, XDG 图标一般放置于系统图标主题目录(如:/usr/share/icons)。和 isBuiltinIcon 类似,此方法是通过判断 icon 所使用的 QIconEngine 确认其是å�¦ä¸º XDG 图标。 */ dtkgui-6.7.46/docs/util/index.zh_CN.md000066400000000000000000000002241522615413000174400ustar00rootroot00000000000000@page util util--dtkgui工具组件 # Dtk-Gui util:dtk工具组件 TODO:添加组件说明 @defgroup dci @brief dci图标æ“�作类 @details dtkgui-6.7.46/dtkgui.cmake000066400000000000000000000125361522615413000154040ustar00rootroot00000000000000message(STATUS "Compiling with DTK major version: ${DTK_VERSION_MAJOR}, Qt major version: ${QT_VERSION_MAJOR}") set(LIB_NAME dtk${DTK_NAME_SUFFIX}gui) # Set install path if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX /usr) endif () include(GNUInstallDirs) include(CMakePackageConfigHelpers) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set build option option(DTK_DISABLE_LIBXDG "Disable libxdg" OFF) option(DTK_DISABLE_LIBRSVG "Disable librsvg" OFF) option(DTK_DISABLE_EX_IMAGE_FORMAT "Disable libraw and freeimage" OFF) set(CMAKE_CXX_STANDARD 17) if("${QT_VERSION_MAJOR}" STREQUAL "5") set (BUILD_DOCS ON CACHE BOOL "Generate doxygen-based documentation") else() # dtk6 not build doc set (BUILD_DOCS OFF CACHE BOOL "Generate doxygen-based documentation") endif() set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${DTK_VERSION_MAJOR}/DGui") set(TOOL_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/dtk${DTK_VERSION_MAJOR}/DGui/bin") set(LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") set(MKSPECS_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/mkspecs/modules" CACHE STRING "Install dir for qt pri module files") set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Gui") set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -fopenmp") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(BUILD_TESTING ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -fno-omit-frame-pointer") else () set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast") endif () set(CONFIGNAME include/global/dtkgui_config.h) file(WRITE ${CONFIGNAME} "// This is an auto-generated header, please don't modify it.\n" ) file(GLOB CONFIGSOURCE include/DtkGui/*) foreach(FILENAME ${CONFIGSOURCE}) get_filename_component(thefile ${FILENAME} NAME) file(APPEND ${CONFIGNAME} "#define DTKGUI_CLASS_${thefile}\n") endforeach() # Generate cmake config file configure_package_config_file(misc/DtkGuiConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Dtk${DTK_NAME_SUFFIX}GuiConfig.cmake INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" PATH_VARS TOOL_INSTALL_DIR ) # Generate cmake version file write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/Dtk${DTK_NAME_SUFFIX}GuiConfigVersion.cmake" VERSION ${DTK_VERSION} COMPATIBILITY SameMajorVersion ) # Install cmake config file and version file to CONFIG_INSTALL_DIR install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Dtk${DTK_NAME_SUFFIX}GuiConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/Dtk${DTK_NAME_SUFFIX}GuiConfigVersion.cmake DESTINATION "${CONFIG_INSTALL_DIR}" ) # Install pkgconfig file configure_file(misc/dtkgui.pc.in dtk${DTK_NAME_SUFFIX}gui.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dtk${DTK_NAME_SUFFIX}gui.pc DESTINATION "${PKGCONFIG_INSTALL_DIR}") # Install pri module configure_file(misc/qt_lib_dtkgui.pri.in qt_lib_dtkgui.pri @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qt_lib_dtkgui.pri DESTINATION "${MKSPECS_INSTALL_DIR}") set(GUISGNAME DtkGuis) file(WRITE ${GUISGNAME} "// This is an auto-generated header, please don't modify it.\n" "#ifndef DTK_GUI_MODULE_H\n" "#define DTK_GUI_MODULE_H\n" ) file(GLOB FILEGRAGTOWRITSOURCE include/filedrag/*) foreach(FILENAME ${FILEGRAGTOWRITSOURCE}) get_filename_component(thefile ${FILENAME} NAME) file(APPEND ${GUISGNAME} "#include \"${thefile}\"\n") endforeach() file(GLOB KERNELTOWRITESOURCE include/kernel/*) foreach(FILENAME ${KERNELTOWRITESOURCE}) get_filename_component(thefile ${FILENAME} NAME) file(APPEND ${GUISGNAME} "#include \"${thefile}\"\n") endforeach() file(GLOB UTILTOWRITESOURCE include/util/*) foreach(FILENAME ${UTILTOWRITESOURCE}) get_filename_component(thefile ${FILENAME} NAME) file(APPEND ${GUISGNAME} "#include \"${thefile}\"\n") endforeach() file(APPEND ${GUISGNAME} "#endif") install(FILES DtkGuis DESTINATION "${INCLUDE_INSTALL_DIR}") # Find common dependencies find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui DBus Network) find_package(PkgConfig REQUIRED) find_package(Dtk${DTK_NAME_SUFFIX} REQUIRED Core Tools) find_package(DtkBuildHelper REQUIRED) pkg_check_modules(librsvg REQUIRED IMPORTED_TARGET librsvg-2.0) if(NOT DTK_DISABLE_LIBXDG) if (${QT_VERSION_MAJOR} STREQUAL "5") find_package(Qt5XdgIconLoader REQUIRED) if (NOT Qt5XdgIconLoader_FOUND) message(WARNING " XdgIconLoader Not Found, DISABLE LIBXDG !") set (DTK_DISABLE_LIBXDG ON) endif() else() find_package(qt6xdgiconloader QUIET) if (NOT qt6xdgiconloader_FOUND) message(WARNING " Qt6XdgIconLoader Not Found, DISABLE LIBXDG !") set (DTK_DISABLE_LIBXDG ON) endif() endif() endif() # Check optional image handler dependencies. find_package(FreeImage) pkg_check_modules(libraw IMPORTED_TARGET libraw) if(FreeImage_FOUND AND libraw_FOUND) set(EX_IMAGE_FORMAT_LIBS_FOUND ON) endif() set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(src ${OUTPUT_DIR}/src) if(BUILD_TESTING) enable_testing() add_subdirectory(tests ${OUTPUT_DIR}/tests) endif() add_subdirectory(tools ${OUTPUT_DIR}/tools) add_subdirectory(examples ${OUTPUT_DIR}/examples) if (BUILD_DOCS) add_subdirectory(docs ${OUTPUT_DIR}/docs) endif () dtkgui-6.7.46/examples/000077500000000000000000000000001522615413000147225ustar00rootroot00000000000000dtkgui-6.7.46/examples/CMakeLists.txt000066400000000000000000000002361522615413000174630ustar00rootroot00000000000000add_subdirectory(dnd-example) #add_subdirectory(test-taskbar) # Don't build #add_subdirectory(frameless-window) # Don't build add_subdirectory(animation-dci) dtkgui-6.7.46/examples/animation-dci/000077500000000000000000000000001522615413000174365ustar00rootroot00000000000000dtkgui-6.7.46/examples/animation-dci/3depict.dci000066400000000000000000001262241522615413000214610ustar00rootroot00000000000000DCI256D¬normal.darkª3b1.webp/256/normal.light/3/1.webpnormal.light «3ª1.webpzªRIFFrªWEBPVP8X ÿÿALPH1‡mÛHg> ÛÁÉ<¸k ¢ÿÀ_+ ¿ÒÎ/$©ÀýlÅŽ¹‰G3Iű IO,^4ƒõb­–å{6ç„ö3hóÓß�«h ½C?YtÀ}§ƒìî•$1F"î(àÁ%‡AÛF’bþ°oo_1]k�á Y ß}ù1l ­hýC÷´£7lHÕû,il¸c8c!?´Š �è8m›INü»+W]G¾\vuƣȗ§[葇333Ç@ÆQ T¦ "&‚$¹q›5E‚‹ˆØ¤œûþVÝ6Û¶±dÉìØŽí8œ8eæö`f¤Õ†�ÖÕ~š¢µuñ“Øíc±‘²ÚÐÞ ÜJ º¸HG]¯©À‘ŒÄãÇ š¨6¡ÙðHXg#©¦ ÷á‹RR¹L¾3Ó×ÝÝÝÙ“ÉeR±Ž¸‰½:UvKå­õÕííÍR±R®‹‹‹‚»’.j,‹Íæ+ô ô� �÷öw¦² Ü_Ìzu¯¸¶4;½±¼¹¼]iHס¬PK›©Ï8öØØÈ`o>ýÐo9”ö–W·—§ïL-íÔ}ìˤ„É�ï ÙÕ7üô‰£Gºs™Oô¥5ËÛË“�_XØnˆ®@¡t  A.uôü©ñ¾ü§æ5V¶>ºtíã…�µ „ 56[bà±·ž.|ú^©·ºt÷Ú¹Ûë5›‰DF×üƒjº?ýæÓ#ÝŸÞìí,ÞÿÝ¥ûkõ}(4Oƒñ¡‰Ç?óÌÐ#ð·ï½wöÚ="‹BÏ”5hjòÇ_}å‰ÑÂ#óê볜ýÕlÓTØ:Æq 0MÇão~áä@òë‚úô‡?½<[6F¯bK-@³5xìÙ¯|¥ïÑìˆúü¯ß½t·PAêåÏÒÈ3_ýìxâî ïÁûïýt·v¹c0ÈýÒ�Žæù.©ßü·¿™Ü¥€Œ&qAüqìåÏ ¸¢_>ø§ç·ÀTX˜eeAö•ŒÔ]Ò7»W~õ¦<“ãÁr²øÖõÆ÷ÒÎéïþÛÿîB)³œ,¤¡7¾œpS'müô¼½®K À�}í�º»:ªréÿlHf–Ž£d%Nïñ¦Ûú¨|ñŸþd]dV +öì·Î8°¿ê¿ü÷¿Æ, +ñôqdŸÕ.þ£ÿµÁÛÅã’Y„Y0þgN8´ßJçþÙÏ H¾%ã:$èÿæçÛe•_þó_–[€ì]t±D �o¢Ü×~Two÷ú·Ï5[8ïWÍq˦>÷ƒº›»mé?þÝ{#`È·\X{òÇÜÝ‹WÿÖõX>X䆭 8ôWN:½#‹÷¸Åu „;Èz‰B„ä­nãÄ?ùç^=�À8•úQˈ4ò x:{¾øj³i mñùÏ~¥·‡'ñôO2 Š„“&(Œ½q¸mtfüé—r(ÄÓ ¯“»^x<×NúõÀÄ(‰ ýÉoŸl3ý™{í¥ꇛá‡Xxât¦ýôêèƒÐòP¯€S±çùƒm©;ž{[Jµð&$ÆÏ<‘mW]{úù!hùj‡*óÄxë×îçé�v¶µŽ�íKø@±**@ a"">ñL¦Ýuuÿs�B‡£œm„z…#Ãm°—;OZuµÂíLO[ìàxG"è‚Ép}2Õ.»ùôcñ14 D¾ÐF»º§3-…ЂÉÁD[íïÌÉN£®°™‘A€öšÆ hFy`Oo¬ývvçp4_mAçZúxª÷~/Fú¸–)×ÝѦ;=-Ç‹ôa�ô·íާÑX‹FÿªU‰oÃÒ±èOâýɶÞóÙ|1ÒôRí~ÖQO,âÓÍößù1À(ì “.™JDøT ^£•AöKŽTX˜pͪ½ÿ)"óݹð0{Å­qˆAx@½ÖŒÞ¨îÖBÅ(4Ê‘^5l\[§Ê^ÄÆ|5t Äf)Z)m„�!©�q¡È« €b8¹Èh,· p‘r˜K[Û!exînó�O)�· !Þâ¶,FWÅ®^Æ¥¹P‹ÂUŠóaæSyº}½ë7ª¡fXgí²Í`Û¶ÊvfØ Œ7�éhz5ô Ðò ûßtÄT˜sia BêW+M‹jW›!h„šK›ÆM$Q[ß Eã³t#:.5²âÒBH®Ù;ÂHÑ\¦[ÝMãt~‡X€È¨ásˆv.…§±Ú¹Re&0nò8bRyº¢†löEÍšÍÉpõháܼ7{«�0}®ÜƒPïÝMÿlM’jÖ2 Nkÿ£®È‡‘Ñ™˜äÝY[iŠ„S÷ÔYÆÌ¹9ÂFìÒ �åô=i ÇÒå06k¶~Ú  Ñž8‘?sê¿Ú eƒwé#C3Í›“&oB(Cãì*Ðä}µa`~2¬ ßÊoˆ†wî‰SµP¼TmãöÁõh¦’爟þûm(ý÷ò9Ü„±rZþ÷^ˆ»ë\’ÐÍ׸¸êÆîü‡sæš±?]¾¡+Oû›qf²BÐøJI€/•CÞ(žÜB6ˆQ«šUaôûò0R-ûˆheD¢|ª´Pü„=ÄúWÀ¨±tF½ê©ð7�ƒ�¢?‚ˆ+ 3m�‡Á¯ç[Fá8�¨¡ž9‡²/¾ f•ÈDÐð›éK„AĆ— #R<³Nµ4³?]¹.F‡É•B<$Žä¡��c"hî€5 T=!]}[–xy¨‘–G¡q,�Ô‰F”I{µ‘NÏ÷ÅèCÐàfc!r4{'‰qþ˜F&Z.öCˆD~cd_Œ4¹ÃZ�«L³a�4fë|Øm A¨Dµ� ÿYއKÄÇE…¶âN_ØÈž½ÈC�SàÆÛé ™$?©HóAøÊ¡¥*D {nÈ`¹‘ ŸHÔçˆÄ›ÏQLÈé\oÕÞ{�HC-iµÑFщ«Ì#‹IH÷zÃéÔè¸mžÞ#‹ˆfäõ.¥(ÌÍŽ u�Ã!2ÌtÅÃ)’1#°D"вº:VµófÓ_nÆÛ Ó;‰°ŠÜÝ a€#Œxú ¬"–š‡#IM¢ÕùÎð:´}“Us„£‰7oÅ­†Wd7çÄc\TÙš“}avP»îÙ®u#‡;ù~_„0‹îåbñEòõæd(<jßü˜ˆ¢ˆÈ¶àÓµp;¼7É"F ް%Ä^‡p‹ü��èqëÉl€o8r‘X�uZ| OÜû…:„Ü-~ƒˆB‘ø©zØJ¦Š¿ aÝ·÷ü)á‹¡m½áÃ_hôðä–4x"ô"9/Š!ª.î«yô°Ö=$ù™üpxú*I3 öŽ÷mÚ·�TÝ—ìë?ቋU>þv|QhÀþFÁ—nX0ýö`çxFfjYšjaņ¶HÚ† LÄâ€ö6éFMjz^€åf­º/W~ :J!±ú- p1¼¸_”K¥sÙŽt.ßÙÕÙUèÍd³iÀûnÔZƒÊµJ©²¹º±³¾½W®îÕëž´¶È²-Š2œ ÀÌå†\v‡­~ÉBïÁÁ¾Ñ¾þÁ|O*•NÆöõ2•R±¸;·½µ¾¼´±¾»ãÙªÒ¾vƒþLHŸ�PŒK›lÞ… ³™ú\vt|ìäØP_OÇ'ð ¤W*no¥Ÿù\Ýœ¹uþìlQ0/Ÿ�ÐðëœÉÈ]Ü¢v®19ãX¦Ô5ðÄc�Ÿêüt�D}eò½÷§—¶É€‘L¿QÉHÌOk„ p yùÍSãéGãÅ—¯þþÒü<+/ó3õ°œ߇–sû½õŒÁ4~ß=÷Öëã�ØÃî›K×Þyÿ~…%�:áeËÀ d9·©¦‰šøÊëã�bGÔ×>üÕ{wªò¡p04#ñAQ íêeMêøãO}þHîÑí šúÍç'›HÂD ÏøhÚkl«?!kÃðg¿ÞÑ|ä»Ä›Ýxç홀ï:^ ͈o] =æâ�Ï~ãTÅ ýòükÇ—~rc¦ŽG!}A_€qs®ê—õ?{Tf‹µüÛ»²:“ãæW©ËMaï­£'”ñ6ñù1}] 5Hv:Ú…zé#YP ‹ß †öÙÁè 9d“Wú}ýqМ�ÜâìïÕÙ¼€Ó= vâèšUt:“N‚ò QqüMóf´͆Ã5‰BÔÔpú=Ã^ý�Ó/\È‹‡ªÇBéB4ͺ»É¨Uw[=P"¸Z�Jû5”HpôÑ¢C‹Pw3ª»ža{ÏÅÿóv@‘¶­’ƒ»ª¶]Ó$ì¶r,¼íh¶É½{­¥T)Ó’{;ª¾ª„f‘éˆt&X(‚2aÓ¹&5@™PYôéLRönÀWy´ µ-iŽ�M›t}Ô ;[,®íÅ5Ð'÷Zœ3·ÒÅŠBa]˜ÊN 9§QfjîŠdÝÁZ4 ·�KzÒ' ¥9•ÊåS#+»°ÃÍÛ¤R(®uÙkó5P)¬l»ËÉúœÙƒ2è¦w¬o;ršÒÜ]¥Â½’?«¹ƒ& ù UX #žNÁ#\ô´ µUÁÍéÔ/lªÝYd‘á¯JtcÔ +Kæõ–[�,ß+™ü³z•;â7l2ª_R°œéÝò5²ì’»oT ‡ë ÇÈìÀhçW,Ço  É]A_C²ÌÁ%C~Ľ×0Z¾ÖeÙ& 86ª`è‹ípXeGÔüRSÃî9ïšµœ ›Ë ³töîp ²lÔGWÄz<¡`ßmƒt‘ïà ËéÁ-0/µLïG_–ž†xLÁ0X¬¸Ê𹘂=pà=@d°xã£NÑhÅçŒÜj‚sÊ»d=¢_Èàºt¢AçxÃ×› F—(Ä3¸GÖל{U¿r®°€ÖȰqoªI*ØG­ï‚%²dŸ€•çI½Ð›xÁóˆ+¿�Ï(Ø;î–A¤ PØZh^ׯÏÚjl¢è–ˆŠ·ËÚ,Ü÷ÀN™ìˆÚ÷6ô듦wŠÖ ��0 ô‚/£v!‘˜´PæëbÈ•ûyõzÃéT=(u…<µ•Ö.]iÅ_l�¨+äóíªÓ³@ˆºB®_Ò.š]ÞáóÝN] $ßoõFN·�¢idwˆ3&ž�ëºVæ*sd” 0¿úz_P®÷›.. ¤Ñ4áà!ݪ“š!Y6*ðH~Ç{uëaã¹R°‰¯ÂÅ‹—ªõ°åý#.ÿ{ ³°ð¬fåXÙ‘ŽÓõ�j}ÜnçtÕ>ãɨ"ñX·fÝrX^Cva‰8Jð!÷z:«WˆïÞa¾ÜäԌ܂˜: Š…©ºåqvP1¢Å4xT±ž6¸¾b¹á å§!¦ÂØ�^=l°1+9È8‚‚åp‡Z¡6E<¦é2LË]‡Äc1­BñìNËÃäè¨Fš>¨Vï·¸±!íËb»ö]È_9§X8¤UÑ׿EY{FЧgH©òÌeÏRƒš ‚1v0Þ«SX»Ò0)�jlC‘”NÑ{`P§m,Èa•Êtwˆ€u“ÎôkÕ<©RÑ'ïšn`*•phñ,¨”çÜ�D72¸¸Šå¡a}Þ»†Éo¸Ð¤„}Â̇5i'ÎóT©šÅk{&/íË®S’àXR›°óÎ:ãoÕ”Œ8 M¹tq•�mˆkÈ¢ÑãhåDV›Þj}ùºè`QPúu tî. ¸ÑQÑL)�S%4nÜ%CÇ©×a5;:4 ÕË7ÉÐùj«FUÚžNEBý·†Ž¸Õ'Á¤¬‘W¤ÛnÅ¿7{ÙOF=÷8‰;èIëV~ÖƒàS#ŽÄ–¡³âp t*ÒC÷‡~Öhq5pê¬p1MŠiêºq­ÅšQ™¥5vW¥ÛÎÙ/þvŽ�f$€_:‰¢!a\—>rz¼ï'þ:ã,!�”TǸ!˜îUÚž»}ׇáŠ$ó²‹éz_ÿ�»Œ ±¹.·XmúÌÅ3�·Ác3šíÂeqMÇt^™ý×+-žÈÏn¤quúÆÉ±ñÿQ'¯EÁewPÜA,¥MÀ×ï]õXlr_±P1mR^ùÏ{-­îrH)Ô§NL4~/DDpŸ{2­Pß5öê; uŸ{*ú´ù¯ž¬F§ÉW©ô™Ù ¢ˆã@£\ wúÖÁgô~{|òc‘¸I6$T«Ÿýäÿ¨øĄ̈ïä©é›‚Ùu©^×)äžú/ ‘¸Ê }xžR‘'·Ï9’`£©TÈžúIÕ ®³7jjdþšÔm¤VÕ*ä^üŸ»î#†Z­ˆoj¨RÏþt×§ä:u½ jµ�,}†êz"áÇu×­TU¬�žˆ¸l=©)‹ÕŒfæSÝ9„?-´¦W�“ yÊ»† pXÀuO­Ì©˜¡tLsh‘µ ’MJqÝX2mtkI¥ÌÙî„(߃KËýZõä}‚y8+0÷`};§T�Zº‘G±-4—�éTTù*ÇAÅ.)–t ì`î*‚hiË\!¦T²9îçÚPÑ)O‚ÈýAæâ …B,Åæ8÷pAÁÚLF¡@Mp©ÜVV:ô ͺw™¡©.}ªâ5Àa MB¦ª²‘×§¢t™h%0SN©“Ú—iÎv¨Èa(>6¶º” �¸� ¼i¾• u‡¡ZÊÞœ2U©7Àyľg·Òª„rÕe�O@²*©J¨º«  âÀÖ­Œ&¡IàBbd³‹æÖ5éæƒgÑ]Î,€¦’¨GØ©¸¯.B€»oÅ�z„Íš3;¥hîNZ�PÁ&Ý$Ÿª%´« v%Oîãä÷ջΫe!’‰Öo'•¨æ¦T“eM–þ™]×!ŸÚ–q wŸ(˜É05o5uEéjÆY$€Š¸´wõ€ ½íhWŠëÀ*hcVN{~a(ª2Åò� tÛ¹h㜧²ÌœJ¨¶J&%‡ªˆL{Gôç¶C͸¡ë8bQ1Žg„ž>õ),u�WíáZL§ò$ïYk9ÏÄïÒ�Û³’¿UBè7§c8®:±fÉêëDqÒ¢ìOñ¸ê|Çêã„Nü'¬å$ÄØ|�â`aÛP“CUÜÁ œMåõóu# çH•Em²IµÁ]µ9y#v©ˆæYrZó¤ú4€¬s¥ ÍeÆBViÞu´L$Ôrë? �u"¢iŠ×t¦&÷t«¯l0¡aìÒÌmËq¬@¹±B\ap¯ÄµäT Ef4�EuM6 Á¥aíþ¢W2¦.io ˆ[x8Ǻ"9!5êÊ‚µWó�O@õͪ®à‚9Ʊ} 2µbO™Œ­Óá-ùý¼…#¯)ŸFT}Ó—†£v&W´vnî(ÊGN?ëg¬MtÔLëÉ]·ü-ñ*m�š»óšñF-Ø‹–~ rÂÜZÐxW>ùm\4ĸå©¶—~bô÷Vc¡® ˜MŽÿs‹*[¹©Lnë>rÉ-¼T×vÔ�ŽÊ6€6€·Q: Øš¬NÞkìmXì9ŽªñÌ�7bŒI~êÜAÆÓ¤S'“Š�ëc¦6M(EŽ¡òáÖÓiµ@åú(„…ÚQ’´ƒÆÍé£ýZ�©Õ ›„÷Y‰uïÕÂ1Ô Ü ÓŽ�dÞhÀڹʉ¬F yvÌŸ£®Ÿ_:e~–/Ò©~xghD#>ptE²¸>=idÛIMh\¿xp\n:ÏŒ¢À¹¨of ’kJ㚀)%SHæm°P¼0uhõçǺm“T=( Òª˜ùÝÚX·`ýñ%¾_{Q?M¾(Ë×®ôŽÆu—S£âA{ôµ2'ÙO^�+ï¬�õ¨ÀM·ßJµ(:¢Ç~Ò#™X õg½±¬x/�ùGé6&KŠv/Ø<7}à`äÇ;GF@Ð:²ÉïQƒ•ÂBsêlc¨ñßr}þP,rKœÔ§Ä M)~ð�§#ýÇÕ1¦A×ÏÜèH v)ÆüŒ&m\¸‘NEwœï‘§$Ÿ÷“‚,HX•Ío?î�Et+#" “züE+Ai4¤qç7÷ºbGvt£ŸÜF¢ÑPVµ|gƒ†z#83žñ�ñˆtÞ’$Y™Æ–JÛ™ñ|ÔFìÄ®]î+¶ôœÚîì6ûº£5º{>Ä íŒÜ2:˜Ä)&Ö¬­¥ížHýøá-�ƒ)ݹ¶!äÉ'%{ÚZ, ôÆ£2:†¶Á‡85›‚+��’pÌ)-/×GÒÑ#�#ÀjëŽ Ä’|Ð)-–²�ùŒT÷2 ›oŽî¼îH™à™xŸ~�ÅIìëĨ‹á½†¡Aå¾ô”$º³Bn”·±°XêÍEZ$»ÖÄ©†}Êx_£EI`–ØžZ)e ‰èŠCX“¼Ñôƒ�`,@¦±toÙKGÕ=ÅŽï ”&]Ÿ¤±ÚHX�rǣИòäGk^w6’ÞsËì"€ámÎÄŽƒL ñì#@»fvRé¨ ßöyÓÛLÐ`³7€dAVˆíª.ßžÜ.gÓ±(‰|a€@ªÜ-)ì#p“ä†Õæ®ß¼¹œîLDFô­x(M?ÚëœÁ}˜ˆûÕ×§&ï/§2)Œ‚(Ä78'­ñÞ—™ ÝOLïgnßš«A2ù00O€Æë¶„�â¡åÂŒ¸TY¼yéÚÝÕÝl£œÝkÙÍɆh¸¶nà~{�DšÅ¹;o^Ÿª&(Í\qp‘M4c±qnDãZ ll�•�Êʽ«Ï.m½dòÓ€ÆÞ2¦Ã3:ëÛòB“R×A€&„ ›Vf¸ÄËæöÂå³ç._¼µ°6Ô]HÆ>ÔKsæÿý?ßy+šo9wÎñyÆ%4£Â0äη†# cúQKªmÍÞ¾~¶³«»çàààpG>•J<”l4jõ½�¥Å…¹�Íír§“s(,£¿\Bßþ @¹1dq%) Ypmð6';r]ýýƒ…BG.—N$“±4&0NMöK`ë^Í«Uªåbiwem§´U,5ÍM_ùn<$Óî%a²aK/DÞ‚’W ©ç’E�fÃ�Ö'RÉd<OÅ’-S€jõF³Ñrm6<ó¥�üÒ øTH~ÇÑr ×ß F“­‚$—¬Á&ö9¢d]ÔR{Ïü¹lF²—SÓA ûÀA`Õ ’XÂCLdÍü•úmˆý¡WCñ-·Íº?±0Ќ۴TµG"æ'<·Œ‚$½ ª1[ÏýPjæè_ê Á4±Œ²0»Ã°-²JÌO(™ÚÒb´¼&’M†ŸÔaè¿ò�DèEÏ\N¶ýC�Í�¯6]Ih1î—’Ù84Ðõ‡'Â.2›-Šl>��îÐêJR$¹4ZhHF[ñ!Ø Œ¦¢Ñ€c±#Ü"»xÂí#=@`€d“÷DŠÜÆ[ø°ˆØêÅï „\ÝrÅ2ÉDºSä¤ z² ”�Af�Ï? ·¡�¿øqæÈËáö£¶p‰ÍyBð6„!Œ3¦ã™²­2}¥�•oÕãC¡Ö~»¾º_ zŽ ™1ðÙe¦içkY:^χØÇ 6·O²Ð¢(»’ ’2O_ËíÄX9íàè ¡ñäì‡î'"±r¦PCRõ&'�Hç¡'CëoäíxP§Š4\)âñ*òDW~E!9À0 b×ó‰pŠÜÞ¢}B¡81v—k«ŽUœÀSh`˜íô›1|,œ¢0KAg†/…�ÒLâ6Mò38\g ãBØ×�¥»¸¿# 9ñ9�âÌØa.ÅL¼ÄÍ⤙MaLú+Ùð‰ÄÊ´1â|„…S}x3•ϰ 72&L:t$|FܼEûÅ�'-Wô¼‹à‚Á ›8}½Â‡=À.0Ĺn/ÊÞ: ›™gºBæw,½¼±oº÷B7Å^) ͇¦_× á2“æP“µ†ÆpWºh0ÌJcƒaãÐ�]ç†àóÐå‘Clb8äÒ©BˆÌ#ðX6:D”Ué±|XD×sˆhhÉfÃè€!‡°ó'0$îëL2]K%ï,b17�„Ä/X= l)ˆ£D«Šµb0ú tòñA‡Mˆ‰3€ñþ®¸¯Óq6Ž¢.Ѝâ"I>Ÿ {H÷'ù0ÓE §hñ[0öžÁ‰ wðÑD "âºHBèÝЬgxe:CÞW äø! í¢Ëöb® så<ÿ\'IIH€÷C‚¡ˆJ‡¸�ÇÐ<}£ål]TÁXÀBx‹À~@K< B4Ú‹�Ål6Î�I™ÿ¿?YtQFÅgŠ�͇3î•øÀ‹-ª8óÄÌëˆí±_7ʱ±CcôlûÂcw€¦_wû4öÎ4ˆûBjG«ÝHÍÔÍvW†œyÚF.Ø4ÈÇ@Ü*¡šB&\Á‹[†muaŠô,A( ‡a ÝþífC |“Ó6Si© ߢ>cë;Z ~Æ>fŒž)ÞÓ KhTÌKVÛ Î‘"¯¨†b’î·% „Ä#XœfŠòÝòÚH…!Ä l¹‰k #Õ�ã¬uäBÀZøA<çÃd;Œbué׊4S³z¢u¥äqB€!•âáµ²`­!i&n%öRÞ3¨¬6ìÇ/k„|P½bj4<ˆ¢ä·Ëf6¼¼ÙˆìmUr/œ`u-à(a¤ÓÔ¥õPbݵXQ8Œ|¾PŠE/tà!ü5“ù)Øú\=d`»ÌF* :¢†¨/VBÅcÕªe 92P¥ ºµ"Ü&w"ìVxsSa»÷w!*odkÁ:…l¬WÄŠÄáˆ|Ô—Â@øÅyÑ8 GØ­Éj»Gua zPms­½£¸Zâgâˆ*@ñýFnFsf¦­ç›56 œ ªÁˆé/òÄBÓw·Ú6–¶=y ¢µHFnvo¯´g4æVÉ‚è ¦ -©qgÉëøÛ­w¶ýþ·_�Ec"Î7¦X½þ�ná]¾¾Çº\Þ€¨K¥H™�v^Ò¬jgvÊïm)«YWª„x6Büåcïû]£˜¹º+ö<ñq ¨Al‚�Ù¬ûØ3>Õæ_×ߺل|‰1¶ÑˆÐÁIʬ?xÅK~Ò"f¯n[Ï»âj‹°{þõ.þ<)lº°ËVß^<ÜÛþ>YhöN™Dž�®µél1¤•Gâ·ÏÒ¡L{ýß<à¾Âù–s´³Ü€—âøývëÜGƒ#íì}×®îñó µ M€›âÆJˆÝpÍçãsíê/­[çæ Œ’û³ÒŒ7Ñ&;nÀa4ÖŽp÷WªÄ9¾‰ãÌL7šèeÌ=oéìÎÁÒÍ äo‚ÚŒ!ü·u¦�”Š�„åË´›}Ö¯¼7E‚Vàä¼Íx gú;Ø|ÿJípª}`î_-Ô€­±y} &<…« ¬Òâ¹;âí[ïýzâ4[e¦�3–£Ž›úÜ%)SïÎõ `x‹Ý¹_¤NŸ«Öh�)Gn–¥€p¯!Ë«ÞúÝTþ :žûÅ;™‰ÓI!ɵDÍÌ«ªr Æ|ôþîh§Ë¹÷Ù7q: ~¶l¼‚é´RbÌÅ‹ug߇«\ýoÈ8B!›!ŒåF¢ÍMº*Ùs(*„Ƭ¾a»·ÛÅÜ{?¯MœÎÏ([ ˆÛ: AP0ÛËÊ…÷¦{úbnEùâ/§;AÎ`ñãý ¤iÈkW€�ÀÛº¾âu»”)^ÿéÞÄé<Ù(À�)²AÜ&]•n?ÃFÜÏ×ûÛÞÜZ®/åF¬ýú8À–dʦŽlP%qß�À”WW2ügµ[g¯�Mœ.€¡å… JÚ¦É'¹iuç kYeaÞsÜŸàÅ›¿\:5q"¦Ö,Œÿ³Ó’$´NE$qfz«óÛ±þ¤£àM�?Gg&ºAà„ˆL�Õ¤ I,+¬ lÏÍ{鬃åû?››˜È }†B!dÏôÕ‡$­6!¬ÄÈç¥ò­¹X®€nygéÙËg&†’†s\kt¾bÏ*„Ò2!I`-K“ö¦o/Å:³Ž@só�«KCg&zxƒ3úJºÓ@ÖÕ¦Œ�Ih€1›-›·5w;—~ôŸÎ©¯ÞþÕêøÉ‰qËŸMf]’[CÖx¤É6+Í©j`›Üµå{w˜M?ÂhÌߺ2ÙuæÄ¡Œ°Ä¸†qbw’Ù*29íP’efZ4²©2wóãyÊdñQDóÁû×¶ºÎL ¥¥…Ä—›TOh �½/"‰Œ<•‰(¨+qÅÂäõ;OŽv¾[miflÓ×Öƒ²Éœr0`idIlBbèôáÇÿ”?«LÛ÷ï}¼ÚÈ>sj€7„¯4k·ˆOHÖÕ¦) ‰I >°%原yv ?ûTþ‘½µtã£åÌà±£C}ìaSƒræPè8Ò’d™Î$¯Ã ^ÈÀÊlçÉ“‡F{ò‰OÓ”+ës·çc'G„WChôèº}s:Ã�·$Dò³à-מ�Áá±áCÝ…O¸j³º±07³>;Ÿê=sf¤ €�ù’¿®ÅŽ@kç É¡Èi ÙAË ‡œÈ%`"ÓÝ9ttxø`W6•ć¼Þ*{åõµÙ•µõõÍr�ëÃÌñÿ¥BKˆ•�÷Æå÷Œ•ctö³™$Rª«§p¨··#ß‘k-Àxb«­Q­ÖŠ;»ë›ÓË»;ÏX:dú92x. >R2·VŽ1œ$g’8 ’Z$_K¦rÙ\G&Ó‘Ë$2Éd2±4@£5¯V­6JµRyo¯ZÚ«4ù "A2ËAG/S÷‘šùcá#¹ËÑCˆÁ‡¤7›ÐÚb¼ ‘g¼áå/-`æ–á¾ qÆv&…‹»Zæ¤Òôô¬^à�ì/‰XÌ’ÌR9™Å>·ÖŽ @)ÆÑóa£B$ægJÒëÀýr@‚$–…Ë0&è6X‹É0)ã;�KÓÏ×ïCAb$’%©ŒÚŒö±ò”YOD(…x’üx)ú zÀÀ²éG‚d/“t)SÖ/)#©Å =‚\ËVZ$ÃOh€m¡˜z.1?©ä™œÉúkEFx1e?’ØHÜ�$1?)ÈRã…rë̪’ÓÓd†I�ÒˆdúzÎí3Š,¥q¥>gjÖº’§§‡­0r$S²æ‡š„Hi[™5F¤g ¿`�0ôû½ï`Iââ²øñÙ9_³Ö�VIn…¬ªÈp“X•f‰u—ÉÖC/ø)‚-¶­Ìª#|XôÁm"ÿØ k�·2³ÜˆŠK\€²¯ˆ} ¶%EÖ\ßBtIkÍΉyÿIXhAZSb¢Ë²-M àûÐLF¤M¾•è–ØÃ¨‹�×ícEߺtŠ-â¿÷€-(û–¤4PCöŸ÷³ªh�Z¢¡�lѤ°¾u­á>–•Ç{øþ½­íSH þÛÿ÷‡ÿ8üÇá?ÿqø�Ãl…VP8 HyPë�*>B0 ,íÛ—+í——â^¯ýÏýÏÕ¯ì?ë?ÎüðqŸažßïwì÷ߺ›`;���=ýßûOùñ¿ßÿ¼ÿÕúSêwøïî÷¸GðäŸÖ?³~þåý�þ‡Ýÿ÷Ÿ±ÝH?¤OÿýëïÃþæù¿øç½Üÿ†ÿ%þwÜù—õ_Ÿ_¼ŸùŸÿýË?u}€ÿŸlô§ÿ}þ7÷_÷ÿÿÿêOìWûïóÿ¸?¿ÿ�?È¿ }Û~ÿÿºüÿ¥êûéîsüëÏÉ÷ñÏá÷ϾâÿØýwôÿÛ7.ÿk>Y®gøþ}°ü÷ßÚeÿýÿuæŸåÿêúþ+ü‹ûçäWï/ùþÎÓÌ›Û?¬—ü¥üÀüŸ—XàÏ?®²þÙûÉþ Û_ÄÏïð?e~?™[ÿÁþcò«êCüúæ?ÖþÈ{Îýü¿üÿóÿ»ã?ÿþ!þ�þ‹û×îŸøïÿÿõþ÷=†~ßÿá÷(ýnûÿ‹‰•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙS$ŸÃ½[ù{IénÔAKz½Ô ×ö÷�¹è‡Òü�y_þ9IÕû¸™Sø%pí­•1‚%)åóHùåe§\vÈò�K„B“H59 x"¿ß¥ƒ ù"gË?€’¿_›ç÷ÏáŒ4�áØœÔu8Éæÿٽߞ6¾I-U*bÿ nµ²¦/íLäÜ0Š)*IVê]et,2@ë{\]_hÂ÷Î,ǾÆq—ÇžëV|Ë%$€R™D ñ½èLÿalJëvÁùós©U›~_!ZU4ÑÂËs€¾2Ùæ:-¿Á(‡ml©‹üK¯˜€½RZ1‚£ûô‰o÷0á}ÍP09jØÒë:VELp¢Fö髌Qÿ}XyQ�'g^ƒ²¿ 7‹µÐn~ó'ò(£D´n5õÆÐ}ô„L©‹ü�¸vÖʘ¹o¹;ø�‘cÙºéÑ¢T¶©à„º´“ƒôb­ 'Wm3„ð¾¸;ÑëûÞÏ.¬Á’AL¶ë°¹¤RQ›=‰²a’½ò&VãgËGà@ÉSæÂ2O¦ULêÙEBb~éÏÀÆ÷ÚÙSø%pí­g)5Ðz^½¥ýˆŠÖ%Q…¸ÑËŒ«QMï„å`É^uÀ�³Ù I_àŽ4A{wÈ¡`š°¡M×¢¿G]¯ì°¼IЦž…m�vIÓ‚«D6®¹–¡ÏGml©‹ü�¸v9Éi¨n[ÿžïïV'O4C};îµ÷gVå3ïƒ.¶}ãÃÚ69õÀ�|c;µC^±áʧ³ÆÁ4,wÛüÔu4·¹×C)¿çÓ¼¥Ô¸ÏWstô }ËôB'|ä_…J&+Æ„ nµ²¦/ðJÑ7”cÁ=k'ÚùÛ쳜l� ¦B6,Á�:P”C.±�εÉ>91Å.?GÙM!üWgîá{·€‡HLj|HҦϸKwxÎцè=ôMS² JÕÖ­9ï±·•Áòº·H£«{ ÒmqeºŒÃŽ�$Åþ @Ú [£U;¡Öå{„>8œÒt–åD7Æs�ÿ^Š9¸uh›v}Êëéøs5!7²’g0'wã•WÙ7Îè0“î‹­QaòILœ–¦ì.~‡:öº©Ç½X °°ß8{átêù¥ÝÀ+öNI�‘¤%;qAõc~޳HxØ[XT/ù|9ñ”À½æÐ£LŽ#pí­•0â÷cOËþ—C�ÐkËiýä^{$jžâYñò“nª�$¿.9ŠQZÿ¦½¨ƒF•îÕá%Õ�Ù¢.4×àAÕW€®ú^ztæ"JI;ѰQ7ÚÍ|Q_„ø�ÓNÞx÷+:H·±¹þ Ô@ðç8Ývæ[ìdrþ{`e*ic@Æ&ÍúmÿÖ8MNó�ßG3ÙžŽÚÙM€RxxKº8ó.]R% >yl·š )B"� ­Zx7<Ôøj.æj/hìaíÖ–à„Ø«é‘ô_¿?0©nÚÂKS›¿Þ'0ÞDm%•ŽÚ/oh�ÕÖ(F´`Méõ®oq¦…† üK¯•¢OVô—¬ƒ¸¾þÅr(Ÿ:ªr¼E… ÌäÛ(ÁSr£E• f² ‘î#¼ÈÅn+B’ìþˆœ•Ùþ a½VS'£¹éÌd�Ûß?[åzÿ_Vì=ØÃ‡Wöë³2.A+½EG=W„}D4îºkU¿ãÔ›=îÊ'æNúžÇœ‰% Õh##ˆ sŠÖƒ¯nÇšŠLŸpp~u€ÏnØŸ¹�*Ø��U)³O¬'ÈúÇ@3AuIÆËÍp]\ø$¥I,Ëë÷MŒAëáéïêßµªjø³ø›iR ßkʨ¼�€ùåÌ$«�ºÊô¦0“–ØcÎGÐ_„¥ã‡p:æ ©?�g=Óko„w²Û Kh¿¡@€ÃýG*RGvŠzÀ±Ðxónãã=y%ù-zg'Ë£€é¯ô»œ�ˆhR¸ÅÎq¸B?×Ò¿Ál,`žD7ÄÄè¯fÞt¯ëÖœS_øf<Ö¼í¿LŽV^ÁÎéá1ÎõTBFg„¢ìÌCyÞ Þ«m‹¹å#ØÈ®«™ébÉBhº÷‡L´˜÷†vôqq6Òĸiš¶3÷=œ¶2½žðºýkò—î´áò™ Sl½x 6 }®F´xÖHv¤ÇÞ¼@)âd#ÎñÈ3ÅÒ©÷ññë\‹ø"�üà§ó~è>©¸ì[rËX±FwˆÕÓ^À¶bÄL©S6±Ubà†‡¾y×fÙz7a¸{+püD’3u1‚û` J:’}.gÇÕÓ<׉p§=¾ÉË—]‰i‰†›†Ž“«úßõ9—G†€zéꯛÅŽÊðxªà:ÿÿ˜ðÿÜkNêO0SŠà觘bl?oäÕÄÖ>æukŽ^U5ôB/ü+M«ö^ÚM… ìžµ–Ø=3¸¼±µ:óþRk5aú�&nÜn>!ÄÄûy®«Ògóâزú©ÀÙ›ðX…)Dþ3!¾I€RHCV…ìhsþ÷á¾…‘Êp1JXš­>èÒ4Ø„¦ùK¹ ²Õ$@s)a�îì?md¢Š^hç•züqÓökQl±ÁîØ·Å,‹.™ç’àšL¯ò]¨ø<aRn¶zИ)ÙC>`!zññÙ&û¸ ®ئ»ÆE\þJtd,o÷PXÿF©%E¤zÿ=ñZ¾âúÁƒÊãõÞ5§ ¯³oªî§^¸Ô~ý@œÆ³¤•$�ÁÊ…ê¿×�2çª ÚA ‰äÇÆ 6ð|ùq»òK�ÙÃEš®ëí¯qO3ßá®0ôˆÝ}}5€xäÐ}3k[Ñ ±Š‡hÆÃÆw ¢W5R^úNÌÏ‘LÊ……í«(¬µõÁ^†j¡®&2„óžêdÛ°¢«BÀüxH`k*¿à›;:}a˜ç­5C#®L?Ée‡:‹Oø¿"ÖÝ^pCú!N�C÷FŽªË}”Ûš—*¸�¾3îâY`ÉÈtnnÖ®Ÿ…›Ñ_àÅy­L øÓ Ö£twÜ….‘ÁS‚¥“*æ6JÂɃ|{'(¿{…aã½ÞЕ¡ÒÿMJDË@ʼn…ÎVõ9ÿ ‰Wþ…_¡!lÍtàIìDE¤M$RñP±›—’¦¶Ï6Ðc—%^În…Q`ª€s §‘•8ŒƒâAµ“ÉÜ0�ܼ±Ø[²4îÍsÊçcô"† [7¼!×M ¨¶vèó{[÷H�·Ù,;Œ›[*Tá·®}kÀQ·L¶-hîrCOV(»lÎJËË+.«<úKb)†›g~çÛº_ÒZêgcÿõÝþ·•]šoê×*^¾(P<¤êðD¶˜�ðdúO­ïÅëê†1Ÿ¨ãì‚ãÊå Üä{&ýpæ�NP³vE%ÆxÁÀfPéâH™¬\qoâ/”z€Ã�WçÀ5ÔøÞ¹ÔªhÌñÙ‰¨(‡ú0Ư´_ >%c?Ü<·ã/z;jÖ&áºõÂvŠÙôP×Xr¥/·^$d(÷7ÑTÔ¹M4þºË,õDRiÚHíÍß Þ�x|ÃÀE«ã¾ÉY¨t3SI7*jÊi´þ"¢¼‰[ÇxWÝb~†}E†Ñ⽇m:#Í�¡.gç(¬Ò\�¡&u‚ G: ª“‰à6éŸu3ñ ÎÔ&VûfÑ&­*S/—·>G»ž^„ÇYVF`Ä€/»‰•*o®sn eÄGvºhÌC¶M®‘Ô>¡ØÇ$¼kÂßGâr�V%ZomQ™‹ˆç×ÿòŠ;Âã¾ÌüøšC¡±’ã˜gZQ'ç�›ù).éÆä~9AŠô†”?UÕPúÕósMøÐw葲yŒèC¾Þ�“w\Ö²*nª¥_\kŒ¾[:Dò~ºdyy¸w›Œ'æQû†Wü?…p†CJÏuDäø$ËHŸFbìqäÁgŽòY“…'Ž9�¥ËÁ;=WÔ‘ÕÇzî^ˆ4¸’8�@kîþ\|Yù¡0d=™ŽÚ$�ÛËÎÁgÿmúzáøZFù36Öv€5Û�©³h†[ø—Œ;ѭ黺ˆÇèx ¦>v?‡ÍÌÎÑæ7〜W?¶>‘—¨Â¸f8pñw@°+'ð$}5ÔëçìV˜Ó}ñºÌ Å�ýµ²›bº]òím G8аä}Èvt¼œêÝ‘h©VÁUyN¢íüÂjûŘ©´³ž:Ê;‹§@†ÚAO§�G"P…2§$'‹»Rõ5Gò«$«ýv1ÉèÌ™¾§£Eáy—E¢/˜o}ôNGä•hÚ²šul§ÙÏ¿ÚWB)Þ¶!ÌhÀ/¾2DßJTë> S:^vÀuüAþ REͲ ¥¤„®s£´ÍßÐ܃Åñ˜½Î5TK7¨Ü“ƒûÙ´Z 3�“÷àŒ=NÆ¥c¢jz¶›’È…pœ¥.�oªÛýiÅI ã6¢TXÓ Ï˜£ÊIÐ,uHB•ôz1ó/Ìö[½ø"ÓñŽãR…85TL‰ö&ÿ SU™9�øøªLãÄx3—.û_)ò ¥ôÓ‰ø«Œº¤´[Ï5ÿãýÚ~á<­aç„I{éŽeÔ+õyÜCMRµ´�Gml‰ÒB“Ói A”ô¬ôÍvQ"²]–9²[W;O¿ÿäv/Êf‰¶"GG�þÜçà68P1S–æ·›ÑÛ»Ãîæ!wM»¼Ž ëØâWˆÝß<¦1¦>J…ˆ}û@³—”mÍÄ„_“_Øn‘䧦z‘¤gQ^BQ¡E¤%ÈD­ÊÈ �8Î\ è’Ñ•3|ãW§ÐXž'ÛŒ£:pÝä^B`"ýBÀ�Õâ›_ºä€Y± f@Ü’ÿ¬¾ª‰•1‚P7Ç$ÑH+N¶•šWKOb™14Ra÷[®yô /�1qÜØ“Á¼³ÈuOS�gñK®+?Ìlpù͘Ã#oK! Â�šN&"eL_à” Ã¶¶TæQ.£Íf[ýžæ)3ð;àF¦oÉ0×"ÖÌÜz‹œ—ç­K~àc â í–mÛ/uGœÀ/4CÿM˜ìª‰•1‚P7ÚÙS™apMé_ÓÕì³€ò.«AŠM¡ý^ýš�ó�Ò:’ÉG·ãµT´×ä¾o{e%Ïdê+Huæ©eþ @Ü;keL_à” Àá2áÞ\/?|š&O�F€Ô_Øa±k$ªröËÉæcÓ>™™¥}·ÒíæH/ª¢eL_à” Ã¶¶TÆìº ã±ñ:²m3æÍ®mŸ&Íg9Ÿa¦˜¿ ËyÞ�–«þ,¤˜¿Á(‡ml©‹ü�¸vØ 5�émI=ûPt »‰•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­•1‚P7ÚÙSø%pí­‘þÿÛРk.�L‚“|´žáìç'€V¶‰”8|\®=ìfO0…øÎñ•|®Q]mTÓ4Üf­�Ã@�à­$ °sìÍf¤í×çF oÉnâõ4Œçy�¦@/'Ÿñ˜�wZï]B��„àä_ûV·i¹a[V?8±ˆž2÷dŸ�gÿáwns§v˜TÐ÷B^9"’/ö‰( —ÔBÿ7Ôå?D÷ðÙsduìö°Ø½ÝO©’Š­˜Ä=…{ |�zº‰¤ÔüÆtúlŸ,¥Ý—ªËâ´ÖpŒznI‡f´*+ŽÕ2ôÀ´k„á¯ÿ}ºÉÇHÖF0¹JRl��Á“â;•ò¢«ÍJ´…ay’ey–içzŠ—rŠÈ¿[÷O¤l¦„ѼL`m5B°xSM¨x¼H><£†áÒ¶±|þãçºVò×C)WgJ x×ÂQRŒ¢ØÆèÞ°q*Ù‰çìâ9ß•÷d£¡¼ ¨…:6ý§ÈÀi·Ýå<Ò°ˆ÷#mUäâÆßD@–¾¬‘œ³›ùkW·–š*Aÿ²¾ó»XÓ* í&˜`Ì…Çá”ްð‰CŽ„4Æ3Ë“¦@�ëîòs0kÿÿØì¸Á é[0|@ê'`;�.•n -‚ö.Î?È„Ò4ð†qZð"eMÝÕn½%Ö´ ¬•Ô//·ƒP ³¤'ܸNæW¸aÜÓÍ` ˆáxÞ²‰)¥øS±S£;¡¥§²IòmÆo-FÈ_óÔÙîâ;9Kް ]ÎjV„'ñN çáÍÿqÜ ‹¢R£”_ôax‰§$ÿþO ‚-ÉxBÓ¯¼ç¬þüQëô® ÿíÃA‘§£›êhü%¼ –:ÉËêR‡ˆémKl+œX÷ÍØòöy%¿òS�Ë�›é£3S#ýãqìhv™D’�§ J*„fúù»HÀg 'ªÚÖ‹~çu4äÏÛrJ1_L¸ñ ßuîÏ“=r ·ù^wÿçu·}<¡h)`ÞÉíRV{�Ê‘šy.øgßœ0 ²©ÍÉ‹Ù_*òø¦H§ì‘¶B�ËçUãï}K:úÇ1½Ö„'|Í©wþù„wÂn|6^Z–¿âÛR1ösɤwÄT"Rù»ã[zvßBʦÔ-Ä…þÂßm`V“«#ॠgz<{¡Ô˜þ‰€��ð÷!Ô# šáz´«Äº<¥SG¦ä/EÌt=‰‹4¦íìØ ÙH'¼2)†È(.É0ÿ½«mO¢íÁl€ôÉ¡Q©ÞAŸÚ¦i� ]Û¶qÚ¿ö(æ†52µ‡ñÄ‚a*¾Õ2äöï�|LÿrлGNÍUìÛ‚èN€g§')DñmÞ‘ƒã’²yPôU�3·on] ŸYëù:ÿ€óÈŠLÂðЯãÑ5ç“/èþßéZ©KðÎUÏ•ºÞ0i,ªµcôÍ#b Ûƒö*gIG+�¬L²)õ±W)tËžjÝÎ�–¤fª@äWŠNwy™ÿ)ºÔó}Î?)`äPø:ûùÂJ•÷~†GÍž« °»žÏÉÌ!jú‘a‚»‚Y”ãöù~}’àP†k‹åG¯šjãñ ;®'¾ž}U¢ìÅù€÷ ˜”1ÙZ‡œ±Î þ­Œ.y &U$©nl»þâÜ›¡Õ·0ä›86ðÎ0‘/]�oLlo¿œÀ[%04„În±§$ø¦‚™�µ–†|WˆíÅG› Ê‘¶ñþÕÅ8Ÿ&kñ@þë;`ÿ!A1ßåŠOþ»qÇ8G_ÀȬ Ý&œ­‹¯v¸wE,¸.?ÚDhUæW&áçÀÈ› Z�3¨Jr[ T·n”ògý@Ø%n7¹« W>r2 fÛ!��dÿSCd&'FëÍÞx$ò�Eìƒc,b7“JäίᎠÊÇíM$£:5³;¾�ª1úª© �-Y›ñhw+Ãxï&TžnoÒÄÂ9Âɘ^­è¸^â– –½(âb„f¨q†jÓFžB–>fQ£.⤲HÄœZ“ÜÛ­%7s'Ê#JÁŽº·5}´ÛÈ1¾»DÜXGóeP!�êPìá„zˆ«W¦e#Š%ò`GôÿTxÄͼ³· ˜Ïnv›‚‚É%mL+@ûàæ±+º�·°!4ÛD Êœ­zü8A>5ö1n;ÛÞÿ½‹¹á«ˆú<í�$¸ j¬]]ÉÒµÈ+5®�•U»elö—å \qûÖêAâ¡p3Hµç.P�`k•ݼ I_ÅèAD8»`4 ÑPÝ!}fª~G1]˜_gs{µ™ž¿V€Ã BŽûŒQ. p>«si6õ -ˆnæ"èä–1hãP÷i)î>òÅ ŽŸèG~¤Ó-É”Äûüț">0e•h»˜P½c+"CgzÖÿFà´*õ$d�ÉÔ6ªÒö`m„™"*cF’#j9u$¢å½h&·piÇA"Zà÷Ù�©‰¢ÄšH£ÿ�ë136è0Vyh�é1tï$£ÞÙÐŒ<ìlLʱâMe ¡IŽq.îr¨LßÑÔ®#}q§="›Ð>]Þ+/â•óD·g[Si��æÖá;ÕõlRx¡ )|‡„$º;�ލÿÿumº[jÁzNÍ[¥èJã‹3ÐÑkü¬î=$†•º¬ „âEÜi­s*y”€ƒŽ'‘_ß„&¡ïÌö�Ñ‚º1¿=ŽjYmR�î‡P�—Ð.{%€I¿’±ºR(»§b™ƒºâ_ÔÈà�ÂïÏÀJ©ˆ»[IìÀd1Do5C8Dßx‰Õɰýà‡&¨±ÇààåT‘$M´Àè�E¸| ÒfIöÔrÓñRU�Dl®iØ÷×Ò¾%f1 G¥ýœA6bÖÝÇ͵œÀUŒVô ch}¦I8é|êËH�^èJ` O¨wÛíìÏïG�$¸9ÕîR•ß\ù<=jÎÞÓ ‡ªì–÷K=Dhä}]aÏÆqIžÑ¦É¨µ±#D`L‡J/ˆDJx8+y¡q;¨àòL$và Ÿ�l÷@bNf‰x_Z¡óì«ÿ5ÝaÓx¯‹LiÖ–ÖçÿIsâFPå1¨|–—ïJvÝ‘@¯Ë=è@Õz{6ëkUÔãµ,·»¦N…­jˆÅ]ëA°XB)0(ÈY#ˆ<¿[–›•½\X²7D‰ÛÀ?ƒ�Õ€»|aä7è(±þï›w³wù¢Zq¬ú»Žb¨&gÀ§þ]~‘;› �£€E,\€ß™iƒnZã·wüXLÉ7ÈlUì­X}’ïÝñí{ ƒ¾¯emLÓ”W·ÿôc…çÉQI2òÈeHîtj„۹݃`cz�@½¨�ºgPÀüU8f&ET8h.,—3ߎ.îðƒƒš ©NÀé�/Y'°“¨ ÔRs[§ 1®VŒ0 @=6^{�5¯õJçF¬¯†6lÚF ±ýÉøZßçNǤ-À²né¥"á6>ž‡×¦ø”w¡ÒIÁÜjó~T1’¥KcÀŽî;kÓjzn|Ûq"I!y]æÏ³‚qÄÃ6”FuUì28USâœuår­‰»êkTAØL\&–@ÄÅß´1ŸÞÚd¢‰×»våò2×V Á{J*íËãݪ$]8pwNi×Áoý—KºÉˆ‚ÙÞ‹¾Ô‘—Š€I”ð%-ëb ¾­÷ø7ClÕKòøu¢¿¤]�ï_Ik—ûimW<2r€-[ Š.„ñCƒÞfõÑÕy¢,ßx¦©kF=U-�^—8¦&ÓeRoÁÀ@ #Ql׎Šû|ñÏ‚'_a+~0Z)„¿5Ú¿í¸zssÖ'®2!¯Ø]ܨ²@x͇ e�, üÇ+Ô*Ã<2²ƒGkÔÐ<0HB>oæ(Œ úÇîîÆ7 ^Ã?£äŠö˜ýû\œ¢,³¸°ŽÅ5 ÔZž#Œ¹<¡¶"ÏNâL1…. µ‚¤‡ùØœ�h;Pyèb Èír¥ƒtî÷®G[Çí¡RT¶X^cöÞ=1’= ‘Â1Y�“^ÑàBçÊUWq]÷þ 1+ð²f”9f7­=ëþP  ÓRQÐbÏ�vÈl™hS¤­6¿‹r„Yö=…ö†gëãíZÛTp1ERø·q_p=xï ÷¶†/€,ƒ¯ñÆÒ‰„xù‹Óv×ä‹—ÂEz_1ö–+I€D?'ç¸YØ-|#cÕ‚Át¥�êíY<@¬†Pä)©¹Ãkvi“¬/AðzGw2‹›8¹çÈö�²fRŽ;�ŒÉb ³ñÌa©ÑtðÓÏlÔÊ'ç« È²Dœ½ÒdÀó²ˆ ädýâ'ƒñ­¯Åì­«hƒl�$vÛ„JsÙk{‚°ëwœí-^òJ¼‰Q½îN_JÕ¥Uzë$º g÷=€‡_ôœÌ%¿*vèê°4¢mÛ’ÝÆI5¨LŽ3&³£†ê‰»§Ÿêp’Èp«mVÛB]Š!åjxFµ(œÎj[:C Âdý)¢Ïf0>pv@Avð­c…ªÔt‡ç+Ù�3«� Ź9K•]AÑ¢èßh‚Û¦ñysš# oݦ4ñ°µTµL9òÔ>Ï¿tÚy˜|äÔ£è¬p8-$IEköîD› ;²äiRr™ ° êò,Né…ŽÕc=Œ&¾’¼¹""ÿñœë�.˜ŸÁ² Î�MIlL¤ƒÎ62EpÌ7ú™f蘆‡H{»ÌøÀ ŠfÎV&£Ù9Æ’Boj�1 oÕëÜQ¡Ë'}[ÒgÜ5»!ŽÖuI•ý_ °à�sºs·þjF§êëÄøsïÂãËZ—ZÒÛÎÕ¯ Æ+ý|²r:Ûg²X8Ï�*È�Exé_âÐ¥ÿiÉÝxª?9ö·e¬vE¬Ðë¬3[Fª}Óþs@ú¼ÌRŒOCc"à‚�Æo¶Jíɹ% -ï Œ+…$®s?4½™ëüÉ€Ÿ*K†»|Ñ Uç´º'’,9V� Ôm¯+¼.¾VÇ(#ÉÿYÖ•žDU—°¢ö-3ä�‰ß«¥=n ÿû«âÞnÿ$Z~k¬Fã-²—rwo,}m4ÒÔrõµÖëbãN:¡ÍpßÊú1pˆjõ‡Ý¿^n†ÑczÐq¯‚ÖY« ‡Ç¯�Ýΰ˽>/†q–û[7Ñ`Äz°QZX“óër=å �5FÿKχ³/]EýPôÐLã›ëþ=Iïºr'‰Ç{­�=M )5›�ø~'/þü4Üýi뇬§ù£œsŤû}0 ¦’¦íw\ç:ü¨¢xÂtÜ¿ë.”´hñú(ñH›2ØdÆuÌàé6ÜJ4¥›ùW{Ϊú ªEû=wûw(&gß–‡âoÕúN—ù†ôQãdú›3"߆E%®k·¤UšíLÌþ ;àÊÕ)$àÑB°µsš6œÓZ‹ý©6r³šKœÄO‰Ê7FŸ›ÚK/ˆ… ‰+¬Œó¿ ¤CÇ;<¶³­5u™Y*½rW¼½úÕk�Ã&˜á§€ÿCð)}Q܇Þäþg*¡¬D¶¢åˆ=“m«/ÕÑanQyÌ–’ÇÆ¥Z) w”¿¿™Úe}|Ýó´{âN-U£—p»¾&m–°õkæÀÈX{Àû–m*Ä ÈaXGo6`¥ûœ7³¹˜Ów߈…Ç{YŠÐ$¾ZÆž; �{~ýÜë7úÀ ª×%عhmƹ»ßÊÒÞÑŠ�Øç8¬�%©ëÓ”Tµ„„‰4~:ò‡Ï‰ºœ­ÍÛóæÛn*÷‰Iõ©J@ÃUl”‡_jž…ûšãt´û€[%2º'ÒmN&Žý]™ÀÐótšNeÛ¹ˆP††¨"Ù?èWGÌKòžÃпSh»PP§÷kR+wzLå¸TÕcVéü¤n¾îd“c”TAÒÕBÁèÌHØ•×\zsˆqËÁç¢Tt§Æ†Ò{e'Iø¿žIž¬eÁ¸l­N ô£@™³¶÷ô|ît‡7J'•�èÒ#{az3D5T`Hƒ[@'FWІk‰‚ u¸Æ;‘gG™‹kËFÌ b%õ^¾-Î GýZ�ç�vô¦– k§þ£| uö¼zƒ]•sœ¶·žqpLZ×Tµ•\�$hš•„kÅÙlŸíå�ŽðÛR6&Ù3‘…Eþg›£JðÂÃ¥ëƒÏií5PåL<Øôbyšgvóò NzŸxÇ`î3öÈD ùfΞaXnÿLôýÈ$6þ Àþ HæCL ËþqMäܬižua½š•”rcÍÿÆáh°‰™¼éN©ÔØ,å¤ÎÿóLJ>Ãþ¾ž˜û¶¾ÅLᄂ¥“¹"5÷·ÕñþY5YÔ'Ü…G„;¤ ¨“£éGØZ¡ŠÝg*§ž˜6¨Ò•³Ð/œ*"Ñáe·Û TcS¹÷N¬]JÚ¤•\oÔQ{•^5t'8NäÔ¿èv>¼ C¼’Y†²Ïƒ0ñph€u{2½ ×®ï0±LÌHÈ“šbÚÙ�Âêó�ž¢é(n#À'“³é ÒXZ íÑHJ:¤jcN·m®+ ,mÕŒE…u²èO^®¹-wâ,±· ÏíBôÞÔ��6€ªny[ÙÏÇ™ÁƂχ2ôÍ4YϰékEöE�àß·|xBáoŽÄ¿DgÀ§^è?D‹ú<à·îÜÞ¢+Ø Š¼ÝÕÁ�OÔ�…Œ­ïÿñKQÔÿêGãyÿ«�Õ‡¥Çöi*«ºT‾âÀÚ¤5”ß’`õ4Vš8ØH3ÓCW¢¯¸º´^ */r*� &äJ®öyyYçεpû†¶ýQþjJ«†q�ä9¾8‘‚)¸Ð¼)��_0îl®\ÓçáÞҋăw¿ðì¤E÷¦[�ˆi§s¢êé©LtÖe�ŽY%í�1Û¬àÖV=݆ÚEöž ñ�9 ¼È—mœ@R`5R½?Í xû9ÓMI4HhÍ3ß{”Œ>ýp“5’߬0¼Ø´`„!Q PŒ@Ø�íª¨=5–¢k1u¯?�¤BϦÎÑb(àåêràò f7Æl;_Ä–û&º�8 è�Áñ°­»­FÜÆ 7ù7ð'F“7ÞWôÛÈ(N·ß ÿï-›ÖÌTŸHê�æ©áF nxZ Oa®¦ü�y3(Þ³Êl€ +WÖWbÌFóÇâf!ËM¿XŽ|±…‰ô*õBƒó¯².‘ßd¶=ð„­ËH"‚hýB !ùÌ0'�!`S=Öø&Ú)!ñŒIh¥)&¸%Eðœ´Æ1#IJ.¿† ¹@ßÚ„í¡têüÐ+|:| „u š!è¿W¬bRvFKص‰SŒ5¯¨—à´þ3PÃCùë�ÐäÛ.-(�Á}>ÃÅÚ¢æØ4S®Ç€Àp%¦ƒéDó~Ï,TpÙ“‡? 1Š(+¼EÍ$Ì.§ÆY@ç$†Ññ,…y! è âÀåâmª†c´iá")þ}€£ÛX…Áƒ*/']TI<â„¥íqtv,<9¿|'÷Ù©á·9?‡‹ýÙ‡êÒ|šÛ��÷ :KyÇð°hŸ¿‡†%ª(÷CZØWT-ä<û)ñ-`oCÍÌ9øRÇ–_ !9�¤×„Rì@lžóOO_��(É%Þ©õ>'u`ÓÈ«~�NÁI†Ò3ÓÜêé;Œ, 2 .¸àyÃ(jЦO1, r j¨ñ¿8áái‹ûLÄY€Lu|?Ä›z©bÌ®?á7o˜·Òo#12Ã×#,õbìSæSÑ®?L­À(ïøô¸33®f¥›ï¿ÅŠÒc†Cš™•ŠDºü5»4OŠH$ñåýÞz`_öþ©Ì`á°êðìÙ ¡ ±[’œ©ÌÌÑBδLŸ×|ÿÒýþHjhl�TÇj½©–,ÁYN¯ØÛÈ–ý€Iþf|?J¼úëJ:N†"µ/?ˆ`ÖѦ%èí'•­¿Íèš]¢=¶�Q~¤àd7/ÊBøê_Ð¥<é?á¹XNù2…½ÿ)ÝêP.î¶2ªú°—,íg1¤= ·D$YíQ0A&˜IW*â…|ÊïCÚ[5¢1(’ê»"/}Ù)*Àû'XP›XfàT×^ Ø)fºUP$[PÈ«� !ßN¯êÀŒ]´}ïlÒ2…«hÔƒÒÛÝ5-õ<=é#ÚjA@ÎYKâ1ˆ~É"üxRýeŠ5ŽÌÙ§ žº_?#6Yê˸UdHWÛ Ä1 ŠÂõ�Rõ>\dñŠòÎ!Ê®‹ïÈÿƒ7åGª÷t°ÚׯL¼m}÷¾¹÷ßÊ®(�“�MôPÇË­ëºeë€à¦ƒb諸�ŒhVh Þ&PJuÃhÒpqÀ›¦-ð>ו¬óÔôE[¾»pÊ®¢5ÛÁÓÇtª8û/œJŒªuʪ{zu6G{øHN¦3Øá2"*˜ˆq{¾JÇßUR4´½qsFH§º¤ÔººÄ‡›ËéõeB‘³Î%��C5¹”«vqËã"Â3íÁ®úÔXÙŠU–™ 7¼NL— ëVd_Nž™R>!좗Öz¶›ßÿlw §„(Æç×�ð•;ãféÓJ­Ÿ Îé:'Në¾>>ùÃ2„Ú/ʉçä±Ñ„üØÊ°=—�NÃÂ2rx�OÇûð�«B1�;k«6 5]= âI½K? LaæE¯f„ÂýIŸÃ¤%Z¨;³Îp&0ÂôÇ£µç„2¼�8‰"A°¯õ— 5›“c�8ˆ’àíУ‡óª°qÖ~1µª+Lè£R'èôÇÈ�0nf‰·PéÝåšïLy¥¾g’ç½�&w�xÉíI{•oO1Rþ)G ¥‚ h«·ø=«¹žzë÷Ó½3Öt$VÈÙµŽøBšs�àÿˆgz¹š‡L‰zü…óXj¾%á$h@ž™¯ u $¿ýv¢ÚÔ Ï3í×kÐHýÑ‹&v…zö0p!úÊ/‰14ƒ}Ôý@æ8–¨Ü¬†Zrª}žøzlˆ3Nm Âër¿½üm¿Ê£kR³±˜àÈvmQJ„0�~:ƒ¿!ÃPT{Ao�É­±Íó°Á­8`¿4ùÓGð}ñçšÅ ò×ô´DÙBˆôù(’ÙœÿU*e#žßøI­�¬º’$Ý *£V° ÈôòëÏ`—ÏÏÚ¤Øp´ehqU® äj©–ñØ$ 't:/ýãÌnÅû‚‘ó{—òb+dRÚkÊëKÞD¦¿pu–.©¬ò…¡/ÌÎÑûu†=ˆ†C(%ºË‰H5)àöð§l ~=æ:‘4ToMv„ûƒ½!`dR‡ï©µ ‹€÷¬ÖYF;.·Øï!ØeÁóϬ®Ôv¸õ–D²ÜöÚOs¤DªJÅ‘ì¾Vùé©Çf§�¶þ¾›)˶}$t·y¸Í{€¥]ßøDŸ�ŒP¯¶!g™mßzêášzxµýÁç�±¶¶Rз½ÂU¨ªk$ñZ¸Î„»?9÷S Áµ¸%´Î»ïÖáÎV’¢­™ðJ®ÇÝáŸu2ƒ;rb£ŽÇáéÃy£EžŠªÚ/¹jÿ+9[sº¦#a´\Œ—•š)ùlêÒú=SÃÜö#ûè›ÛÓ™@|˜ÆEé�§”¾¤5¿ÕM²å‘ÅãÀR_Óå@æ*|k¬z×ï¥ d‹¸œå#é2†žåraSªÎ ø(]oZãH–>RŒ[?¥ò €ºˆT®g:™®ž$f†t áùRWŸpaó³;³ôîO[=Ô<±5¶»l¸ß 4áþ¡Û'§;N9Ê62”â6˜fí:Õ ²¸Šï]ɘJfUÿ,�žÌ�ñªCj<ƒÈ+l¡X?ÛŠ0L®qÔ âoù*Œ€NXxP§ 6%h à\¹¸Ã€` üœz@Ê{)ûÚÓAFÒ ¾YŒ ¹ØÙ©aŹI0f*а×HEÿEEѹÿ�;ãÃÄ ÞÔpnœƒ¼láoóÝåæ÷ÈëeJ4»k0ö8û¯CÆ[!ª¾¼Æ@²€�3òÌúßܯTîꆃ*ë“m!êNu` 67q¹8<º a)‚hùÞQ ÷!Ó«ý‡¿®ù«)aE• _êæ¬Îsª©¶„†L¯"´Õ±«ˆ1ÙÈ„ʼn�_éÇæ½Â=9¿ l¿âÇ Ö—»y‹�´75%9ÝÓ� WoÑ eº—àâÃÛaZKï`<çÎ6“óŸFH‚”+ ²ÃÖ É�£‡™˜4Ê=ç!É.º ».�T Ù,ùmÜ·^l¨<êf­éͱð`ö±Ý‘÷�ûµ–ˆ4 [½l �€ÀïŒù°mT”Û´³Žõ}òòÐ!ïphM•/¹�›|È鼟&�K;힤�õç|°wcúס²S_d}¿ÕFOîŒt@ÖÈ$Ið$~¤O ·¢¦IÁyW«Ç6¡†.Ó�ž*__»ÌCÛËv'y'ÀÙ!*Œ£"Xutº<ž!²£×…Oµq…P.üù©¼©3‡b—¨CÝ„ Á F�…³6ÿhÁªÃR+k1 ì²[˜Š &ˆFïx,Ì—º'$ysê²ØlRI44í_HújZ8´x74ñí=MR[Nö£ˆò:ܨ¸d o¢žf×ѰÖõ­0CK4B4FŽL =úýdð |B2á5F ¤¢a›:QUŦã�¦Dçܳ@d†ÖÂe-#p,S§ýG‹œã¡brô™{5ÈOžvÅç:nâÏ‚@Ͼ6Ì�šóôPäâ]éFÀí=ûA“WP6a¥°‚k‹ä°Z®˜éÌÝ—·)_ûß©" Òè¶J0,IØ×ò@§~|@U¹�¢#ÕÄá¤` ~JÙ™‚b‘퀿…0"Hq‰�"ñÄ@ŽqÒ¶mƒ~/µþ̆Å}óýsÙdtÉžë…Î�èm>(‘wYðÜõÀ±Ö‚Õ|v̓þ7ªS!Ÿ.lÖ÷š̶Xcæ%ÎëŸPIݵ9k»XsÔ‡�¦Î) ®¦½?Z¾”B–—–dŒðË׿B;HPh±F€�zvÉ—´ŒR«g#f*F„w�ë¥SFkÑÑÚ剪ç„sFß~böÄÎ-æjßT÷ö¾0ö¡•„ÃeþÏc�Â’*×iÜK˜w.|�¯¯ñƒ…|·_À­¥‹Vîü íÖ$!ù ) ? RsF'ñÀ{¨gÜ4XL�Û~åf2Tªë÷Eão4lŒI|԰Зœ”Ü5+«­³ »·$ËôÀvA×.æ’å;Ny-2düNc¾ #çÄšõŽÑ€'ÇÖ/ïv4$j’C”IÇ¿÷›Œ%þ4Œ/ð̃Z¨ãz&¨ñÜüÙ:~é„>ØÌiÆ y=¿žN˼…!OEé5,ôoKÜï±_ùÀüú)Ûç¥ým­ ¤Ÿ¾qò8­ŒÛ×_À_ÏP²>“þš‘àúÎüߢæ&[û€Ö/²U šË"mã„/ƒÅŠ@Šv?o�Òw …&_³>�Gÿîí)ªv‡ÈOq–o] Ñ-D1naw > ÿ«|$Èž·ÒJzIAï9ÏÔÎ?PÖÔ2ZuúHk�ãÑã”Ëé–$ðç(ÀÕí�ð·Db FU¶,ìÿ�~çžX}þéåÒtÍéÕSw�î›ù^ü-=žµðÖxÉ*Êêϰ&¶+@g‘Ö’'òô,µç}í\Õ ØþIƒøÉ޽‘~LÙß'Qâ¥\.X$*.&(9(n‰ç˜¹B°ˆn#'ò„¶:îhñŽñÌ�ó<ŽÜWÊþ–œ í(Óð—›³ à\4êŽyȆ7joF¿IÕáž9äî}.� ¨ÇæáHÐPc´Ž©<ºËÌ«‚޶ƒÃR”ÍB¥è\³æ&=áÚÔªÝÀ î|uΖWJð¿KØöJ• VŠBÓͤ¯J+ ø2_öÖ‚z뛞�!‹7È<�#)Ÿ­!ý`Ñ `Ð#%²$ÄÐè Ü@ÎP; Ê^¬Ž˜­ˆ• x̆¶¸0¡±¥‹'u~ŽJôœL³h<Ð!ÂW8Î!“Dtii.ZvªÂ…§ÌÂ^Ô¤µûELŸËõFÂ+VKjèqëYQ�0Y�¢“€Hh1`rBC!E‚I_È-ªè¹ìj‘QW—4±ä0ê¤íßÓ-êlÓÓËg .XÒ—Pz)�Ýþ_¹÷‡˜gXÇêì¼*öÅÍÏ!4·ÝMK�Ò¸ZhTë^^M~цáÚ5J˜¦õe´†JO)ì‰Ö2÷˜°Ý3ЂÂž ,ØÐ¨•“t*­×ÏÌ“cuóþzAôäaBõ×Õf�²zo% °,côºXã^p#å§ÊÀ<@ xu8âj?ò8}»8ö3ß9Äm;€µ¢)¼�æ›÷:˜éVMSÊq8íL9JþÍuuç~Å\›¶SáäÇ-�d-c …VÍÚ̧µè%f3¾™z"sÆÁœžÕ>„GO‹3µª†�hˆÈçõF_@rè¬ô³.rñ«ÔÁ¡SIz”ù˜}F¢JLMÁƒ�|ØÉà já+`d^Xªˆân¡ÚF/rÚ¼»Ã*xFTêÊž¶JÖ4\€d' )�OqÉ­�‡[áž‘T”NóLï…Íñ«¢¥ÊìH•2à¿#Ç/d»¢ˆU‘¾D�<‚É™#æÕ Gç¾Yèt1!Ç(D8„×€wû­~­6&†72„F³ÈÅÏ|lõ©ØsLƒKŽý÷Ê8À[ù3<`Z;˜SRq©ÌœUÍ)Pr<ó>ø¯ÑMº¼L¬OY³/ ç¦ÒO/I—Ò*ºÇðîåàu¿ Êb圹+O“�ys+-0Àå,Wøñg&lWô|­‘;dþŽëÓ[ebn[3PdßàƒŽpí¡r±¿›µ™¦ œ8cØHæ4ˆD£ˆ�-é®)#Œ>{UmC©·°ë‚šƒ²—ØÃ±p/ýÐ{bøÊˆ‰ÏÈÉg+ç\QŒ]‡`öIÿA_ ¾üjZs�lÓÒ&cšI»>�µÚ€1ºš ¥rŽ€ª�2�…Èú[ˆàpg-õ&O�ïKÿ»Îñ¤7 Ë‘%|>¤•b£üÎ-õ_ ¹ûˆTS?áäÜ4b4‰ÈÁ¼GÍdV¦´@¨­ 6�ã16îprD´‘—˜œaËGçh ªéKHˆ5MêV°ÜX�8¹À¦xkê.ªeG’3Í•�X‚ì�nrþ‹ãðúÉgú’ò‘“5bnN-_t4™œ­º@6ÍÙZM5pÄÍmÉ>h´Ã©ù÷(4®ä]< wåk‘Qß~1n ´Å6;Žq3ãôÑ%rŸzú»»Ô@=o] Dôç$”k×£S~‡Â&œÃ›_›‘¬µMËœkøÀ#_§Ø42‘³_Rç‚2¯¬øŒªi…@ßAFR®æÿºz°M3ÊC!2>vsȳáÎSp©´ŒbV©/ÿ)5<ü ºƒNqæjé}��0Dáî4Tk95(!Ë/T\7ɦ£W§¥F¸oÏñ¦ùþ5Æ9?[;È´®Ò÷ißMzZ#òBP_�ÏáRZ¾Ô7kéAëü@.¹r$“-¼8ŸÛLÛV-j®e²%$´©hiðýkøŒ|ñŠ-êµÑ a¹&µ_ä`R÷�µ7'ôR�—Ü{áÛ < «¾PøâBâIêB[Á¿¥Á¢6„±3 §V¨€e�ª›‘¡hÓ�y ±F¸§ò¥Îv E„;¯™m½ºœ3<­÷Ò$Ì~¥n¼a¼Á,e2(‰£_¶¥\im� ¾FNÙ~UC.È¿æ‹vhùÌ߸E­!iÌÌöcÔ-º¶âL¦"#7k^ƒï�Ž?1mÀ*e^È\ֵ×’Ƥ$ÍñÍ8Ô_¥Dêò (¥’¾Àiy ±)ïÁf[«t„Tű?/»ô{¨d}o,Dë‡�©�AhÛî3ˆWøÂ(¢ñ OÚ|#&ׂò…$ ºAûó0H- ó–+¾³îg'µQËZßo>Î+¿M^´ÃðI2Ô=Ha‚Tºðì‰ëÙ`'•¼Žp�uŸBý¬èéÄjj¸ŽRö$2a»Vþ듉ï„6ZCD”±~{myó+ /o'"¢L)[MOln¯ª£Â|ê"×[åÞCà–ùò6SGËÀjÁkooé+µû-®Ek\ ‚OÃ\Ï[�šÓ'²ÄpàgÒÈ%ÊFèO胱OEÝ=õövOÕ7t¨ë‰�Å‚Þd c1÷øÃa "y5¿1žô(äD漑m‹G÷®ª×@’ñ¥FX°¹‚8ŽVï¸}ôßÍÇzzô®¶Žþ²Sàíâ*bÕðC… x®—zN3ýig¨ÔáµAýsaÄ;Åyð€{»ÔZÑÏ•�YG—AŒ¿ÁÑ­*‚£ï"Q³”­J}ué Tþ“Åêý4xº»¬B`5k?¹§1ôƒ[ßÀe%Ç©Ú@Ú=–UNª•à°$Žý}>ë9Ûw°@È›™Lr­6õD#.K}z/#]ŽüÊJº�c™@mfUÌî·�ŒÁ„šê)M÷!èÛÂ7ȶÛc,œ‡VI2!‘Ð(A1õˆ]S?,Ìg Æå»ƒ)ùÉ?‡ÖŽdÚ•¥KËÙ¢H$f0uK$ã„ÒWpðЇá»5¡FÍ<àð›ùú þ y*VVxâlÙž‰—§Wáu�¢eÄ+Õ?=ó^“"Z3Lá,…k(CJ$Er[…på&†bw,ÿ{2½1¤-£þëñ"ƒ¡=îÌ YèS�¨ å,lÅŒÌÄ¡U÷›Æ‹H_ñ×oŒ 4남џ¨d„°9Ö4í!ÁHa ÖAÒuãŸ! ¼r™wåØàõ÷™ßgáBtct�e+iþÕ`Œ#nx’´ëq@aXâo'¨Ö¦bª�œ¤–ÃÙª§U¯Ê A Ž5"]œº¡øÐ:Bò%eî6@‡tª0HÇ—§èؤTü¦žoWô‹°WžqÌgDÁö0)©¹õŠd…뢞�qÚ.Xp$cW|¥�/L×¥7åGÒ]YdÊÁãV`4ÉÈ÷‡€|dIóÙ“U¾ÏmoT#gùíÊW¤?™lÞ+ùoM׺U†ÒÚÌ“äA©…ze>ÌCÑeöÀw’ IŸ�š­¾A]vj–µj‹¹æ%iùdØDãˬ¡6)‘o{ ÒÝ‚»Í‰€ ,L‹ 1@ÈKFMo ,dÈS齕ƒx 0ÖÐØ¦äs|½ë7hW  ¬­G£ü³¶³ì-sBüm;jRþyíA€­<Q´¡cÜdMë?¤L�ôtƒn�–n”pÞ<Û'™P«‘RCp– Yt @œK^µËz:Zà'¯Åd–ϯE±C=¤µ·ŽQÏœd´þ4;¶I£øÃ?T0Œ“Ê?Æ Ä œ£>Uz�ræð³’ÆãbÂ4 wsLÔí¯ðjþsÆsÍpo'tm$a?µ}ˆd+C,Öá d|û Qž½ÐWovi§ó�öý²ò•5 \1K V:F¤b/ ꮲ¨·k?…N½#,páJ1$¸³kø*„»Y[‰?ßµîÌ2ØAÛ*«-…+ú…ó?ì"ÿ²Ò`iov¸±ñ‹ÿîbÇÓZ�žƒÌÏÇñi¤çR’0®PGøGÈ×IŽÜʲ�F¹Y™Á³‡¬!;äÁ¶t�Â7@h+û²]à[vG£ÑFXbLJ�ë燎ùÀj\¼ˆ3Á·0QA¿MKï¸nT´$àZÉ{\ø[™ pK_Ï¿ü5îý>ýó»„?»¶¿|w/ ËÅíM L7?ðÊ6ÏÚâ£ê†ÞVŸÓ³ãKï µ-§‘ΚWìüÑNŠÓ6®pŽk?ä’òðKù»P ä»x øh&”W>.)C#Á< sýò»Ì ßÊ䜗ŒÕCØ -Å.%œ¢!1 * x÷ÁÕbôðÒG)¾_¤Ž8‹ž¨Ro<޳hócÖ( ]†Ç©õã'è ’8 ©fé&Ãt—“Sçh¤—e&fT´ðc�Œ¢Êºj\Ü' è®E¥;¥”ƒ„$¦¬±}mxBg@¾Ý„tÉ €P®·“‘uå$¿ EÌúð†Í¼}Í—$«ëàÒ›E¦™—¶2ø¸*”Ï C·ÙèÃ’PIƒª9çK^‹8eñî;be-æ~›&7aBGÿ‹wT×ÜçQ€&›ÿê3 ¿3ÅKˆOZòÀþ‰NÂ0�Rs•l;×ÂÙûJÜÿy†™4 `µ˜üÙÑà3X@â+±¸ÇW‹‹O R=\iÙ¼\h·KÄÐh�ˆL‚XOál_ÖˆiÑ«p ­ýòì€ Í¹äSé"Eíã—éséöô™/]#tTÐ�lâ_W‚‹ªR˹§¸æ&ÐÕ~Ÿ€‹õg¿"·ö=j)Ƨ ¹ÁwÀ\ Š”±mÉm©É; %Ïš»I\üoml.„;|ÙÚµÙ^¾Æfzeèægz<ÙÌù†&ªOø,I[‚[.ŸƒYeÄ:ëg+ÛVeœñ+msÂLýým>‚Tý bSÉ¥pVÆü³†÷¦^~Îr)ì¤S2&§°uW‹ì#þ‹õ\€H¥BŽóýÜ:u 98xS,÷5WùĦͮ ÔœòóU„Øœ¤û0KËë±.ÈÌÿó†‹ÂžcP­¯¾2õpXíwMAx;&ÿø¯«:*4ÀÏy/;–ñŸp´.訅b䨓–ø]ñ¢tîJ™Ü¼ošI0y©ž[E±ªUJÜòÞ Ï†‹z42ˆ.¶‰“³+Ò÷þýªc ´†puHšô×éÚ‹�RLû'O¿y’ͤ3G8¿Q7KIeeÞ,âmõ1tr!_ŠœÕ#m4‡µÄä´âBœSñkø¼uß×»\¯ÆWíõ—bkŽ�«Ot¢€HŸvRÑÂ<Ò“†¥ô¬;X¨äcÔµ!«Ìc4àÎìYèÝ•óÝub."¢Ï¼¿‹)iàËq©³$F]ñ?)ÿõ†Úû9ÖåÉ#½3½�Þ”Z„ÛøG )TÁf#‹6†š''sŠoeW%º³!ÂôT¯é¡ûkŸr¨óçxUê€dƒ{ £¸q²„ÜÕ"õ¬‰½.sgÞØÒ"lV/̼a|ùA›ßòëÕkòû€W·�Ú'6ø±ÿ‰½›*lÐ� Ö-bý>Ì“”ÉÛ#q¤ß.À�g1�âNÍXrEæd>±[ûYœ(™‡w$jÖáMDçå13%¥BÓŒÓä\5Ûx-‰ Žx#…)¼�wÔVØœ5{ÒðÿKüªc± >+”3矇^l SuùŸ û'S½’††sÛ2’ñ'wˆ© ûõ9»F:ªME Ûýj-€h2¦…?¼×jL‘üÉV4:Uz™ ‹ÂR™q–a&EêrÕœôгX?»èäÅp öUÌ]¾¬�®³ç„nz ¦>‹²/žúP§„�¸÷P+'®]·„…|L°Â™o&ÝBNi²siÓB„NL¯ˆrhßuc„A 6ÆåN_„[¨¸Æ7€…Ðs ›çÉì#9kž`(×uP»{ÔR@a(/ÑäW‡Ž9«"ª>–ãÌ, ã8»ß+«uÁîö7风kéÁ/¸¬ Á”ŸÞ0?‹Ã{ß«óŠ-<ç’õbŒ�ínGFßÌ#Èõ‰vΚÝTj}’7Oô67×Ü¢Ý]¹ÍHÚ~UOôÈM¦;H™{Õ&:¬Û¨‰³ 3OŽ$œ·è7Ê;:þFôÌ!s^/ª ±_ä­|¥M†@éJÒÛbä YyJIà¾þ u®Š�˜ú<•þ�g8´üT¯®/þÏÕcW ÄRæÉÛ€Á¢†Uåõÿ˜�G¡Õ0Gf wŒ$V%�ð Ÿ1£Ì2Ä´^Éëü„øs�àž“¤ÏiygN¼OcîÖ6°Ãå5l·ÔR�œ•ÞϵØe®‰‘ãw ѹ–®~ÙHÄÊøåÈ`W*ð˜.üÔ XÏqGó¨œó©8жïÄvnËû±bûüÐÉi˜õöL Ë�5‘?­dë_އðÍ´y¸,�¾É? ¨ïÏ•¥SBC�{QÅbn�|¢ªíRž¿QÖº`eñÈ8¨ìˆÙTòxh‹fc'‹‡Z�اÏx5ÿFCÁø¼' Evn H»Ü‰fZ><ÓÜ?¡é’DJ�)$Ó…% "†®#òy#µOe]ÖQ² 3³[ Kô(@õ?âúòiDˆ€ÛÊjD¾Gù¡¸ÊÕ4\iѬí&ÉÁ˜ßUw¹O–Ü{òFí ›>;6Àwl/(Pf Æ3æÏ;IóùelÐ/ÎìŸÎaÀCõ>„31éÕ†�¸+­¾òBºvTT´9¦cBÙîRÉkвEsØé‚n-µ{«hϘÇC hðV¢Hså)4ûú“Ö¢¾i# T‚pˆov’¤‡Éäuc¿µ&‹ý2æÍ1[ ÈPí�Ç®³2×XÓþ¢?I³Óx£žW´ó …,¤mºN}Ÿè7pczÂê¢ÅCW}yßç´›ÁM;b§ÑF;NèŸ[Â6UêfuŒÄ•Zr§û‰U I£†öú�£2ÊH\G×å¨c™; àó¸˜ì$\"îdKvõÍì ÉÞtŽŠ Äø ŠÁ¼ˆ~g) ­fUïoÙ *™"&‡i)ÚÉøýIWÉŸ†š·ó óÊ]?ÅyàÌ–º.Ê…­Xh¿>"›ºÍ­Ö‰¾ØˆT@æNÆ×w½¿8=*F;=¸M]v§ˆÿôÔæNü n]r`—lñb¶._T�eûçÞ30Ù<;O¶`•8ÿâöDÀ¹Ñ±ŽŸ�S@aWrç Ñ·AqèÃÑÞú›?ÿø ÝÎ\vý7á51ô²vgº¸ÆV,`ï™/ ÖŠ�_Á¥Šú¤™.RwC%¦dV�ÖncQ*vÜ lͯ3»à ’•W$[Œ©Œ�I †^u\\¸L}ƒ–ƒý‘ ¤‡h”Òù2‡™Ëµ:T~qUòmçXŒBtK¢„K¾n©Ô�í°AWÃ4*³t>A„}Îp>°¦"•ÀAãó‡'"× æ$úe*�&ï,±2F¿Jµˆ�È›ý‡I`I6{ó׊©y®L_¾ß ùt|,xž÷>ƒ£›7ËRRoŽZ�áѹ Ø®»0h1_x¤=ÃŽB“”^Gúæº]Ñœn) cÈ1$Ô‰°Á‡©è­vrn9-ÒoXBAó¶’;Öéó@»åÀÝœ$P9k¬‡“‡Ü¸Å€ê«ùZ ñE”:lQlZ¹— Ì€Û¼|ó3A¾¬< CeE ºoêöÕ܆Vª'Šñ¢ßê›èI¶ 2‡ä*éPzÇD²ÂGZÕò[œ^ 8©t¤üáÌÀ-Y2GšÅÎWXÐÞ|» º1ÌkÛ…ñ´4#”ý"½ü�¤\c1ÃÒÔÎ*޶êR+Ù@_Å €ª}Ô‘½@\h•/£½¹ °Èò$ò°ÖµàELw÷ »I!ýÜê-mÎï§áæPÝ�vÿi`"§Gÿ*…i@�MÏÃÇ•æÂ²à®ÐêÙq®hyÖâ»æ´“åƒîÐoåïVÅ%€¤„ÍüJéýOÄ¿W¶}xwË©ÈJ2~œ�Þ]âKYÌÇÛ /ÀîÙ8: Ûy.#ƒl�™�¼û ~õ(¶$@*:lÂqÈ¥K‹q�}�-b9�•zíÔš <^âJOöÉ0jò´v¥èÛ‰eX[þ?Ã|t™‹ÇúÝ¢¥S=±7ù©ère=îìݱsø=ó6Ê¿g’ÿ†š¾ÜZgTp­GôGz¨Ý/ƒ�P¯úœv&œJ:Xm~ ê%Ä*J”ŠÄÕuÝ¡_­vÿA�cëP�?…îDü§!çñß(\1;Vy¹KD”æ¡¡ ô`A=Xï1Ú‹©Þ½ßËW0•Y5žE½(Å€'š V»¬ ,•Ý»ª÷÷1è$…*Á3#­!öÀÛ¤`ÒeŸ-“öíÄ+²Ñÿ1ì¦SmA¢#Æm9~mªÿ9D»zϽØ[€uGÛ}Q e<tŽVð[_Ñb­ûS@î×XÆ7uù§7qƒ3cªÒƒ0`%CáÂÜ1pÀ¥íø@šá™\–€ÐöîA^MRN�X¢ÓoUØçy܆ss†êÃ)PæÍåú¬sèʃ¦¹¬«K 8ã–MõÊL%Ÿ®¡|L!þמ¿Ûû„)Bâ¼ÃPå›]M›hÃ2õèéo¬¸ðæ�àc±Ã� ~{kx^Ä.â ”@ÂXÓBð½sê¥Q_pŽ/y÷ φü£YÒÅÍL¬É¬b$LÉñg¶|Ö­JI>¼hÈ9þÀûíňUÃ+Yrãi-AÅ?"ö¨î@ïªn'ö|ª– ôVÞlÈOK¦4/ �÷/ �”Öi÷žuÞúmJ§ÖEHâCþ_NûÏìë.•’Ï6˜f Š’tÄ1þ�E|*ŸÀmµåí`±_4J7çþ¼˜À–,æ£7bH†Ž~�Ö º!y¹Fç¡f¢ï$”k@ú•ÿOóÚÍcÆáG áH#¡ Þa8ý(è1X©_m°¡D�Nº¶MÅ�dèE]ìx=v£ã-ž4 ]p¤- ÈôÑ)ùYD ´ä05<â,­ ×uTàQ‹²¢:ê:v@MFà4«b× ‘n‡NWEå”p°kht¸Bdcü·ƒ¬'‚©ÿÖw$ âZª;µ›«©jxÔ�×�¤0Øç^ªP&¼›'%pÆsBã5”ævñ{rÙ†éÙcz¿6:!èþxækàlÅ`ç­÷ßO¸¨H²˜¿5ÚžÎH'ë•c� Où�î5nÔɪ™Åà3qÙÒH^Çj¢rj!b=ÀÀáæ™kõ~fp-ïo¢ëºd)òLxŒñ–×¶sFeå)æøð’ìT H¢¬ƒ¼ñtME;â‹¡H“Ž—«û&SÙ:áÃÀŸˆq9×£"/æi|b~òAd;¥¾g§ëJ…xѽ΃CwtÙøò�"†ÒìoìûO_Ã×'{;N=gy µìÀhw†:äC7¨liѪk—{}\¶;¡l`ØÀ§ g\ÀµîÊÀI%b�‚ºª·q ˆ½v²?¥¬I¶ìƒ.04-Zì³wMt~>ÄÉ,�ª8H_íp–PÛŒI0œD‹&øä¥ÛJݽO;\Þ3ù¾?�Ð.×vÊ9?ÂNî€Âís*¯Ú!ÉÇÐÖ*cž´Y¿�‘«ÿ~k�wêŠ]Š­$¹˜OGÂÓcÏ\©9ðægÿñe¦Úº>_yÃ:ñF´g%¿d]‘ÖÒŽ²M1O¥¢Þpͺƒ–^ÐÕ£B>žÃ××F±â+ªH�X+EÑ­ZD`öR³'€Æe›¤ A¿&.éÚó6ç¿4ÕlhO‘ H¶,Ú¼À¬¥Ü0wæ.(Öñþ‚]î–v%¿Â…�´J­gÛ Â9xéÊ£÷âʇÇ1i!n¾›Ë¨ÁKSÀ‡) ¤!!v+Õ7;…—uIí3>8!N"+×ivÀ Ø’Õ6Ihžš«9A² 8fFˆÑ<ÙÕ�+‚ôC6äí‹wè�Žábð© ïÙs¦-§Æ* š¼ârE†q9[*�mëhMKhù”p&E×ר³³(}æ¦ìų÷}< µD[û¦RxÄúR3+•) òdd÷Pº‘ù5¦ÀÛÕùi'&™oÅ4„kÊ©=Ê÷Ö“µ«û£ ÅâùL°Ú"«"ðæžRbÄ*–,© *Í0� ùâ¬L¤Vxd¼¾®Èì­÷…âõ RŸDi ê$ß.ÇÑÛÇ›x:u+nˇ›S–$& ñIxG‰J½_EÀž"6E± 75ª€Ìh½YÊ�¯81Ž)z  �[3¢­’º¶SW  u’ÓBLËŸñ "ëpeÖ«žÇíÎlàrïøÐ^:¬.O[÷�ti)¢_ËZ# 1�! vÛ8M!@N£~ ç/„Ó§9º]\óêŽÜ03 -Ï÷Y!6� &0Öª%SÀTåÖ·üßhE0ì0üÿ·-±H§NÐ8'“¥n<Ú�¬›‹ V‰œ›‹ÒyØk‚ûÎ%ªÁ9rqD¯Œ{58êl©b‡¤šÛX}»†-wž©_·fÕB¾B¥dˆÊ$²Ë]Óéâ¤.�ð?`mCSšü¢5»¦Q"�ºÌx$ W_VÏYxºÈr´nÈ;ö¼Dô? ×nrñÓâ-¡'aiÑ76»)>“Á’Q©c¤¦qM#Û7ù‘ x µ#.Ó;”®I†pi6-u^l·j³ÂDõ$ž� Î|I ‹×!ܹ`à˼íÁÌ �¨·Ñ(óô<àGÆËñç²Rl�|OÞ›cÿ2M)ªÜÙMÇoÅM·Ô c³ {‘@›Âû"û ð¢¢ÂSH{pè Ñòow¢°M™æúÏ­Ôm9Y7‚Vú%IªGN`ÉGìpáŠw_iDâýönÍ{"#9þ”úw�‡Ëæé¥è#¾›ÁìöêŠ'% ž®ZÅ-(‹öE¥x!I6·ŒÕlçÜÎõ!ß='v[¼ɯ�ÄG»ô¬.`¡éZ$È‚ß,´¼£É™˜ çÓfáÆ+|âÑ Là @áß±¬Æ{¢L?}D¢ â,ÜX¸ ¢œO½å�ª„,o…:êWŒu ?»ç žîdù(ú¯è‡Vú¾qm;YJÀk£?Ø{ãàøFTï¯zTT+œœ»rõ_D¸¨}u! ­îv Þ™éûeŒ±?2‚nÕ-vWk‚ OJdZ4zÛÁ¦(Ç›tqUÿ|ËkLz1kSc»�´"Õ¶”`š{óx½àˆßkDDìb:ÆòÂ9€b)S—Ä—þzFð?^vo³s¶‚5;%Ã¥¿Î(úí~FD°ŠŒ0–*Ô7[š¯‡þ»Adsöæ¼È\"È,.EsÊCÍå€OI'H©Ò߃ äu�+О&`ò}§óË™€Ph=~nÆ%e#ÒJøh݇…Eä~5Oðœ�Hûí*M>ù"s§…—� H!øM¯•F¥—³,6Ì;¿×?+¬°x ¤s‚�â9ál;:CxŽõïßÞƒTÃ|ò’x—vœ"2HH†•²á%kæþÌ ˜Öá4ŸHcvìo2¼ÜíOÏHTÚL„U¸ßes ÷vo~?‡^0ó™ke Šxsó4²d¢½nI(”ô ×i1â�¾ ‚S%vøWö%|°$!чѲ—û5Å¢d×ÄÈ}'@EOrEu¦péŸjʇ…³%í�Õ ¤ñåć÷ºhýÌ‹CZ”tBîö>f‰6k¨ou%–z5|=s Æ˜îpZá¨2xœA´Ò:éI €Éå%šÕ? A‡ú¿©KyÚã™È[*�èëR1”à'T‹÷‡�ï~Ÿ¥eµ/jÚ2 Åk6ò„‚qs[h½;ï†ZPi6d§PÂ(lÊ…UoM«'�”\Î ®©<‘L4 xÞ)Pµµ] ÌÁnOÞP 'âz�°Z Ìø†G>yФ¾Oýê“à]Po³TÏMèæ}}‹lþK2(�$*õ3ŠÁc�߃®Ÿ1øA­­,]„³ÑÀQ®H»¼ñf¸û‰¦o)¾Ÿ† 7T<ù@E²MûJ·oü&ÈGSð+§¢Šá!#a|÷¦²LÌïÎÙ!§ àg`d­œZ³Êbòݬ¢¬CeGl[¶5Kh<º¦8@‚±Ö˜³.^³�NþXË#€³¶….DâŒà vk~Dlœ¢DWzÎZ¤•¶|ø87ñ·-¬hº‰ßî܆> ·E¬“¨i�z푃Ç^uHÜ`7ä}}N½Qž5’k­RÄ]PË|?7<¦6šðëZÒ…ÈI1 Îvf§IL­ÀD`ÜÃ).ë6ì�ÅvKeJœ7"�×ÿ…ATâã>qXU³Ò?<ô½� 2Úiãp�KÙÁ’SðÐïiñàÕÐÌ{q°…̸AnÎR0×÷Ä/ÖÒ½©ï�íû?Ïþ7Ÿ6N²F„åÃÖ)ÏŸß‚Š�/ÄUÔúv«çÿÆÊͰß+ßr§uüßu§ñG‡ˆ"s.#ɽ'âô`7‡5òè1ùö<°J”yWid‹­ãÐ'Áx-ƒ‚3¥©æÖÛwh€î?œ,¢†´ï@¡ˆç_˜(Ñò±Gn¹ {AÑÞ>Ùyà ¡-vºSo9�]IÍØ¬¤�XŸ@Ú|¸Qdo‚æ­\¾Y4kÝ«¹ÏñŽïƼôV÷…6(Žã KýÓa„¾El§9Rzz^ÏÊÜñ_O¾°0\í-NæòRÞª 8ÉŽH‹†â¡ØÅ†[þ‰+¨«ÛšB¡í„+»íÊ ¶1 Úïï`/hœm6´£);,®~SÍßÞif-„üBb^’nzm8"7fwüÇ™?”ˆ>,ÎQ“ƒ÷BÊ]Ð=q iƒ?Ý©dÌÔQ1‹¶ ¤6Ú3Dì5éö†í ú‘òùíAÀ[ª<½ø=ye‰Þ2Å�&ü³ |En Ùf¾©›ˆ-ò’ÀSù—ñA‘bø7ÜÍàÕ÷� r¯†­¨Ñ�F€¨íÊŠr®�‚=ç<Ítø¡Ùú:ÊÁpŽG~À / ªÒZ*¢XEÒ0/:Þé>f«ÀÒû%ë¼t‰2ïÑß÷ݪSr×­Q8)2b`ïРȸ¢�Šš*Xe�2?Å]Dm.ÖS¨›8‰È¥•E�!ïLƒâX·_œÏóÎr)�  –,˜°\XK"Å¡l RŠ_QF„‘ÆCÂ\'|�õ+A– jd„°€ºï‡è‚ÜÍy»7^é*p°ÐZù³&ÙeÙZ’9Ó]5¡+$?3i.cTnÔC)”Ý™°2=R.ùp“ú9Àã\ÌÛYD=„5+~ÃØM]ËÌ5�„Ö£D˜¼RˆA=Á�„ÜO^ºÈJáΞ À#šîMAÊ!̉£#+U#ÜtùɳîÐZq²-¯}²ÁÐ9]ø±/ö©wÿÊç ¹—«µ`k©º®¥ä"¾…ð(€ÑfOéÚ… À’e¼/ß§0 g$Æ·cQÀà­M1ÚKBáwÉSÈ2$eA¶ÐZЍ r$ð‘“I­iNåÁY}ÞyHs””8ëÔ_j£‡/W^¢íœ¿§ú,¶:dbê%ÿ«EE<ÎBGÀµ¿\Ìz~±vs+¹Ì×1J0^ÏQ|>«icÕÑßkF4§óMWcœÀ%°¤}’¶0:¡(ˆ}øÔcIõϲ‹µ Zj9SöÈ|¿DóâoØŸîF»ÿd.g¬²µAŠ5³�ä%ÙÖq%:ÿP„ëÝÌæ™èº˜öæíi»Û1…OæXÉšñjâת!=~Ç"yV1cyœ�¿Ç;H-ï t~!=¸§{Õã$hM‘X™·Î¤•-nŸ6M¥íñ§³»œÜJÀ€ ÷e€˜˜¿„p�pæH½„.ÃäÌ•u¡üYÜgSƒÆ¹ȶEÌø�ºpÉëî³Q'–‹ÅÚTjGbäÁ°9SÌrŠ›”9.Ý�$=FïJõ?L³³ÂMùtÀªÿª=ÅIê»}¬ÏK4¡_¢Î²•Ÿˆ)%Ÿ�ÑX©Qã´þÓ öÆŠ7Äàó¦¹î§V¢C�„¹ô‚d³жËí¦fŒ»Õ}b�\E�ý`r�ÉJ&ÔK�ùðŠËGxù$p«LªŠRÍò•–˜–€@–i¯e´v€&Þp #­P½æWÒ(C:ðCqmô�bú¼ë#­¶ÝEèÉÅÖsß-¥²�ÕrȉdD†²Ñ|6u²ªž†hNˆžÌç@Ûoâ~LÐÛô@T MgDTø? íRÚj»"·Yûм‚' z–ÝøÙ^òIPÒd=Q¾� 5ZŸ“ m)ÕÖƒm¹Ñ�Ç/Ï,2"ƒN}ä´Ùzôˆ<çú6+˜— ÉµTÇ䇩‘ÉéS�=lþçÕ˜Ýѯˆ <÷eqˆT¹M c[iº7R™_fCúâ»Æó’…œzµù5ƒ?ÿÆÅæÑ(«¤§¬àR›¸s¶úO;4Ô›y êÞ+24Q�ÿ •ã =ió+Id}ÿ—ª!.ØSÛ®(½¸oŸ{:yj¸p%~9J´nå�]¯Õ`Õ‰Ô¯‚Jä:d–ýÀW—}¹”�vhxjƒæ GJ ­?v‘€¶·U«ú§ñ¡>R›/Ú¯„é »Î™ÏBŽUÓª®] Æ× çÍü€ b¦Ì8]±-l�Y袚‡L¼f¶ÏLÒ>õO¡©‚ãŠú†rÎT¸Ìäs�Q÷37ž_x¤)ž�?�_Þ·ìÔ§Òc¶u½‘™ùçú´véÁº˜Õwœgdž ªF+¹5›ŒØQïB½vOûÕPV?ljÃöƒa›²FCî¾XqÁfÅÊâ¡Ê)rwș�.h"¥2¦ñXx»BS(e'Çߌ֡zŠÚacÊ×üÙÿIÃÉ3�Jú%UJEǸœq¢}ŸÓCÒ[µ´nµJ“ ó6bCú´- 8²e»MH[й£àˆ%�bY 5–1Ï@p”Ý[<²ìä¬ì‚Þâ-/ô pØk>Ñ?>Z%J3žWú*/öuN¿±+‚s¼4Ç”›?p$2!Œ¬gÀÕ\Mj…­¸b�rÑ®-¬[*ˆ'¸mÚ9(w‰^Ž ÿk³à`/��† @ ¯†ÚSV‡ÎÁÀÁ…œd-ä¹±É ¤/ÍÍ�wrU¾[�ð=a¯ö$œ§{¤8Àz¿ ™zþ¼µ’ÃÙêG·mù¯¾Ú9T'·ñmáp`l ?“¤ÚÄ~Æ9‡D²Wr5²QlõI±Æ|ÐU4,ï²hìÌCRdÀ€É0dW™&ª>$Î(u™ñé ŠÕœp±Ø,VPðÁª0ò!Kí¡Q�ôïw)WFÕ¼ºò‹‹-˜;$µKx§­ÆvÈ×y!È9·F£{ÂÙVUš�¦òÃÙ�ޝ:%ê/ƒÂN°Å62ýÃÍ�íþåyØ#1а[ÂLŒŠèðý�_Od4�ìîëŒz«ïÅÙñz{j#�8Ì® °òE¶¤2cÆ/U’ $TEõcãàYnõÙ-÷ˆã6µ‚N);ÎKvrmsÿ!¼ðÛížñPo®¹Š“Lî1E•Èm¸�c7�Œ ¤q“u™§ŠéÁîí\ÕÅ ƒ®(=§í8RR3 Ýÿ¶®+ŽÉÿX vë!6ç["’„Q Š0:‹ÅïÝž 6’ê俣ï½b>˜*iO³c(eʜؤ‡¼¢Y•x.XI&Áoº÷㚆+B0'´¤e1�ã ÆM„ÆÞ¦;³ï©Ú¸¡Ïñ—€}cíš‘ˆC\q4€SO[´¯Ü¤V|DùXRL5å”Â-^ò�«de=û°¾~?(äºâCn%¢­ÀƒòK¬û.ñB#>Ú5ïÄ}‘°¶‡7œèd³ÙTg©‚´gTç@ŠEhAùÌ ´6Ò”^Dg=^M7ݦŽü‡¦Å.ñÅà3ƒ˜3ñÔ1½>M—(*Þl(Ìœšgi¹Žºæ2»ëÆz×:“(øØÝöæOŽ ‚« ¡¨”"H@}Gºÿ¤†Ì;Ë%^Eõ<›A.AyŽHTˆ9‰V3‹QÞÁ·âÃt]î^ÛLÔR)˜‹¬É° 2ÕuV° +–ö_RnM'N¨°»_ÇŠ_o¬‹;+îžWmç3¤)œñ<�ÓÑ/f3ìšÈˆx#þãŒ)éS`C‚ö±C�ªF¢Ôó|0XÐf I9_oÍÃÀ`ž1 ­â¦ÄúQÄKü(OÜšA#ë¾%¿}Æâç@1¨�uÎ5Ùã.%�á¶ëºËIbVƒ c¬8ÉCm{¬)ŸËÞXA�ÒÍ ¶­�°@”F¯HýêhÃH/)/òëÊÝC¦æ(IÜ2|ËxU¶ Fõ¥|}#]E=·W;`´aQqdtkgui-6.7.46/examples/animation-dci/CMakeLists.txt000066400000000000000000000007141522615413000222000ustar00rootroot00000000000000set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Dtk${DTK_NAME_SUFFIX}Core REQUIRED) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) set(BIN_NAME animation-dci) set(TARGET ${BIN_NAME}${DTK_NAME_SUFFIX}) add_executable(${TARGET} main.cpp test_dci_icon.qrc ) target_link_libraries( ${TARGET} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets dtk${DTK_NAME_SUFFIX}gui ) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${BIN_NAME}) dtkgui-6.7.46/examples/animation-dci/dci_heart.dci000066400000000000000000001432031522615413000220440ustar00rootroot00000000000000DCI1003Æhover.dark¬2d1.0.webp../../hover.light/2/1.0.webphover.light‚{2:{1.0.webpòzRIFFêzWEBPVP8X ÇÇANIMANMFdwnCVP8LL/w€G§ m#ÇüQßú‰ ‚@ÒÞ=�o"qB±Š[!Ä"Rl�Q"ÄßĤmÛv6ÒÝvfº¶mÛ¶mÛ¶mÛ¶mÛÖØnîŸ1»›÷i’&ß#úŸ0á©=då¹ߢÓb¾¿¼°jp½ Xàm8lõ¥W?bÓc¾¿<¿rH¬ÏÑÿ@8ýE�¦ ?G‘‡æ„¥u¶ÄÓXÒî†0êjy8•ƶ7€eõ/Ñ̃Ö0âêø‚f®6†%eOÒìùð[ï:Íž­Óž± 4Ÿ6?b¦å>šOœè�¹¢×iÍãjj<§5wKÂLý_´*¡+”®‰´*´ Œ÷M¡ßÔ/×÷¯Ø°ïJ(ýú&C7Q£?íç¥ÝëVî»þ9…~SÁè�²ïêÈn({ì £Ÿµ.d¸VÒÏŸµ�óBq~ÅGY c#4ŠOƃ?o¯ë”W c.å ‚à¯È؇µq0ÒM£6Ä C-Pœ;žâÕú0äJIëÿµ)¤oÈ£î¡q4>У¹V§SHª…QøRfÊÜ¢¡ÛÅ`¦ú ŠAv�¡ð¼(ÌywÑÀ–˜+ôˆÂÄnä†Y×\ú]Ó9¯P©t<Õ“™aÁBúY 2¡šXÂAª½°d Å=.Xr‡êQ¨ ¨F—…5žã®{aM©Hª�¡Ü¢¢uƒUYïSù˜VuԨ܅¾ ÕÕ°®ðWê¢+úT›CwœÊW/,¬Ãi­aaÈg*§ð¿œ�ÊHXÚ:�GÁÒ!T|ðo.•ï^X;˜«amÈW*óðï •1°zÑY,AåþV§ò3¬vg…ÕÞTj c6•pÀ<*s�q‰J8 •ËI >:Š¢>!¸.•#pÄa*õSG ¢2x1•2pDi*‹ŽPï †#‚5ê�<¢> £þÑGê_À!/¨ÿJý%8äõ¡ Ôï…CöQŸ�NýZ8d-õé1Ôo†C¶Rûƒú}pÈ>ê¿¡þ2r†úש ‡¼¢þÚvêÓ¼p„+žú�S©T‡#ÊS™Õ…Ê(8¢•%©†#6S)‰ÏÔÇxáÏê#c'•öp@S*‡�Ñ—Êa8`•¾ÈÈ•L}JØ>õiyñ÷•¹°ý4*ñ¯7•°¬°yö0*½ñÏJe2l>�JTfüŸO%<'l�'’Ê2芧PY [¯¦’R ú�TR*ÀÆUÒ¨l‡R*•ÊØ×u�JJ¨ë¨ö€m{S]¡@ •?¹aÓ<¡Tb AšLu lº‰ê$ˆÞ7T´æ°e �Ê›È-©~ÌfÿLEk»©n… wRÝ ¿ùèv‡íúR Íÿ}¨F—ƒÍ*ÄQí#'©>É[e{Aõ ‰ ºvr¡QƺR˜M£ªu…ÑMT}�`›.Õ-0œåÕøÚ°IÝDªO3Ãx…hªJÃ¥C©ÆT€™ŽÕ·ùaƒï¨ú:ÂÜ ÷²#à9P˜“®ƒ.fB€½—(tÁlæÛN# ÁÇ)ÜÍ ó>QØïA=(|,+*†QØåFÀÜ;)„W„5uã)ls#@îÍâëê¶)¶º÷ ©ma]w…À³�Bz/X9X£°/–í¤  …µc( �Å!‡)hã`õDJg2ÃÒ̧)M„õ“(]Ë ³_¡4 �˜DéQX–ÿ¥™Ì$JïJÁ¢’¯)MC Æi~Vƒ%U¾SÐ& pÃ|¢šÂ‚|#È>i’ºÂt§D éØŽÉ|ã`r”�BrWºe¥Un˜p/¦ß�¯FéXÎ|€RdØ¡âWJ÷ Ã`þ›”¾W…=Š=£ô­ Uú@éU Ø%×Jqa U¥[yaïAJ¾Éð;<�ұ̰“{ Åí^ˆÁ«)®vÃfÃÓ(Ý* !ß%Jé`¿v±”~Ö…Rõ#¥øN°c�”’@×9ŽÒÏš°g‘{W#óP£ô¸ìšåÅ+ù3.P<• öuÍÕ(}ùFI[솭{&Ð`boؽæ7ú^ ö/x�n‚BÖÒï–8d@ÅäpNío¾×ƒ“ œ rÓ?vÂ÷»(ü•zS꟢ԎQxZ¾.õ‚Â^8+ôœÂÕpø8ò&…gàp<¥¯áãE”ÆÃið¥Þðí@Jçp\ì…•áÓꉞƒ‹a”r—9ÿ 4®¶SºF]¢´î2'PÚ€ï‚Û(ýš.«&Rú¾û„Rb5¸Fq$|6‚âhXN)­#|Õ%�Ò2è?G)±|Ô(‰ÒùphÉ‘@éI5ø¦ÊSJñ9 ©ìcJ÷ËÂ'eþ£ô¤´5M¡ôw1ø¢øß”RšCã@‹Òï…áƒÂ¿S²Aë,Šñáyþ_)΃æo(þZø™â"èn¤økAxZðŠ[‚жŸb|axX(žâÁ0xuŠâï%àY‘Šg¢àIÌŠ—…G¥ÿ¢x)<Êx…⽪ð¤ò=ŠW3³,W)>®ê<¦x#3<Ì|•âËÖÐÞä9ÅÛYáiæ«“{As·$Š·²ÁãÌW(¦�…ÖQé¯g…ç™.P^}�ù”/e‚bNR^M!‹(Ÿ‰�/"÷SÞ -Q»(�‚OÂ6S¾œ²] ¼3¾ .§üs ¸.òå•!ðQà#Ê÷ëÁe�(€¿&Z{ÂU§—­9ð]¿ŠÖ\¸˜œN1u|Øê9å�pº„òËðeµ)_Ì G™�Q~P>-öå„ pPì;Êñ¥àÛ)?mÛ†÷)_Ï Gm§œ66£R(Š�¯ƒŸÓfK4„ðe´Y¿�J¥|«0”œç(§M€­ŸR¾×ïUý�ò³¶0¢|<å”ñx;$‘ò•`HŽ ´Yñz9m®å�1ëhsù m¶FàÀÌtºHŸÃÚ>¡ã§ía\éŸèð§²00Ë!::žF?°hk}S;?£ÍóÞ0¸Ì,£3m¥°%Loq"�oS�5ÃÿA–¦ý4ÍANMF —‹CVP8L/—À"¯§¸m‡û��rýþ’¶ðîiüä Dálˆ¡ØwNÁ¶ÿ‡äøÿ÷èÛ¶mÛÉ"¶íÌÆy¿×¶mÛžØN»qÆ;iÕãþììôóUõªzåvDÿzü †O]¼~û¶5 îT nøê½káÚmÛ×-º{xC¥Ö/ëC×´lj¾<Š;®SsîåS CcïÚ( �}ó(¾ÕŠÿ †ÖÁETG@kߊà ûP²¦BóØ0ÖlhžhQ:qÅÝо˜Š]Ð~ÅE�ÊfQúÜý÷R|Ûí¾�(]*a¥µá‚ÿ] i)p¡úUJ››�Ni:\Iùƒ1é5áÊJY ˆ™Jé ¸Tý ÿCñç&Áð‰>GñiÆZÕax5‹±§bl:ŒOgl(¾ …ïaüwš §ð,Œ–Âð©6ÁøÍ¦.¤°Æ/¢°`5…i0~:…U©ÆÁøñRwPã‡QØžJa4ŒK!u%…)0þN «çQ˜ãçPXt'…T¿†Âô¡ž€ñ�PÜ�Â70þ# �üEŒ½ã�36�cjÀð@”±çPü…;aøP Ÿ x …Ç`ø6 ©(îGá, ßGaŠ“Š(t€Ñ )Dø÷G »`ô: ¢$•BF ö§�Š’æ”FÁàÁ”Úã¿Ã>…ÁR8�R©¬60¶Y„ÂN”j¥ð2Œ}�B´JJ!Ü †¶ŽRø1£(½ Cß¡tbüg(D;ÃÈÞ…³qˆ]Jé ôBR¥©0p¥K)�–SÊ(ã—(­„˜”Né!÷(¥‹I�gPŠt…aÝ£”æBáÛKéP<ŒŠ?DiŸª¾¥�0j%«Ô¯R*l ƒšRz 6jdSúÑcâ~¡t½:ì,£¸Ƭ§8¶ü¿Q*jCº)ýàƒ½ÖAJ'ʈÀJE-`w;Å—aÄë·ÃvâQŠ‹`ÀRŠGa¿sˆRQ7x¾oˆR¨3œì¤˜Y¯s‰âN8JøƒâIðtòŸ�‡³F9_óÁþ7(æ6‚Ó»)oƒ‡wQ´î†óG)Z³àÙ¹”…†Äß)‡À£CBÿL„Žº—(æv„';çRü»ôôºEñRx°ÙŠ·ú@×<ÊçjÁsµÏS´æCß}”�U�Ç*¡|4úß§¼7OÒ(è‡Î2Rþ¹,[º›\¦üU2<’ô9å+Í ¿så/“á‰äÏ(çu…ƒ‹(‘ $NùÖP¸3!Lù븞òåðd¸5+Jùûrp¹Ì7”£sàÞ‹ò¯¸ZþGÊÖ ¸¹ŠŠ}Uàbå?)[«áî&*ŽÕ„k5�P±no¤âLC¸Tÿ$©p#Y­àJ‹‹Tì€6Rq½;\èz•ŠíðÆ*ò‡CûÐ<ÊÖxe¥E98šï R¶ÖÀ;‹£”£k¡uy”rt)¼4-LÅý>hóí¡"2Þ_DÅ›IДø*Á»àµ!ùTüP Z_SQ0ÞëyƒŠ  ¡Î!*²ûÀ‹­3©¸ÔŽÛgRq¹¼Ùà$ápTçšÂ«ÕöRÝGKÂT¨ï–ûœªa;î~ª¾ ÀË /RõSØ,ÿ Uo%ÂÛ¾]T�m[ ŽPu¿ž_¦"{lôºLEd%L™GEx%”soQñÏd˜Ñ>“ª—’!Æ?DÕå0¥Î!ªÒê@¨ü UÇÀœòŸSõwoÄ´9KÕW`Rü£T¡ÔùT=Ö‡©z2Åñ÷QY ó†fSõsõ?P•?&¶´†×RÜùŠŸ¥Bs£¿¨ÈéÍÉg(Þ)p‚Òu ý¦<Šö`h¯ñ;¥3A#)Ù=áÁHŠOƒ;lJãø’Òlxò$…żxŸÒ7AÄô¢ôC*<±0æP<Äÿ¡l ;àeÇ΂—[(\ £èvJ=àé wáiJ�Qô1…/0ØúŒÂlü¸Há~}7…?(lBÁ® £«Ùš¢p2…c0ü…©(\Há!~?…E(̤Іw �‰t 9q0<.‡Bzk û`ü ­SxÆ¿Iað£fÁøY›M¡;ŒïNaöJ �`|# +·R¨ã+QØz�B*ŒO¥pð,cí ŒQ8ûcóq ¸ÊØ/NRÂø…Ó{)$Áø’l P Æ—£°e …Ö0¾1…•oSèã»Qxk…ûaüT wu£0Æ¿J¡O ç`ü! ÍÂùŒµKÃðø\ÆæÅã(…¾0¼#…£(|‰ÂG0ü o °'…߃0Úú†ÂPfD)Ü £[Rˆ–ÇG(,€ÑoS8Œ¢{(ä¤ÃàÔKFQ5›Â½0x&¥Æøÿ0…ŸJÀØð·N¢Ø4Jc`ìJÓQ¬d„Â7a÷#…œ ›Ò$:�ÒÄ4¢”• #Ó²)ØM»ŽÒ³0òJ!´¡”SÖϧt=¤ ”ÖÀÀÍ”¶@lcSê ãP²[A^Hé§T–ö3¥ePTÏ¡ô {›RN ¨ž£í£ÚE)= eò�”ÎÇÁ ø ”2“¡îKñôÅ^p²�ÒÕv0¦C¥•pTý¥¯R`Hú÷”þ©g³(΃Ö2ŠSá0x„â1‰âáœ6Î¥t¥ h•C)·œ?Hñ› ø¾ì‚‹ÐaŠ[ƒðyxÅ#!¸©s‰â«ðùë#µánå ðõ$Ê£àvÅü[áã.çÁuÒyŠ7�o›F(žO‚ûúŠ?V†O+eRŒ4€Ž¾6Åsiðeú9ŠÑ¾Ðóå½ ðaâ~ÊOA“µ‚òº|^Oy•]É')ÏÀg�¹”O$A_¥LÊïZð•õåŸ*AgÓå—á'ëÊ‘æÐ{G>ågà£g(çßÝÃlÊOÀ7�P¶GAÿ½T<ŸÁˆQ*rÇBÑÿ_*¢�À”^—©z; !ð”MÅ•A0§õ/Tí.‹˜”UTýÖ&U;KÕ-Q¬îª.T‡Y)먺2E½ÿ¡j[*L ¾D•ýb°ðY›ª÷C0p\>U[·Quu̼1›./Þ Skœ¥«sµ`nò ºX�“OØth?eÁðžÿÐÑ¿ýa~½Oéàëf¸”\Eå†t\¬G¢£�p͸=‹BÖ¸–”|4“Å~|(׫ÙÈ{ïÕÌ‚oANMFÊ ’‡CVP8L²/’À!ÇG&mÿ®÷– ˆ �´…wOãBD"wœ‰OжíŒ$½…ÖØ¶g¶wǶmÛ¶mÛZÛ¶m�m³5]]õ¶òýÉŸüsÑÿÄc»pË�ãç,_±pʰ®•üЬÚmøÔE+ÒçNÔ¢<Ûnó—×)&ýþÜèÐVnâ‹§P¼ñÕÖ±p5ט÷i+òǺ'¡¡á¶#´—ôá„qP>±â•·jÃAü ª~ë{Õv%Sµéë¨JØ\ö‚=¢êvØ.vžŠ“|°_ö¹0›çQÚ^ö}½�Rq¹$lÆýH9´.ÎêþGG¿Ö�³¨å©”ÿÈ [¾)oDZ[ô^€ãZÿQ~Ý;)˜:º>¤Í»Ý¡#÷Û”§ÃFåŠ;ÐSû"m]‰‡ÿFŠIÕ¡ þ@q=´•:Eç*AÛ2Š¿EA5—âFh,w�ÊËå q9ÅÅP¹Oé9h­r�Šû5¡õ ¥‡Å! ôC ôÖO¤ê½Ñ_Szb|…kÅ »W˜Ò4è.|™BZMH¯Qêý³(ìƒþΔކP!�Âópc/-áÂÓ•aÝIáNA¸|ŸÙŽä…ùnQØ K¾‡æÀ�Ü2óF¸3�BBdŸDál \*u‰é)ÍáRô) S‘ý+ “àZÍ‘ápm,…o�­D˜ÖÛ9á^çUp/î&­á’ÈšFa ]Ca²>£P†V¢ð2£hý ÆþAkb42QX cPh„Œ¹ž‚±ñæ!ã Zïøa¬ÿ­o"ã­ïÃà÷h=‚ô@ ­K`ð"ZSü(K¡/ îK¡,ÚR¨ ƒkSh‹!´FrÃà<†`­ 0:�Ö ˜Më5}�ÖÙXFëi}šÖeXAë?0ú_Z—c9­Gaô1Z—c­gaôyZçc"­·aôMZ§b­‘X Ñ:�(T€Áe(tD% �`p UL¥u KkZ Ò�Ñú2 >Lëd¼Cëü­ï"c…ª0¶P˜ÖÅÈhFa.ŒC¡-2b’hýÆ~Hk(2¿ 5\†J¥õ+dͤ°†. 0Y¥#´^ ÂÈày U�í{ C`d #û4 ÂDßf {�$ ]a`o )…`yšÂŸ>çÿ—Â˰֡4Æ §ÔÂWÎÅÁ°ÜW(|©-¥e0l=¥Î¿¥�XFUL¡ð#ä¶”Þ…I¾)µ�âJý`ÐJŸBõDˆÂ•|0&ßU ¡'¡ÜGé ŒÙOiÔoR·€!-#n„�Ñ”N愹NS;¾o)íƒ)}{5R(DºÁ€>”’*ÃærJ7KÂóåîRZ »ÑÿQú6�G}Oé¿(Øn¢´ßE)TÖRŠ ‚§GR\'1SJ¬ ×K¦ôW ÕH¤t¡<[ü¥Äp8žâÏqðhÎß(N€ã—(¾æ‡'oQ|ÎsýOq<¹�â‘\ÐPíÅ™ðàLŠ÷«CK÷0¥ð`xnX„R¸4-¢˜ÚëœJq)tù^¤˜Ø žj’Hñè‹ýŽâ½:ðPí»ˆ…ÆB')ÞŒ‡gâoR*¶À3˨x;Úb_¡b5<4#Bù‡‚ÐTàkÊ‘…ðÔØ4ÊÇ+@KÙÿ)‡'ÃcýQ¾Öj^¦œ:žë�@9¡'wx@9©+<Øðå´ép8!Dùn x²ÆE*öáÀ¿‰ŠËOÁ£¥ÿ£âã¼°�ã5*Ž•ƒgóMőаYâW*~.ǾJÅÍ–°Uû"ïå„§ý;©x4 6z'Pq ¯O S±)…oi„rd è‘HÅGù!æz•ŠäÁ0¢þU*NÅC(÷7šÂ�rÿSñ ,­nRq´"ŒÉ÷‘•>dú¦§Rñy>ÜCÕ[y�žëEªžŽ‚Y“CTü_9ý_*ÒæÁ¸öw©¸{�Š{]a`Õ£tt¢:ŒÌ÷|”†6ÓndkæI¤­äá0ºÖÚ¸Ô†ü„ʯ‹ÂøÀFÊ‘­A<úß§p¯?%Ÿ}ÄlÉÏ”Äã£ààåË€7ANMFœŽƒCVP8Lƒ/ŽÀ �§ m#ÇüQßú‰ B@P"IñßœÌÆ”ƒK³7ß„ælÌ4ÿ@ÿÿÿCróžÝM²¹mlÛ¶mÛvm\R±“ë]m·QÓØ¶�³o÷ýDßÏÌ|g¾ý9¢ÿ‰ÿã =ÇÍy>~á sÇõ® ÝVµ¾潸ðÞ sÇ÷ª„{¸õŻێƒ¦#VìH¡x{ÛGýÂð0nÒ¯™t”ýûüRp]áÙ-yt”õÛ´¼i¾4™.2×·ƒ«ÇW¹t‘º¢ô7ýž®wt‡ã�éúçVÐ[3)J¿4ƒ£v›©#úu=è <‘AM‹ã`[lMŒš²ž BSýíÔx¢=lºœ¥Æ]M edµæ¿€|;J­Yãá>ðfŒº¿�@‰üHݱ‚pYô:º±)aÉ[o.Nøã í­ŒG*í¡“èù?Ö}úÆÛK?ÿç:ý�«¸¿h~åÐrJ÷ýäí/5ÀƒÚçiÛóvï„rC–Ÿ¥ýÖÇà"²‰vÙ‰�á é²TÚ]¬‰{•ÏÐîê; à ÃÆ,Úm/Ç…7Ñ&ûÃrpXì™;´9S¥ÌaÚ\~" ‡¥ßͤÍö0Zë(Ç’ªÁE©÷r)ÝM9gQ.*¯§M’gÏR¾:.[¦‹�à²ßEʯÂQÿ(ÅßKÃuøc:�}V®KþD16Ê^£øq:¦åÑQÎ8è¼CñfØK)ö4õJ¡ƒÌþÐ4+Fé'ØN¤{Ú:gÐ6³;´ÍŽQš›7(½�½³i“?Ÿ t»äw)m„ÖQÊs u%¥�!ÖÊ¡°£ô>CñSè-´•Bn]HIÒjA÷r ¿¡¹Z …¯!Ôȧ0ÚC¿R9T Ú§P(¨õC ›àA±|äz xð…O¡O¥m/ª^惬ð¢YÕ´xt…xÓ2�÷bcáÍZ �ãÑmT jÁ£�Œ‡GÕó©nÇ#U¢T¿ƒgó¿´àÕ×T£ÕððI ]á]žu¢ð4n¡zF¡º ÂÙTÁÈxª9aÜïJ¡)ŒlL¡+î¿Lõ =MõÜÿ™j Ý@õÜ?Eu& �AõîʧÚ†6¥š_u©F‹ÀÐp”j]ô§zÆ^ Ú“¨n‚±›¨NÄ<ª_ÃØ¯©ÎÅóT×ÁØuTŸC<ÕÏ`ìbªñXHõ=û>Õx¼Fõ3»˜êkxŠê*»†ê3˜Aõ[û%Õ9CuŒÝBu<ºR½ cÏQí‚ Tc%ah(ŸjÜK¥Ú†¶ šmáÞªÏÃÐÙTãþzª¿ÀÐ�T×áþTªéa¼Fu&îס0Fv¥Ð .QM€‘ŸR½ÀƒõT3ŠÁÀðMªðp…Y0p …áxXø.ÕÃÌÛK5#‚GÖSãúPHÀ£])lƒiÖN Ý¡¤Ð† ¤pÊ‚2“Ân F÷QX5r›Â5ƒÂí8/S¸�A%nPX©ø oÁ )$—‚ø …œF0¦i…W G®Pø×‚!�ÿ(\‹Àf ¥Ù0d¥é° ì£�\ FTL¦°7ÛŽ1 ßÁˆï(D;ÁÁJ£aÀXJ«à¤Ì- ·+Á÷UïP¸ZŽÆSú+Ÿ‡¶R ‡¿Qz >_HéW8­™N!¿|Ý£€Bz 8žKéj%ø¸Ú JóàÜú›ÒŽÂðmx7¥M\ÔH¦´¾ÝHénu¸EñIøôiŠ£ár5¥‚Áðåð(¥5p[t¥ô6ðaÛLJûÃp]'™ÒÕšð]Ík”’ë@à(¥ãeá³rÇ) ‚–)îz ¾*¶‡âËÐc}Añ¯ÂðQ‘¿(~eASÑ�¿ Á7¡o(î C[ù³ðI �â¹ ÐØè.ÅU|a­¢x§´vÉ¢¸~°>£˜Ý š‡PüÞ[ïS, í3)¯­)ÆfÃç)jÁSëʯÀ“w)/³à¡õå÷á�µ„òÚ< ¬ ¼^Yk)'…àQèsÊë-xøœòEàI‘ï('àa0‘òŸx÷寂ð4˜HyGih/¹�ò7!xL¤|¸24W:Hùë<&P>WZ랥œ„«(ßl �­®S^€/¬O(§÷‡¶^©”—XðË"Êy“¡i\.å÷á£gbc¯BËó1бWà«YQÊkBp\B9:>•Cù·bpùžrÞxø®wåƒUáªÒÊ™ƒáÃ67)_i M/P¾Ý¾¬w†ræ(8î›BùB#ø´â^ÊÑWàp^>åÃUáÛb¿Ó&±„–ÒfsIø¸ÐÚüW¶%§Í—…ákëÕåó­`ÓàmÞ³à÷ñ9”3Ç@˜B9o è~‡rì½ ëù(åä>0¢áiÚüV �Ä}I›³�aHÙ-´9Ùêì§ÍŽò0¦ðzÚ¤ ýAwióU&=¥�_£]hÁ¬¡it•>Æ5=Mg›ÃÀ2ÿÐñæ²02´˜—†`êäl:È� ƒ[Ÿ§í•Î0ºÜ?´ÙZ†‡>¢û$ó�¦rz þ �L<–’zANMFžŽƒCVP8L†/ŽÀ ·§ m#ÇüQßÝï B@P"IqÙ¤¹oz&Í`vÍÚüjضo¤;m’ÁŽmÛ¶mÛ¶mtlÛ³6ƶm³‹a™Ü¿Gïó}y¿ïÝßýOüÿ&/ßsÎÆï÷œ:¹ëÛuÓ;•H­_•î±þ»]'NïýaÓÜ^RÀé$M–Þ¤Uü…95üÐ’¸ÁÂkAZo-o– Žy›þC›¯wÔö Do“Ÿ¢h3ö·–>8‘~êc†tcx*„�qü†ôlF&èN9ý-CþoLbØL>íC~7;5tzGüK-OúxaÃ?4’Z^�õA[±SÔv¼,‹ž£¶ó¥ Ç;1–ß ö@ M�qÓ}Ð�êjþ3„Ô{©y_Z„\äµ_Ë %Ïuj¿W!VC±¶�ëÙºn½v}&{=@‘UðEÅ—´~û¤ž­ëÕiÕsìÖó±´ñ®Bªýž–ÏW5O1uûMÿÐ2º>ÕŠ¢eäòf)!&mºü)-£!„zQ´îmç‡�Ä=NÒ*ª&>”K«Ý­ü°ákµ‹V1Ma»B-V„íš§hñ¦b±h±«2l—ÛC‹˜j°™ã9åGMJX‡§”ÿ{FùQ „Ôà>åÈ<°•ì"ÅàÆ”1Í7 aM2„˜l5å«)`ç[ŠQ] ¡{4mFõ„†¶ï)þ])>--•"iëeh)õ�boXfEéAnhÊs—6‚¦ìw(½É ÏJrC[îÇ´|’ڲߥtȹ ¥òCcÁ´xUs½¤Ô bÂ;âê@k™wãêCkµX ÷AIi47P Íý)�…�ì? »<Ð=œÂRèöüJáu ¨Ã(ü— ú—Qùà í™ÿ¡0Š÷…�pÀû ¿¸œô¡ðÀ‡/ÛP¸æ…IÏòÓ‹\pÂ{™B|¹‡B38“å?DW‚3 )ìÃTÏÁ©âo‚]àÔiª�Lø<�Bw8Ö` ëLa0>¤ú, ô?¡zŸR©Î‡‘³©Òàc `dY Mñq6Õé¹Ou>£º†.£zü±T;ÃÐNTcýÈO!' ÍA!?R}cŸQmˆ!TÁ؃T‡`1Õõ0v=ÕÅØJu<ŒOu ~¤:Æ úöPí c»RÝ�T[ÂØVT�ã,ÕÆ0¶ Õ³8Hµ5ŒmKõ0~£ÚÆv£ú'vRcPýk¨Î�±Ó¨®Ã$ª_ÃØ-T'¡#Õ+0ö0Õ®(M5.! õ¾¡ZÉ)T…¡Å©ÓáÃ=ª`h_ªwñq#ÕC0ô'ªÛð±Õ@™,šê|ÌGaŒì@¡(>zîR=#÷P½‹ÏJÀÀ"ási ë`à 5ðÙs‡jLf—é=Õ»|1ŽÂ<·„ÂD|™!†êûÌ0,[4ÕøìP¶PXÃÖPøj9 qE`T©…²þ¤°&yQØ©"¥æ0¨=¥jÿ¤ð )ŒIþ˜ÂŸ�K(,‚1K(JÃb…ø20¤l€ÂFXe~KáœFøÎQx“ –£(�…c)�†µï2…èÂ0 h … >ب¤pÚ×'H)Ø.é¤è­#(ºÁ]GCó|Šñ�á‚vñCwØVŠñ�àx‡xŠÛ Ý÷3Åø.p¸s<Åßýp ÑŠ�p´k€â�Äp$ÙqŠ�þp°W€â©äp(ÕYŠÁaplH�â¹Ôp,í%ÊàÐxÊÓÂÁô—(ÏõÀOå«éáhºK”׆C{ørÊ×3Âát—(›šì¤|-Ow�òîdКtåKà‚4§)ŸI�éNR>›®Hy„òí¼Ð–ó:åã)á’$»(¿(M%ŸR>� ®Iø#å·� ¥ÞÊ¿'†‹|[)Çõ…†nq”wú᪰Ŵˆð DÏ$Z¬ ƒÛ&ÐbGB„”`-fÂ…ý”�¤C©öR …+[EQ¾W¶s_£Ó.­ò/å×�`³J$å×uàÚÂ(Ç…­î1”Ÿ”€‹³œ§Åj,Ã#hq%;\�ìwZìI‹ä?Óâ@J¸Ü·šw‹CÌw…[Àý£ƒ”ß¶…P÷_ÊÁI0¢måàŒ0|áO9ª# )÷Œ¿¦À§$Ûhñ²2ŒÉ~ž7 áC¾‹´¸š%ý‰¯š6{E‹¿R¨ðÙ´i±Ð ÓºF3„è0°ìÚ~RFf>A›'3ÃЄkhksB˜Û?––q#`t¥§´x^†g:Bñhï�ˆ£;Ó�ÿƒ¼ ïóÓ½ù¹áANMF¦�„CVP8L�/�!ǧ m#Çüißü B@P"Iñƒ¹nŠIæÐ˜0_ÁmÛ¦&Iûû¾P:³ÓÎìHÛ¶mÛ¶m—mÛŒ¨.ÛfªÂJ+>ìŸQQqÏ}ï¾wûwDÿ®É£6?òÁ÷§ ®çþõÍ»¬\ &õ‡mzè½oOæ];wæ‡Ý2ºQÞV™úP:õ§îUF*Nz �úÌG¦W…Wñc_�Ðéµçà2nìa:�¾9!TÞ›AwnªÕwÿMwY‡ªÁpù]è>c–Ûs‰î/Áe¹4svnâVdÓLþÚ L5z�æþ×ÚÆŸÐÜ'Ía$°ö*M^˜9°ì2M^Û€û2OÓôse!”{‰¦_,· ¾¥ù¯ë@©ó ÍÿÔî:äÒIvê­«g�<~îÚ»>( “´Ž(Ñ.�N²Rn_3kìà±³WÝ’’E'Ýà¦sµ‘Ô - Úoÿ(Fíå>(îr‘ÚhêšVˆÍ×½¡öBO8ïzžº¬õá¤É‰|ê.tAQë|ê2vÖ‡“º{Ó¨»ØN[] &oCœ–Þzžšü6ÉÔ¤¯I‚ÓÄÕÙÔ\jgÕNRޝ7Un�RÎ>E9|¼ Ü”;¦|¶&œ$}Hù·pÛç$]üØn;ÿHùóRpp/å§JÃ}¹Çéø©2pŸôåG¡M1ºF;ctÛ3"'AW-›RdLM/¤ƒÈB˜š¦”Wš(EfÁÜ䵑é07)LéUÈÃ)ÅÂä¼u«`r&ű�â¦tf7Rs fPú= Jo„`ø.Š/a6ø¥5PËæPÈ©Óq¯Sø¶,LWΤ�_ÊJJ`¾Ü·T2êÂüHJëP2ô'…gàE�t–¸Ú^Oá]Øø˜Â+PúQšËfRêõ= '“`U™4 ŸAHi¬ÚGi(¤÷)\M†EM¯Sxb·…Øx‡B¬'ä')Í�5s(= Mƒ«r«Â’*¹®Ôƒn'¥'`É”vA›ø;¥Ñ°b¥_¡D)«*,¨‘M!ÖN¥ôr¾¾Eé~8ª’Ci-|¿™RV%8›NéFø¼[!¥ipú"¥3Uàëi”^„ãy”Rãàã„(åÕ€óÉo†�ï 8n ¸¾]DñA¸*û+¥Âþðéà0¥ßÊÂ]›+” Z—­.PºÒngS¬y†â\¸¿‹â×åá»ò_S¼ Þ§˜’Ÿ%½Cñƒx˜¨všâ³!ø*ôÅ3Õa¦íEŠ÷à£À}/¶…©áŠ7Ã?�#£`n9åðÍÊ+aòå�ðÉÊG`4ð(å-ðÅÊO`6þuÊ›àƒ ”߈‡é2SÞÏ7Qþ¬ ÌWúŽòvx¼•ò÷ÿ�5~£¼žî üG xS÷$å#ð.p€òéúðªáß”ï£àm”ÏþÞ5N£üh< =H9½1¼lœFù…Dx�ð åÌfð¶qå”r0^ö Ê™-àuã4Ê_T�á*ŸRÎhï“ÏPþ­>ŒÖû™òÙÆðCý?(§µ†Áæg)ÿÕþ¨õ#åsý`¬G>å_kÃ/U¾¤|} �¿FùûêðO…÷(G7ÀȪ(åO*ÁO¥_£æ¶\SóVø+þ1j^,—¥ž¡æÙø-x5_Ö„«ªQsO>ÜNÍÙvpÑìOʱ=ðç¼0åKcà¸åÈ2øuøeÊÑMp¸°�òÕ ðo—jJ€ƒÐ jòzÁÏÉ¿Qó^hË¿LÍɦðwå÷©9ÙšÆ?SóEuø=ñ j.M„8¸€šçKÃÿ�ýÔÄ¡ÖG¨9„ ©y¹J”z˜šÂŰ¥_>5¿6Cqƒ/©97ö4ú…šó£P44Ÿš“-`S¥·¨‰nߥ惪°+þº¼'Ö-)¤‹Âå°±Oçôƒ�õ¿¡ÃïÀÖÒOÐѳe`ñº0µ‘XÝ?‡š¼!°½Þ—¿jû“N„©KÄÿ…Æ7Ÿdñ_'’áANMFÔ ’‡CVP8L»/’À!·§ mÉüqï¿A @RHÁsEK|åhˆH<‡7lÛ½õÿï¼'µ­¤nÓwßµmÛ¶­´ËvÚeÛ¶íÚMµ¢*Næ>™ë5óšyõqDÿ7íê}¦,Ú�¶së²éÓCÐn1rƲ-;¯®_8¹o ø"vÀ}_üG±à÷æÔ…¶Æ‹_ü«ˆbæ— Šƒ§Ió?ȧ£ÈŸw´ƒ†.î§³‚�U€W�ž¼B7ßN��«¤…¿ÓMÞ³ÝàE�/è:{K<W¼ý2]ÛºSß§–3 Âp³:›Z>î�ñ÷•Q×þžpÐÿuY�&B[¯ÃÔXvw ñ�D¨ñX?è Þ¡Þ¿S!vÜO½‘{CÐPñ]jÏ a\µR®“÷Ó™•uô�Ÿœ-¤3klë#tV˜±÷§ß�dYtv¤\¶:G'Ÿ˜Õ)åBÍF§}SFO‡p=¸› ?ß2¸qå:ÍÜs‚²RáªíTž¹µ ”U&¡ò… ®öPYòÞ¸8([îÌ 2»#\´Í¢ê×qa8kþp!U{¸“ª+÷Ö‚³ð¨©ÊíǵOQqpBμ`QqßF*J¬ç�1{©8[ã~¤\z{4Üuü—®~éwQi%”O€£ÀË”t‚ëØû,:¶n Áuê?”ß ÂÉbÊV„ŽáWè0w8t$½My¤äS|(=©tt¶5ôï¤XÐ ÊðºGèàxShÛNñ×(¨6R¼ž¢òL#hÜAq;5/SzZSÎSq©=´>N)¯ä'(}½�ò)–�Þ¨/)=±m…ó5¡{´EitW;CÁJ…ô…È(è_Ca7ô¥ô.„¦…àE:m‡áÁ“¬Ø¡�[^„ßg¹½áE¥, »a«|…ÂZx“ô¯g6�7Ë)äUAù%ŽÅÀ£º¼ZÔ E¦°å¿¢°žµ¿™ÏæRøåêZ´çÄû¡·À»¸,Ú­z¸±’Â]0ô6 «qãsÚ#É0´)…/p=:Ÿö?`ìo´DãZ7 [`ì& Ýpm=…¶0¶5… ¸öí¹Ì¡ým\ÛOûû0ø=Ú÷ãj¨ˆö-0x3íE!4¢0�£Ðý)¤ÂàT ý1�öH N¢0 ‹h¿£¯Ð¾ëh?£ÏÓ¾i´�ÑGhß��´ÿ£ÿ¦= i´ïƒÑûiOÃzÚ�Ãè“´oÂbÚs`t&íË0�öH, •Ò>C)4�Á ( F2…!0¸…æˆ*¡}= žK»ƒ«i ?I{®½KûüíïãÚ )0¶šEûV\ëIa-Œ�K¡?®ÅÐþŒý€öÒ ¸þíV#Zµ˜ö¯pc5…[`è ëp£~„öŒ0Œ Ÿ Ðå¾§0FŽ¥ðʯ¤ð;L üFaÊW- 0Ž¥P\ ¶g(ü€qÁ(¼{GJ“`Ü J] |EáD K:Ká+Hý(í€awPñ[ ùõaT“" ?BîOé˜ø€R?(>¤4M¤ôT­Ë(œ­c*�¥PÚÊ=”ž€1{(톺j«7 é¡�UæP:”#�Rš 'Áo(¥Ãˆ'(}g­Š)DFÀ€q” “á0�Rf]ø¾áJ[á4f/¥¯ÃðyÔw”þ�†ãÎe”î‡Ï¡TÚ._Ï xÜÄüE)¯|üÿBJÆÀUë|J'kÁ·µOQÊo— )þŸ&üBq\¿Dñõ |z‹â‹pŸ¸—âýðå÷%BCËËWÇ«(^j -£,JÖønj„’5 š¶R, Ÿ -¡¸º/QÌë_uϧøbÚb¿¥xáðQ‡\Š?ÄBcõ#3[Ã7m²(©­)YÏ5‡ORÎQÌJ�æ.yO'ÃM2(æw‡ö¡¥3šÂMNR,¦YO%Ãó¦§(Ff“e”O§Àãä Š‘Uðhå³­àiÊÊÛáÙ”3ÛÃÃ6ç(ß ¤œÓžuÊ¡ü¼ ¤S¾ÜõºD9ÞÒ) ‡'ƒ (?€Ç�tÊ%SàÁ„bÊÏáy �²µÚ—X”Ÿ Â�G¨¸ziT¤à‹À=T<‚ÆP:÷Ã7iT¼m±¯Rq+|´:Bù»ªÐTù+Ê‘ÍðÕ<‹òÁ&ÐÒà_ÊÖRølR åó� ¡ýÊ%Sá»Ay”óFÂõ K” †Ã‡]³)—­€Ë…¥”/ö�/[ePñh.‚wSq¶=|Ú`/W„ãø×¨8Ô¾­ü ûšÂa�Ÿ©ø¹:|û:Y½à¨Cï'ÀסG¨(ž£ó¨x"¿¯²¨¸'E`{„rd+ �OÅG•!&¼JEáTÑé<‡ZChô'™=`H£½T\[ŸL*ö7…1•>¦ÂÚÀõÀŠ*>¯ ƒÂ�Qõv®&¼HÕ3Q0kY){“¯þC…µÆ ¼HEîE*.�€�ÍÐÕ¡–0²Ò‡tñqeº�N#÷‡`îÔ:*œ £S�ÓÁ™®0¼Ú§T~U Ƈï¥y Œ›Á„K.NÀM¢îsÅ,WôL]Ü<ªMM»¶cjøANMFâ ’‡CVP8LÊ/’À!§§ mÆü‰·;"%"IBì†ü9²€Ö[z›þïÿÛÿŸ�üÿßµíî̲³ÞY=±¶mÛ¶mÛ¶í݇mÛöc�™uÇÓæúŒr»§÷ä¾?Gô?ñô.P¹aû¾ƒ»µ¨YÖ|åjµì>¤O»ÿ/�í¿ñÅßô?úôèÜÆ>h ´\xò‹'´‡ÿxiÓ€ \®ºì½t:¹urXh(>öâ=:ÉøpyM¸;ò]‹Î﯇([œJ¡sëÃ1àFáe‰Œöã¾pîñ-£½¿º(tÇιM¶„ÃÎ_QG‚‚ÐÚéoj²ž«•ß ®+= /xÈ¢¾‡c¡òM QŸu²4µºJ½Ï•‚ÿ õÞl-“Ò¨ûzC�oRwÆ,DŸ?GRé8Ô¶¾!:N‹Ðñ±DóXßïŸÞ®Rœ1¥j\u9�Âó�gV˜n�_Ô·zñüð+¶›¾ï[‹Þ(€¨b_¥ÒzwR(-Ö_¡zræRýûÊÚPÅO|Û¢ò킈¢ÀëT…vV‡£@¿7©œƒ¬ñÖËmá¬ÊÖ'T½[Ž}©H?çm?¡Âš<(LÅk�à¼ôî4*ž÷Ãé*>©�¨|ÃîR§S¾1ÑUù€ŠÍp8¢˜ºØ�h˼Ä(.­N EkUO¦x«%tÌÓaú\èhr�bj8È÷Åo*BO¯'tê=ñŸSü6ê5?BWý:xкŠ|Hq”�2)}„¾F©|ÜúŠ|D)Ü ß”~+�­BT¤w�Îà�”>ñADéA èí¦hM„Þʉ”F@Œù“B¤'tÏ ¸º;G(ü i:¥½Ð¿ƒÂ ~hßNiÿ~/ýþhû¦0ôø…Â_ØûS°:Á�B_0Ï� p£ ¥Á°@ḅ9IMàÎs>†­6…ÌZp©ÎCfEÃ¥jê!ï: çàZ— .‡k§(lDÞß(4�{“NÁ½†þ@ž>‚›>¸ø>…FÈ]Ka, Marߣ=5†Si91É´¿ c_¤=%Ù­(L‚±)´BöB Õ`lU ‹�}‚ö;0ø6í'�ý!í/ÀàhÿÙ7i߃7Ñ~Y…-Ú'ÁàI´[…Q•B{Ü�BU4¤PW£Ðm)ÄÃàrÚ¢'…¢0¸(…žBÁƒ† /…ü08–B?t „ÁÅ(tF `py ÍQ�BS\‡B”¦0÷¦P Y�h_ ƒgÒþÙ_Ñ~ï¤ý{d_ ýü í/ { í‘’066�öuÈîIaŒmK¡²ƒ™´Ÿ„±;h·J çKÚóÁPß¿´ÿŠÜízÂÐv!·#…gaè) �‘¸M{zYY:•ö‡ù�g?… 0r…ÓÈ۞½Â0°h…Èëû…Âb¸‚Ÿ>ØfSH( ãâPX{ð …µ0n…P »)$U„a•Ó(ì�T!•Âö<…ŒÿAÜGÁj £:S:¹b*…c`Pì¯R*@±™Ò*´†Ò6¨‚w)¤V‡15Ò(Ü�ƒr¥÷}0Ä÷.¥iP¾¢4†L¥ôµšF(<ª#þó˜Bfc8:@é ¼KiœoPZVRºRPJoϷΤÔŽŸ¡ôwqx¼ÄJ—á¼L"¥W}ðtà J eÅ0Škáé-‡#ª‹”"áá¡¥Kˆ®Ø¿”B àÙ!JÿÆ!ÊÖ™”®ÆÃ£®SÊhƒ¨—Püª0Lùr ´Æ\ ž�ŒÊ¤üN‹¼I9s <3 �òwñÐVæ ÊéCà¡®I”ÿ©MUÿ¤œÒžjý�ò½6ÐÒ<�òãNðX£»”S†@C¿dʉMá¹jÿRŽ,DԳ”¯×‚Ëÿ@ÅÁ¢ ì¤â·ÿ“Å?¡â� ¢(ô"Ÿ—‚G ½DÅÏ•á¸Ü—T¼^ž ¢"¡-6¼FÅÙüðòj*ÒÆÃÑÀ$ÊÖf¼=!ƒ²µÅ¥oI„rætx¾Ë#*^, EÁsT$õ…u®PñSUˆ¿¤âfQî+*ô„Ðê6ßU„!…_¦"¼¶ iT¼ZƶSu©rbPµ7“&ePñÝÿ�Uñ3*2gðŽ÷¨Hè˜u—ŠG½a\Õ_¨ÈSñ{-÷£z³Œ l¥sk[¦ŽI¥Ã”±0¸É:ºÑF—~—>-Ãóí ò@ Ì•L1yž õ¡ðS<%bçýÅ<Î�ÁÓÃWwÜ’¥ãêÀ#ANMF°�„CVP8L˜/�!·§ mÆüqï�@�¤-¼{¿¢wzD_¢3qoض’¤mÛ™•mUõÌÛ¶mÛ¶m{lÛ¶ív�§jÔ®j×L1cÿ]�ó8#ΈóúÑÿ„ÿäîóùtGVö™Ã¿oýè�™�*Áè ]ç<òɶß�Éùcçg�Îï‘‚€ËxàojÝ?îîQFÊ xh/õ{\A9=^Ë£×K/w†ßHŸwré5ï­ÞPnÙ^úËœ[>’–勵ý++Àp©…'èÿäü<–^qžþO// ƒÎ¸lšÙ;Ê�‡ÈÔlš9:ÆÒ> ¹OÓ¡­þ-Í}Vf&Ÿ§É³c!;“/Òä¥Y0Pâqš~¹4„2oÐô ¥à7e+ÍïL†’¼‹æw§Ã_Ýlz¹´ëéU³Ç�0wõó?þK/‡áºéåÂögVÍ;lÜìOï¼H/ÇÃOÃãÔº»×·�@Švºùgê/´ÃÕç¨u·¯l…i½n‡Kí©fðÞø$uçh/M½Dݹ(®wŠºÓ·Ô�—z÷ž¡îL x­q’šKËÃk…Mÿ£æTƒjÙÔœZQ^Ë­¹@Í™ºðV1‹²ûÔ�ð“ò¤Kùè^ÊñG*ÀOåG\Ê'ÂKÂ'”³ûÀoÏlúø»=üvÛOù«<ÜIùãŠð_é-z~·ü——òÐw�SrïŒÀ„s ½¹k˜ˆlq)¹} «xˆ’;¦¦ÒC|.L͈SÊI„æyJî<˜›§6>æ¦Ç)½¹3Å¥09Ë¥n)LΣØRd¥§av55Âì#”~Š@Oik ~šâ§Q˜�}Ci Ô‡)\¨ Ó±/)dV€éôsŽ”„2‰ÒT˜¯”Eådu˜Oi®w~¥ð)‚¨~œ×åvDPÈtp]O … H›yÕ�@êPèƒëÞ£ðç•Íèa âZb>Õ¼Tµ˜Åo8(9—jA®N¥ð‚{dwiö4…¸úU·9‚K¨ŒàšPøW ©n‡¥ßS-LBñ` aé| CP|Õx:,M�S½ Å;¨î€µÛ©îB™ª·ÁÚ[©”iAa ¬@¡ÅHªñDX›èR¹Šj,ΦºêªßÂâo©>ó%Õ§añÓT¿ØEu,^OugÕŰx ÕÌCTgÂâ™Tž¦:�§zú8Õ °x"Õ{©Î€Å3©îÿ™êBX¼ˆêïßS½o ºóª/Ââg©¾?Õ°økª÷Ï¥zÑ�½‡¨.ìE¡¬M¦0¸*…©°v…Î ªÏÃÚ;©ž@ñ›TODaë?TßGñ| ]`iS «PÜ”Âðt …–(vS=WV–8F5Wï¡0VŽ¡ð®¶£ð¬ÜN¡®:‡(ô„…Ý)ŠàÚ ßÀ>g…�¸.9ŸB/X×—BQu\ÿ2…],‹þDáM(m(�‡eÓ)µ�ú …œ²°ªâ ßBè@éfXu7¥.�>£�×5) ð)ÄfE¶:°&²ƒB¼%ä§)Í‚5³)=Mêe çSaIÊy S [BéXò¥åÐÆ~§4VŒ¥ôKô�] gRaAÆY Emáå1J_Fúèw”€§ŠG(­@è7PÊ)oC)vAÈ»Q ¯¯R:š‚Pgœ ô*Nik !.µ›ÒñÊð>Ø¥ôBü %wüB»€âÃðUê7J…ýÒAE”~+õ/QºØ ¡ly™ÒÅzð;œbN„°ÊQJî(ø¿›bV"B—”IñnHøœâÖÒY™í¿ˆÂDâ??L@¨bQÜ›3 ÎS|9‚E^¤x®>Lõȧø˜ƒÐ8�P,è sS(߃°8÷Rt§ÂäÊ· $7SÞ³�SÞˆP¬¥ü4 Gߣ¼!XKù½(L—ú†òF¾žòw¥`¾üÊ7#àM”¬€ *gR¾A:·Pþã“ò凿ÜGùŸ4•±Ÿò3Q}’òþ Wí å7b$ö*åƒÕdµ”?)ƒJ½O9»&‚­v€òÖJ0^ñ[ÊÙµtµ”M�áäŸ(®‰à«þCy­¹�ò¾jCÚŸ”O´†Á¦Ç(ÿ•ŽpÜøåK}a¬ûʿ߄°TÚF¹`2 �ͧ¼' á)ûew-Œ,w)Sa*ù65O%ÀwôAjÞ/…pEŸ¤æÓ ðYö}j^J@Øœ[¨ù­ |¥þ@Í}B¸È¥|¬-|4>LÙ]�pŽÉ§üß(xîw‘rÁ$„µûÊîÞæQ¾<ámv”šWKÁCìQjN´F˜«fR³3ÚÄ/¨ù«Â]ñsj²[AÓp/5Û*#ì±§©ùoÄA©y¥$,XíRsOг:NÙÝèÀŠ1¹Ô|™„ëʾNMÞxØÒþ5û›àj�LjNw�=Õ~£æò½@Í_µaSù©q·ÜâRóE"ìŠÞEî}QX7!—>r'ÃÆvGéùX{Ø™¶‹w§ÃÖ’OÑÓK¥`ñ¬|j –ÀîG©9Þ¶§n§¸= öǶäSÉÝÃÿ…ª·fÅYϺ9aANMFª�„CVP8L’/�!ϧ mÆüyï@„€ D’¢mf&˜Â¬™Uó´°m;#IoR­Q{lÛ¶m­mÛ6ǶmÛ^{·Ç¶§ùžõàÿþäOþ=Žè¿S¢Ã‹Ã¦.Ú°{ÃÂ)C_îXfÝR]^>uцÝOþRÇ’‚®ðÌâ‹Ô]Xþ\y˜qª¿²öu—–>[ Á•xï_zýû³2ð]õûCôšöQiátY’E?Ù˺Gà#fÀúÊ^ÞÃ�é¶;éÿ÷žðêÞ�Fÿ{;Áh�u4³¥)<µÛG3›ÂXìÇ™4•3¶´IÓh,ëË<0Óð7šLk M»#4ùWS˜x,�f³¿ˆ@ˆú.‡f3Ÿ‡ï˜4¿8?”Kh~B,ü%l¤§ãk†}òú3¯:lÕ1zú±8î(¶�^²÷¯òѫϼöéðÕÇèi{2ü$î¤þøÄþ©�R{�;FýÑʸUî0õÿîž)µïøcÔïK�÷äÝÔe-í�Þi7/“ºÃe�[,�º«ãš;ÐG:/̢ðšo5ÙÓËÃkñ™Ô¤Oý•š«ß�×2“³©ù1ÞÜyÔl¨ ?•æSóçnjf…Ÿêk¨Y�§Ï)_yÞ�Ï�çèãhWøtž¸Lù;xHù·Šð_l-=¯/ ÿe~¤ü ô%/P\Ñ£èqPLäŸKñRYèÜuG¹0ôj½¼ Cî Š["мHq”cÏÑÃË0æ ¢ø:äbW(Mp`ðMj?†Ag$¥k%!N ´9F¿¢f2ŒF¯¥4RÝl  ¬;›âæX˜Mþ—BNCk)d5…é<;(ü— Ó 2)l„Ú€Ò—0_(�Êùª0ÿ¥ÆPfPø#T9Ç;2Û#€˜_(ÌÆ�¥2)tC ­ÓyûiÒ�BViÜñ9…õè~ÞŒ€VRø·Ýƒ!¨˜»<‚€êQ8ìâV [˜3í—x¶�B3ÜD¡‚‹-†àzR‚›ÎQªG"°2rˆê1¹•)|K¿¥P¹�Rh KSx¹“©u`©s„êä¦Q�k§QÝ�x OÃÚ')Ä×¥P ÖÖ¢P·ÕÌhX�Iµß[TÓ`ñTßIu,^EuÔtªcañXªÓQýGuá:ªÁâ©®ÝEõuXüÕ�Û©¾‹ß¤º}Õ`ñ‡T×Ì£ú,þŠêÂIT§ÀâÑT§¦º¯¤:èyªañŸT_èL5'ÖF]§Ú£<…æ°¶…QT߆µORM�ÃNª+aíTª»�ûÕë`iÌ9ªƒ‘Û�B?XÚ�Â]ÈMʦ:–Ž£šU7·PM/+¯PÝŠ[ÏQx V¾Há Ü*–Mõ`4,ŒüK5§"no¢p,¼‹ÂÜq/…_]Xõ…‡pGÜi ÷Àº(\Ì�;?£ðO ,˳ŸÂ×PJ¦Sx–½M!½ÔQ.‚UÅ®P˜¡t…±°j …Œò�FSÈn‹ZS±è ¿ÅšØ?)\-ù]JïÁš÷)}M¾ÃnT†%•nP8”º~”¶¸°"²™R?èWRzV¼DiB)½BÙ&ƒÒ‘BðÛ$ƒÒ¹jaÕó”2šÁÿsG芤øLL øKB–òÅ 0»�â¶|U¾í·ÇÁL‘ƒWÆ D1Ë(( SÕ/Pœ…ÐDͦx±&̵ˤ8ÕEH"S)ft€És(Žs w,ÅœaöMÊ£„ÀFù˜By„ƒÀ�¡”‡Â¸;•òH»#(Ïta>zå1.uGS^� ò¬£<)‚#c)oȃ`òo¡<3�EO£¼½‚JØEyQŠ›Oyw‚KÞCyM~’oå½I2iåíÉ a3åŸRlÒÊ¿…ñ"?Rþ¹ ‚NÚM9­ —û�ò©>qå“õ`´öqÊ;“†ø�”/µ…Á–(oŽG8ò.§œ~7Œõ½NyM>„%f.åœ×`è…lÊK➨‰Ô �À€û 5Ó¢&w5 òÂwÜ,j†»ÙÛÔì* Ÿ©[¨ùá{<‹òþjðUñoÊÙ/ Œ}nP¾Ð>šŸ¡œ>álužræ³ð|ï Ê—Ú#¬ÕS3, žÜ�©9Qá-ñ+5«á!ïljþ,ƒ0'®¥æ�òÐßCÍÖ„;f5gÛAÓä85sâvçÝÊY/C|8�rÎç,¸7�š)y D ¢&ýaØÑò,5{JâŽÔ5Ôœk[ÊÿAÍɸÕà 5ÿU†=I«©Éx ¹�Ü fK*lŠAݘ±ÔMŒ…eÏfÒWæ‹°¯ÍYú8Û6–û•ž+;ãÐãâxØê¾“M9Ÿ¸°¸Ëyj/õ…Ý~¥æ�*°½ÀlŠs À~ç±³TN?Šÿ‡ø'Wœbî©å�çGANMF¨�„CVP8L�/�!§§ mÆü�w@„€ D´ò*Ú¦E†÷°ÁxÿjÛ¶�‘¤»86wlÛ¶ms=¶m®FkÛ¶º{5¶m4•ûôööû¼É›¼û9¢ÿ ïù›�]ÿÞ×ɇÎøí‹·×Žj”Fó5»þ�/?pú`ÒWï­×¼|Ž·_ý§C݃”å­"0’£ÃºÝuÎßk;æ€oͷߦÛk;šÀk¨Ý«·éöö®Vð#çcÓ[Òø\ð�Ò>zÛûd.ŽM8Eïg&Dà2ÇäËô~öÑLö>D3ûúÂMhØQš9:ÆŠ¾Jsôg4÷N ˜p‰&/õƒfè5š¼2¢ëhzG9_¤é-1x-üÍÿPJÑiþ›bðVá0ݤÿõò¢Éc‡Œ›ºôµÝwéæH d«vˆnî$¿¼hÒØ!ã¦,~ùÏ4º9^^*� þïUmc�âí×í¥þZ#dÕ½B}ÒÂÖ1HÑ6+ÿ¢þLu¸¯rŠºÛÏ5‚›F;R©»R™UÎSwm]m¸©ÿÌ-êÎÕ„ÛR§©I[[n ­J£æ|Õ2Ç©¹º Ü\y‡šsåà.w5¯”†—2»Ê'÷SNl+/%wQów^¸ ¿Eù|_xívŽŽ´�×îg(†‹”¿* ïEÞ§ë Â{¡O)/‡¾é}ŠOEa"¼–îœ%!˜ˆl ø t¹PrfÁÔÄtáL�©É�ä…f+%gÌ�u¨u&ÂÜ$ŠÏAn˜ ´&Ÿ vL΢ä4…ú†Òk0»�š§aöyJ?BêK)9̆ž§øyfsüLiÔÈA wªÂtü û ÂtÅ[ŽD¡ ¤ôÌÚOår%˜ŸHi(”Ÿ(|‚•.2[Føú‚ÂoÈÞœB¢!|ižÆ,g4|©› Ð Ù^¥ð|˜à¿+áÓN oà¿<©TïW€_3™ùN>•½G5-/²†Pxþ=“”¾½Ba8²Þ¥ÐþE‹Á¿¦ÞÿyÒ©þK“¨¦çAf' ³`é ��¹˜ªS –Vt¨.EæWTÿ„µ)T¿F,•ê&X»�jj¬…°v…=)”„µ%(ôœBõ2,¾DuÊVª¿Àâ_¨ný€ê˰ø%ª|Cu%,^Iõë$ªs`ñ\ª¿ï§ú$,žDußiªã`ñ8ª§ŽS‹'P=þÕÇañ$ª{~¦:Ï¢úÛgT7Ââ•T¿~“ê°øªo¬¢š‹¤ºz,Õ´ì=GõáÖjÁÚr:§ð¬Lá!œ ú*¬ÝLõ$2_¤z5 KC'¨¾�Ì :ÁÒ&¦"³…m°t-…Zø÷Õ[yaeÎKT#k9…ñ°r4…�ȪOaw†’(´Æ)tƒ…])D¶~„}¡ß)ÌF¶ÂiºÃºÞî•BöR°,ú…— Ôs(Œƒe�RpêB}�Âùü°ªð Ÿ@hèPX«6SpšBzŸÂ½º°¨á ïA¬yŸÂ¯aXI¢p¿ä­”&ÁšI”ž†¦Øu ·ÊÂ’2·(\+ Ýã”>„¡�(=m$™ÒHX1†Òoaè›> p½,,¨pƒÂ½zp³‰Ò·a>ö3¥µp•÷¥…ü JÇrÃ]7J: à�œ®p»“Ò…ÒtùË”vÁuÁÓ”~Í�çN¡tº Üwv(íDpC/QJt�—u§#°Ó)®‡§x¥½Ðþ JÉqx«|�Ò�Æd“TJ×*Ák/‡Òù `… ”œ>ð¾œâ�"\Ñý—Ã@øŠ¿äAÀòþFñÃ0LäßGñÓ8ÿŒâþ0Så2Å7#Pä5Š—+ÃT« Š;CLxÅŒ607Ì¡¸A m¡˜“³(¯C@ÖQž³›)¯B –RÞ Ãá×)¯@–R~# ÓñO(¯„ï+(‡ùRþ—ÚGùD ­zœò�ÒB‰¿)_nƒ�.RÞ]Á(ü+å;=`¬Ë-Ê)E”|_S¾?†Fߣüs'ׇÔ, Á@h5ŸæA�b¯PóB ž£ÏRófÁ o¡æ«‚ð˜ïcj¶E¸Ôì­Oeþ¤f‚øèÊ[ÂCƒ3”“Ì~é”ÓGÀu¯Û”3†"¨­®RvV„à*4=Aùf'·ÖIjÞÎ ñmÔœ©� —J¡&©´E¿¡fwY;ïGÔœmMÝcÔ|]A�l¥&c,Äþ·©ÙƒÓÔl‰A /v('fÃŽþ©Ô|S Ùò½KMÚ@ØÒð 5' «æ~jÎ7ƒ=¥“©I†Ì�·¨Ù]6å~›gÍ:ê>Ê»ÂËzrV…aÝàTzH럤ëS ag‰ïéò‡°5¶…®¶Åañètjï>»Ÿ¤æL Ø^ì+Šß‡ýÑùiTRçFð¿ðÐÂäû̼—<¿$‚ANMF¢�„CVP8L‰/�!·§ m#ÇüaßüA B@P"IñÓ˜cæÔœ™Å˜óÔhÛ6õHû‹QHÙ¶mÛ¶mÛÕ¶mÛ¶Sm”íØù¾àÛ¿ÓéÜsß»ïÝþÑÿ„ëèóo~ë�s% ¥žþåå}ÓÚFÀ`TÇY_ûõLZK2Ïÿñö- zÆÀÛf+ßȦ>å™95`¤þ¢—3©ÏykU x•¸è;:.ùdj\ÆÍû&LÇ?.­ߟEw—Ö…‹&·§Ñ]ÎÃÍ`¸ÎÝAºÏ=P«ß¤ûÐõa0foÍ\_±;2i&ÿp,Luÿ�æ~hm§ßh0uC1Mæ¯ @ŒÜ¤É’Û£á¾Æ'4ýa„jŸÒôWµá¶Óišÿ§9”fGiþ|w¸’Ká“oÞ°pʰþ#§/»ãƒKt’Òú\§“³oݺdÊð~æ.ºá�t’?nFP|cy#Èm6}RBmáH”* ¶èí¥Í!7\òZ!µÁñp>º�ºSÛkÁIãÃW©Ë„²ÙÔ�Û\Njl9A]hœöRsqI$œÆnH¥&»w»TjÎ.‹†ÓÈg© �³¦×)÷ÄÁMÕ[‹)§_¢º!nb·RNk 'Uþ¤|¤#Üö>F¿t„Û¶?P>Z úÀ”ˆ†û„ÇèøÉ8¸�¼“ò{hS,Z 3ÛJé¨t-Ì, R\ ]³JÁñ055HÅó`jD¥¼V�#¾¢s“‹©-žs# (}q>¥Òi09§”šð2˜WBi ¤„‹”vÁì:jn„Ù-”®T‚°�Ò‹0}7ÅW0ü¥CPkåQ8_¦#ߤ�œÓ•NSȯe…Òa0Ÿ˜Låb}˜TJá*Æ]£ð¼¨wžr»Á‹û(¤Ä£Âb 9uàIÇl–—N†'53),G…_)ì�G#‹ùï6x´�Âø¯-…Ôxµ”eOÀ«¸ë: |?…áÝ-_Dó¢üª¡úð.¢2¼«¤zÿ¶§ð2,}‘B”­¢0–N¥°eÏSÍK€¥ñ¹T_@ÙEª¯ÁÚW¨^BS `í: ÍÆSèk»S¿‘jn$¬�Ì¥ºñ~ªÉ°8™êýR}¿@õÿ©Þ‹o ú÷ª+`ñJªç3¨Î…Ås©¦Q�‹'S Q‹‡SS ‹GQ çQ�‹§P-¸Fu,žC5õ$Õ-°x5ÕsÉTï„Å·PýéEªoÃ⩾tˆêXœLõæyTÃI°6>Duy `í ýâ‚T;¨†âðÕ£°ö{ª?¢ì íaiÃ0Õ{P6’ÂAXº‘ÂX”ÅåP=+ÿPÍ�ÿÏR+GPxå“(|+ß¡0åqYTÃÝ`a×0ÕÌxüw…Waá[B…vaªáî°®¥ž¨ø)…`[à3 _BOi ,›Bi<”ÀÏŽFê¸Óþ @�Di3¬ÚIi:„À/rÁ¢¦ùŽ ¥ô,z�Ò(ÈïPškfPzš¶E®$Á’ªW(„Ú@w¥Ç`Éc”n‡¶Ò á‘°b¥³‰ÐO¡t¡,¨q‘Ò8y�ÒËðà-J/ÂQƒ,JËàûu”2êÂÙ J]áó®AJËá0ð)¥“Iðu�3”> Ài“JïFÀÇQSÊiçK(ÞßFq ܼL)<¾�Kñ¸J:G©°?|:0Hé\5¸ë¢”Ò¾l�F)ÔnWS<^>¬y‚â:¸†â÷ ð]âwŸ��ø#ß�†ÏbÞ§x$&^¥øl¾ŠxŽâÕF0Ó·�â½ðÕÝ úÂÔÌ0Åá£Ãóanå�ðÍ.Ê;aòAÊ›á“Í”†ÑÈ×(†×Á«(¿ ³ñ_Q ¯…V…)~ÓI¿P ¯ƒçkÂO‚ùÚÇ)†7Âã ”OÔ…�ÏSÞO7Q¾ÐÞ´¼Ly?<ÜMùJkxÕî:åÛð(p+åkíá]§ÊEÀ“ˆ(§v‚—�R(¿ ¢ž¦œÞÞvJ¡ünŒÇ¿I9½;¼î˜Bùë$Nú’rj7xßá*å?ëÃh½ß(_ë?´¾HùllqšòŶðGÓ“”SûÁXÏk”Ï6‡_êÿI9 �É£|¢üS3™rÉ*YRLù×ÚðS•/¨¹5×�ýÔ|]þŠ{ƒš—âà2æij>H€ß¢§æÛšpUísjž‹†ÿ·Psº=\4;JÍ]ør})å¬QpÜÿ:åðvøuF�rñ8œ¤Zÿʤæ�(8ˆ¸�šìðs‡sÔ|”mâ+Ô\ê ×M¦æX[hšüBÍŸ�á÷Ä·¨ÉqP 5U…ÿ#twêÊ"jŽ‚J¨y9b¢¦d3l—MÍÍQÞà[jò&ÁžŽg¨I†²Áר¹Ô6Õþ–šâM›‹©9ÒvÅ>M—ÏÅú-%tQ²6ŽÎ¤ã¬±°³ÍQ:<Þ¶V}“Ž>H‚½ûJ© ß «ÇgQ“= ¶·þ‹âßma¥GÃTJNÄÿB—ÇSX~ýÑÎðANMF´�…CVP8Lœ/�@!Ÿ§ m#ÇüaßüA ‚@ÒÞ=�_Î$BÌâJ¤Ø�{1ˆ&ÞƒÚ¶m‡äè®3¶�I6¶mÛ¶“µmÛ¶m+öîNìd˜FÝ ƒ÷y«Þªw?Gô?á;«Çü{?Ùu¤”I·èÀ–wožzE* ftšqûûÛ¹L–Ýõé} zf!ØV«>.¥þÔk³jÁHÃEïQ_öÉÚUaÉôì~3%>sæþBï/¯Œš=YBGo­ M8C¥Ï¶„áº�Åè¿äÖŠðXý�(ýÇŸnƒY·–Ñ̉5ið�yÍ9š9w6LußAs¿@Ûa Ííí #é÷$h²lmbêUQštÊ„ÿšßÑô•!Tý†¦®¿] i~W3(ÍvÑüáîð7¼Œ[_½vêð^�ûŽœyË{ûéåD\Öó=¸;_¿qúðÞ�z›rÍ+[ôP>~Fž§¶äåÕ!7ZúaŒÚòa¸Ø¿ŒÚò7gÔ…\mÚ‹ÅÔF'ÂûØ(uÛVT„—Ú×RWÚÉ®EÔí^Q^*,ÝL]l ¼ˆR³gj^Ó–¡¦¨{Û“Ôì™™ ¯ÎÄ�ÔćÂ[‹S”KÖ¦ÁOÞMQʧS.¿.~R—S>Û^ªì¢ü} øí¸…>~m¿�¿¦¼¯ôÎÇÝ»Rà?óaz~4þ#7º¿Š@»ŒbÙ ˜Y§§ø"˜™\Jqt-K)• „©Qeô� S½Š(•µ�œú ¥’�07"Jml4Ìõ*¢ôGÄ”bÃ`rbœwLö�RZ)ÿ¥Õ0»˜š`v1¥ã!ÜBéi˜¾‹â« ?Bé.¨µË(ìÎ�éÈ›~΂é¬íÊëA¹•B¼'ÌgÿLåßš0ß5FáN\ž{’Âý¢Æ~^v®‚¸ƒÂé<\¶ŒÂ©Ê¤õi^Œ�@ �SX‰KÎ kPÿ(/¬A@Ë)ìÂ¥e ¨ÙL>† ÒPè„‹·Q¸ÁÝøEÛDá\pöQ-­†àœ\W¥„ê~ÉŽž‡¥ÏPèŒäj #`é0 k‘|‹ê™ Xš~šê;pŽQ} Ö¾@õ¸ÓŠÂBX»€B«ñ `m…ñ©žr`­s’ê¦'¨~‹¿£úÄ×TŸ…ÅÏRýz/Õkañ5T÷¥:Ϧz´„êxX<�j …¡°x(U—BoXÜ›žúÂâ~bT‡ÀâaTã§©Ž‡Å㩞û�ê2X<�êá¿©Þ ‹o ú×ÛT߀ÅÏQ}çvª;`ñ÷Tï™K5ž kÓ˨.ïMa0¬íJ¡onŒê-°v5ÕX.~¦ú7¬ý†êŸHÞA¡),­™ ú’#(\ K—P�dN Õ½¬tþ¦Zšƒ ¯S+ûRø'RøV¾Aa.æSu `a›Õ¢\\z”Â˰ð Oá²vma]—Bw\þ-…waÝÇ~„2–ÒX6œÒ8(‘Í6§Âªô�vE N ´V­£4Bd3…3µaQ½sþŽ@FéMXô¥‘�?¡4ÖŒ¦ô94WÄ)æÃ’¼B ±6ÐÝGé!Xò¥ Í?D!ÑV p)æA?‰Òþ|XPé_JcàåJ/ üÎë”Þ†§úE”f!ô‹(�­ oË) ämK)-ƒÇÈ·”¶ç#Ô•vSú6¯M‹)½ã Ä)Q*n ïK(^�ßLq1|8ïPr'"´]JïÂW•”J»"¤ÝË(¨ =£”Ž4D(›£í ¿«)n«ŒVÞNq|;¯Rü. ¡Ëú–â«0�óÅwR²Ô÷(þ• �Q|ÚA¨œ§)k3½Ê)Þ�PÝI±¼LMs)^‡]CÑ�s×P^‡Ð¬£| :ORt—!$Ë(?£©ïSt!ó\Š¥ÂlöÝÁ<—âO90]y3ÅÄB¾À¥¸­ Ì×ÞKÑ]Š€»÷ÕA�PtW#Ðe.ŃML‹#”¯B€ë)-@PmOP¾A97R>ÞÁu8Iù�8÷R>ÙA¶?IùÙT�òåÓ]lû“”ßÉ„ñŒ7(ŸîŠ ÛŸ üu> çAùTWßîå?jÂhõß(ï€0¢¼· 6ÚIùpÂÑôÊG»ÀX‡C”ÿk�°ÔÛA¹h :Gyo#„§úŸ”csadF”òæÚS¥ï©¹Ñ�oç*j~ªŒpe@Í éð™ö85Ÿå"liÏSóueøªð)5¯g |‘{©ÙÙ>l¦æÁB¹Þ¥|ª?¡Éû“ ¦?¦ÉgË‚pŸø5M›¡è�4ýcq¸­ušæOT†Rù$Í_¨w­Bt’¾sÛÔQ}ºö=óåß²è$£%òµH§“Œ�/L‘ܵïÈ)[I£“»à¦Ý=jÃ;g×�hºøÏ(µ�:#¯íj#;§×‡\{ÆOajt†óŽ÷©K[U Njn΢î~ä6 Q—¶¤2œTX–BÝÃnpÚô5·fÆÃiÁ…ÙÔ„š×¾IMÚ´8�›šAÍ£VpV>…rxC"ܔܡ|ûåð¦BpSxõsÊ•à¤àÊg[Ãm‡Ëtq²Ü6?AùXa8x�òûà¾ÈûtüQ!¸�ƒò'ТY#�¥Q:Ê™ 33ÃGAW>‹Rx8L N‘ñ0Õÿ9¥P%È�Ÿ(…‡ÃÜ�µ‘0×ÿ9¥Ýˆý)EÇÂäØ(uSarX”ÒHñ)m€Ù¹Ôl‚Ù•”®$@˜Mé‡ ¿Bñ› ̾¤´jÑ…ÌR0û…c…aºD…ìâPæPˆöƒùÄãTÒ+Á|¯(……È{�ÂÇð¢bó=j /Þ¦�‡|C)<® OšÞg^Î`xRá!…‘È÷…õð¨w„ÿ.…G«(ìÇU¢TïƒWS˜û>¼J̦­†¼yvÀ»-%À³Í"ïÕH x,ïªF¨Á¿U)üK¿£P ¹ã(Œƒ¥£)ŒCîTŸ‡¥ÅžR}¹ç©þ k¤ze(,‚µ ©FËt¡ÐÖ¶§Ðu2Õ§ °6á)ÕÉ©ž†Å§©nþŠê·°øª_¦º o¡zè<ÕÙ°xÕsiT'Ââ‰TSïR‹GPÍSM†ÅÉTÃO¨öƒÅý©>¹Mu,A5ë*Õ °xÕ'¨.…Ås©žýƒê+°øª¿¿Mu,þ†ê;‹¨fÀâST—¢PÖ�PݘÂ`XÛ�B³ØT_‚µ+¨>ˆÁNªWaí1ª¿#w …æ°´&…õÈíHa,]D¡3r㲨fÆÂʘ+TC±ø÷u ae2…‘דŸ°r…�È‹½M¡5,lMáv<þÛDá{X¸“Â6䫞C5ÚÖu mˆüßSø¶þ¦ð ”î”úòᔺAÝGár¬*”Bᄞ”êU”ú@ÚGáQuXTû …¿!¶�RØ{»)D;AþœÒhX3šÒ—ÐÔxJáv,IºMáIuèVQz–¼Oi5´/Sê +þGéBè{QÊ, ÊÞ¤í 'QúþþLé]8*“Ei|?ŸÒí$8KéiKø¼ÕsJcàô{J×’àë2)”~€ã !J»càã¸ß)…*ÀùHŠÛàã)Ž„›÷(އo'P|®/QzÖ>íöœÒ¥D¸kþ˜Ò?õàËÙ”7ƒÛ ¯”…Ë^£8î_§x4¾K�òáD˜O:Ey<^@ùL)xQá2åðt1å+àMÕë”×ûÀÊ)ÕáU­tÊ/àQ`;å´Zð®nå·càIÌ›”3ëÂ˺”¿Œ‡qŸP¾ÕÞÖÍ ¼«Œþ‰ò­Fðºn:åƒI0\r?å̆ð¾N*å³U`´ÒÊ©õà‡êW)§6‚Áz7(_«T:G9Ô ÆÚÞ¡|±2üRú(å'ƒa¨ÿcʧËÃ?Å÷QΙ #S#”&ÁO…wR³#×ÁõÔì-ÅBÍW…à²À'Ô|�¿_¦æPY¸*õ75oÆÀ‡+¨¹Þ.ê\¢fü9)Bù~_8î”E9güšüˆrdNxFùÉPø·ÍjÞˆƒƒ˜MÔ„:Áϵ/Qó[Ih¿¥æzCø»ÔßÔ\nM­ÓÔ+¿øœšû!vÿ‡šo ÃÿÁ�ÔDW¡Î S³-+&=§æÛ¢ÈWàmjÂSaK÷5çê"¯êajîö‚=u/R“ݹ=îPs½l*¹—šÈâ%9Ôì+ »â^£Ë·âaÝ´çtž »dÑqV7ØYý$žª [ FG_�½�jsV`u÷,jB½a{µc�×€ý_ˆP o/€ÿ õ^¾Á¼/Ô�normal.dark­2e1.0.webp../../normal.light/2/1.0.webpnormal.light2Ì1.0.webp„RIFF|WEBPVP8X ÇÇANIMANMFPwndVP8L7/w€W§ m#ÇüQßú‰ ‚@ÒÞ=�;Ñâ(Bܹ؈[qÎ…Ø‹P0D*˜â+dÛ¶mHÒ.·mÛ¶mÛ¶mÛ¶mÛ¶m–«rE#ÎɈ›ïýO8.Ó}þÑ;¯~$üxuûØ‚îåCa ¼r¯…'î¼ú™ðãÕ�£ z” �ù”�¶}¡¿ï;º¤‡£Ì½÷ý¢¿¯;º¦†Ñr«Ó^̦J°T{g<íE®«cNÐÉ•º°Õø6�œ©#yÐé±Rð[á,�.ÇÁ#é,mž2KûÍߨûúÁ^ÕkÝ’Á_x»sÔçãÏdêg‡Â_ÒΗ©„�–>j÷[À^�«T'¦ú¨ì5¹Cµ=ü—‰¢7!vƒzþ¢Í¯ƒÃ`7dL,•˜Šð—å-•ç%á$ÏÚº“ NŠ=¡ò!;ü¦r+œ…o¢�ã©á,Óu*Ç‚ ö¦r.-O¡ß5apšê•ÐrERH 3èg Dì¦ŒÊ e;åÕYLusL„]¤Ü Y‰òG^˜ ÞOå\ÌäüJY âe+˜J~…âiF˜jBy Öª”‹a.ó Z¾�¹”5aÙGñ2‹ýà¿„ú0þŒâ þçK¤è £õâù·Œö ðÀ¿É¯#`¶;ÿ,‚Ù°Sñï>E˜žy$†ûP<Äß’o“ÀtPr˜ŽxMQ &PL‚ÆSLŸEá�Â'Ië=xâ­Qaå)à )*t§h O´¦è>“"'<‘ƒbæ.Z£‚à‰ (Zw_£õ6F“r1e¸¶ål(é>S¼O —¦ý@ñ% ´>”«àÒ•”ƒ¡†Ü¤ðÕ…+kù(î‡C¯Nù&\˜âe øÛD¹.Ü@¹~3|¢ì×u ü˜þ;Pþ,—åÿEÙvvSÞMW¥¸M¹¶2¼£<7í¢|ŸöR™ �¡Òv—Pi ×´ðQ®€í¤7(#ËÁ%å£(¯'…ýÜ_(?æƒ+r ü’Nê&P>Êd|@™ØÎFP¹œOy…Ê88ÝFåt8ü•-Apšä•ƒ¡hè^*g#à<Ý}*;BÀ�mT¥‡‰Üï©ìEÀ‚ÖSùœfÊü¦²3 ZIåwy˜ªKeW(¼šJl]˜kž@eW(¼ŽJbK˜ì裲; ÆC6Rë³}¨í ‡áˆ=ÔÁô0jÇ’ÃhŠãÔ†ÃüjÓÁ`º‹ÔÆ #¨ÝÎ cYoS‡À §ö4/ åyJm 5ˆÚ»0Rü-µ¡\¯D*ßkÂ@¥¯T|}ÈöñTbÛÃqÓ(*‰]Ø&1T|£à°_"•ØVt�_Ô–…ÀAÐLj‘õø²Ÿ¨LÛI¶SûZ n(ø‚Úå̰™á<µ×EáŽl·¨½* [S»—nI}šÚ聆Qçµ éឈíÔGÀoïxj{“ÂMA³©® ‡º�ê¢`¸¬wµ Y ¤?A-qÜ×ðµ7å!Š=¡ö» ÜXò5µ˜.°4ûEíMi¸3ëeª‹Bñ'dº�Ú�ìpkÒ�TOeÌpŒêÁpoЪÏ_P� W·�¢Íèvp{é—´õª ÜŸémœÏ /„-¡ß5áðH—ª±}à�²¯¨¼ª/eØEkü’ôðXùŧ?D>XQpressed.dark¬2d1.webp../../pressed.light/2/1.webppressed.lightè?2 ?1.webpX?RIFFP?WEBPVP8X ÇÇANIMANMF&CVP8L /ˆˆþANMFš^WCVP8L�/^À'ÂsY.& ÀU�ÛvÜ6�Ð/À[_ ÈÂÄÏ×M\@àã¥�ˆþ'þçëúBçu¤üÅj.hø_V¿�ðà½àöÚx[ zlT¾±± ãÁ6.6g´ÿ²3ã v -ߨ{`²;¡ìÃÝwgžLÜ‚™`âµoT¡~Rf¨‚:\N!.§Ðp…†3¨Äá”âpJ ûJ©aJ {P‹}£N1œb8Å“S\œâ‡SlN±9Åæ›S\œââO ûF-ö tÆ”þ`SjØ�Ò‚ýƒÒ ÇF%Πðço §S8á ÊToÊ •SVPS†ÛJ‘áæÜ)Bc¥ÄÐpJ ZAÁ‚æ›C›tV:Îá ½ààŒ®s° š‘p=� ,H9ÈÓ ’ÎôÙ`rAÚ™| LÍp¦ F‚ ÃÐ\Ù5Œ²‹agÇ0l.8›Š• ƒäƒ ˆœ7ƒ*X-�9« º•§A< ýˆYANMF" “ˆCVP8L /“"Ï Hò§~ EµmS/Èóÿ3€TÃzÁÌÌ„�èCmfC¨FgU�ÊNÇMÊ �¶mÛuÛfó¦ …p€‚9æþÿÕ•"q9O}ˆèâ¼ÌËOÙøª·ü„ª2/?eã«ÞRðhþµÑ«GùZ �èÕ£�,¿<®Ñã´‹<¡Ñ¡‰/<»Î8u)<»Î¨î k¬3ÏÊ«GUI¬U<ùÂZEP/°fÄgI¬¨PIþcÝÕáƒSÖ-‚žõv¯¬®3Î_Ùâ;‰-œMl“ñ*‰m2Î%¶Z'ìô êÚ¶Wi¥×`ÊÈ•AZ»S–FFÂ{þÇG]Š�Í÷;¢ÿ GjS”Õn¬Ê<]Á‹Údeµkª2ÿG!U|µWNþÜ—+8TÅG{ådßîKߺ9qžmk 'º9qÞо¿ÀŸzm¹¨-°T½ž¹èTÂ�jz.¾6+,Hö=÷�‚sµëéäºÅ\µ³tÒÿÇù•κ³ÊžÎºÕ�þ(aA:0b«±¤fÄ5–m‹…ëž‘^,Íç�aù;£|ƒ‹##lá$é]§à&µŒÌ¦pU0®¡„»†Q5pù͈¾átud4'8V#1 ®×WFÑ%p¯{FÐkøØXoSøÉnÿ…¯‚aÛþ¶ y(á³b¸Ã~+†:Ôð]1Ðþ+¹CÜ!ŒŠ¡ 5B©–Ý"œ’!Ù!僱ÂÊ,±9BË,ƒè7/íÀU#DÝÑ{§fr¢g“ TÕÒëY!\õC�„½§·/„^ÓSƒðË�ì1d=�÷9âÐw±$':5 âQ?tx@\{:{Cl¯�Ø-âÛôtÐgˆQ.6kÄ©\xX!Úw.js9p¶-wÚqf§{râ¬? ì9ã2”–OìR¼\8ÙiÈ¡¾ùh?WEï/üÌ»F(ANMF†{rCVP8Lm/{€Ç„ÿjN#@"š»ÓÜ#0ópÌC¥ÒX’û»Ä$ ?I1iI!UY>y&E `Ûd¶I”ñ4±œbh£ÕEq�dŠàÁ*Œu˜6¡lCõ áÂ>˜g‡`½s â¤s ï @6�ºj¨K ÐÖ¶íIc½¢LlÄô^H/f\šÞ{E×Îßó?’øÿÿÛZ;ýOd©m´îþep¼9ÖäÎÉc—ýþýñº ÖÔ‘ÇäÎé’…L…•³€Éíã¨-î¼1m§QFêZ+`ZooÊìz—™ÎªHU»Ž™%:°¡ÄÚ ˜5jÙH,ÇÌÚݵ�}ü‘*ü$,Tñ2†Œ¹�˜ŠN bŸSQ¼‡L… ª{«aÀñ¨î*�ôåª §Ð7PåKiËÕFËø^Œ©¶]FºªGåKøœ‰©º]Eš¢GõÑÜÔ_ªo‘œ¤Ž¨K�y$åÎ(èI뵉áÕ.EEU ³(ì1‡!·…A»Cq~Ø@ñ/F6úv)²ŽŸ|‡"} ßËêâûšBoñeÇ”jã |^Rì,ŸbCÔ(ØY§`·EÁ‡×|óNÁ1Çü_,¦àÞ;\Sðmƒ‚�\ ^u(¸Šņø<£Ø |.Sì2> …öl|]Rè ¾)tßV‡"ý~v(²Ž>»K�‘�þa Ø¥¸hƒuŠ;À�‚Oa~ÃÖ(ÌÅÐÜ3E=#a"¦ Þ8’Ž)¨‰Ä‚G1í<’g(fiÎ(ä ©ìEü±‘n†"f‘¶I-¤¶žhü³…ôUŸ†‡%d™¡ásȶC£w‘õ‚_ sþ‘Æ>ZÈ^ôhh{*j� ¨™Œh`4Uó1�ë-B�Kã\¨Ü¤a;P[§Qu¨nРÔ7iÌt4iÈô4iÄt5iÀô5©ýèܧæ:ônQët»Ô¸ý‹15õ–aÂt—Z¢9˜1áSC8 Sœ6•ÿ…9Å*þ(Â$ûžJl˜e�Qá¥ã~SY&º1•ôÖaæt— ˜êxÌÜ…¹¿î™ñцÉÖ)3�[0|›vaþ\—)ÿ›‡Çcª�QȰo™âÖ†”\�‰‡�´ÐåÐh ²�C>F!­p³¯wœ‡ÀÊîíÇëÍnANMF:kcCVP8L"/kÀ'£ m&þeïxp\Û¶Òàî2gNTA=,ê¡'w‡xòÞ_ A‰DaÚ6Lv{ *ÿ¤$Ɉ“E''LÅD�Ç.üÜpóÞ�#/Œè™Ñò–´¢†å‹’9Jzä(ù"çÇ)?1€”b@Ò1O„r‚B!€�B>‡À¡Ý²mÛVÛfûÊjLaff,3³Ù Ǭîÿÿ†€#]]�[zŠèBwpû�×eOÇ{³1ˆˆCÛï¼.{:ÇïwarèÅ%C/_ A{ôU�¡W/‡`FÍרY[€ŽZ;¦¦·SÇŒp2‰ÐÙsF8™AÄÌ7FÌç8PdÄïDYh2rs«mFn.C[=¡‘7 =Î[y® çþ¤¡r ·©" ]è<¨ÐØY×éS«¹w«4xœº®Ñ ç"L}§Q¯L£ùBžRôsÏRø"‚²M ofðƒâó¸?M fÑëœÑ‚s…žuZ±‰;uA+.¸�¥%ó¸-Ò’"n²´&ƒëmZ³�ë ­©Àõi�Ÿ§EãG´èágZôé˜ymZÔâù6-jÓ¢ãO´èë-:§EIŸÖø.J´¦ˆëuZ³�ë mñs¸)Ð’M!gP4N!㢘Ãý¢˜_(”ùã•#‰‚.#ßKA½Èíñ(Ès�=DQ‡�½GQ÷�ýMQ¿‘�¡¨X;µ]RKa5mÖ¶ŸÂö¥°£Ç)ìØA ;ÐAa�õÖ˜ñ)Ê·±HQ«Èþ£¨^dïSÔd�SÔId÷ùä—"7DACÈ_§ [È×ãסÐK1½�¦˜3Y«²b!|…B®£ÈY£ˆuÅW(â*"ìy ˜·u‚N!ú�ÿ‹˜Æm¾U‡¸;4ü&bíI=n!¾Ë§Á^'’ܧÁ�(3Ic'l$kݦ¡[-Hz�†^Dòw4ò œ18î@¥vƒÆ­×@mÿ. ÛÞÕs4+8õ»4ê.t¼¤A¯ ÅúFc~–@�ÓGCú3ÐåŽÒˆ1úJ'hÀT)tVL3õé è­šfÊsÐ]5ÍTç« ¿jŠ)ÎT!�ŠI¦6U�tJG˜ÒX)Òrû˜ÊÐ^¤çüa ÿ¤i ö/6ÒµžRó+¤‡:ƒ{0á‚Omþe˜ql‹š¶NÁ”ÎujÙì�9uSÔ0_“öõQ¹¿fÙo¨øÎ†q·*øw`â©-&Þ: 3ÛW˜pµ¦V 0ÑPÌͼb‚×6Œ¾ì1Æ»Ó÷¯3rý̯bÄH5$dž ùOmi{9ïeç_¶!ANMF8wnCVP8L/w€'F�mSìýncÛV•wwrB d¨‡ŽBw}öƒ@ÒÎ_mÛ6Ìb§GwˆgÊ$3jÌgÍ(;ö s¤›3­œùM%æM!o>äó%›/v˜tþüI%�ý¤’ŠÁ� bHæI"É…>xE¡¯ê(´þ9…¾¸M¡w/QèÕ£zäg ým….J¡Ã²,Š´3qƒ"ï!ôEnBhEŽE(¥…;SÞA�K�£IxBq¯]Eqk“ÓFaíÙˆý‘Â~G\~'Eµ þkŠúuTŸ §´Ž ×(æzœZè·¿(äg¸f¼¤ˆg©pK£áe'ì‚§ì74þM¼ ³h¸= ^ á?ÁsòE}1Þ ëhp}!Thl`Ô–ÒØePý�†n‚rÒ)y6ê™·ià�Lè(zEã^BOu3 k®�®Ï:iT×çÐ7²�õŽ�Ω�ùôδhˆ= ºçi„=úi€½~,Òw{)ü™oÑg{ üšmÑW{.ü›ÑG3àç¸núÖ3þi£OíÃà÷'�ô¥ùSø_ùŠ>¼­… Å÷¨ýa ÌȽDÍ×ó`JÚ1j=™s7QãŽDµ–ºì�0mzµôÎ�y_4RCÓ˜Xö�Ê�+`fÎ9*žÏ�©É[¨´;¯°èÙ^³GµÐcëX˜^þ€žVÀüì“ôp"¾¢›ýS„Ln£cû È©|@‡‡U�”¹ƒ±ö¶t«ýåj}èú¯5ð ANMF{rCVP8Lþ/{€ß1’ä¸MÔïüÕ/á Â9 È‘$¹Vzzf¿@ëpÄì!°'°C‹«Ö°oG8pÛ6’ˆ¤³÷þÿ¡sÏ6]I[8µmÛ0£SyPr†S9lj\àÇr‹#yÀO8”Ìð�}i¸ÇŽìÈ#¶å[òƒMéö‡o×iÞŸnkKþ¸àÓíeá@g¼»÷•­¤c©^ýúßseÏRÞ9♥ž¿û-ÄÍ`o÷½Çi�{ïù™Á÷Þ<íâ¶ÏüŠÀáìpëÓ®Ž&iMÛÿÄ*ßþÛ†)ÂW~¦4}ýG“ £5¤tk�è:ZÃz­U ë ˜º4#:eËP–ŽÁÄÐ^G‹iLUX&È,„@&H­YíI¨¨ @�V $�,µ Ír”Ud)%�å(T¡YF©KTþ¡bpCIRJd*UŽBµ�¨@¦ŒJòË?*`úÐ4BM£579j”Í#Âä¨y˜µ å HˆbæÐ&G J€’ (I¥" D ”‚HP Ô¿Å€¨ö@‰¶mÓ¶3߹߶m[±¿Û¶m7?¶ÍÛvòlÛ>ïÍÊýçl­R*ýOhxó�ð«ÆV}ûäi«#0Ðk§3Ÿù¡š±%_=rÒBXˆìùXËžÛÚZ~¥ŒáOì�Ñ1ç¥Pµø¦éP^­ jÚùcalصÕÔii:”í VíÍ#`¤×9eÔmÚ>¡ãŸn¡n厡¿âgš(܈�ýKhâ÷UÐôÎo¤¡g‡ `ø+4Ô|¹��oÐ\âÄÍK¢¹ƒ¡>ù7š,Ý1»—ÐäŸÓ¡:5�f›¶¡kKÍf΂ڌ šö7£c¿FšÎž •q4ß°v—jšÏš€ðþßÑFmmü:aÞ«ô¶‡�)êtÏ®¦¨Úùêù…ýÔ'RÜ©ˆR@qÅCw#ÞŠØQuØ01—Qä•èîW@‘ÅýÐu…Ž®O)ôstŽj¦P4:Ž¥ØÐñ.ž‡H)Å–G–Sð’£)ø¸{)ø¾(ø£$ Nn¦`Ÿÿ‹5Spk"'¿OÁŸÝNÁAÁ‡Î¡à…^.ÅVFð2ž…Ž(ö t i P:ß¡Ðѵ‰B7¡«g&E÷F÷ybFUS`íHÄÞB�÷#nl-ÅÕŒCü w=çSXáMaG!°ÇÏõKÁ«Û(È_‰°ít'BgRLú„¯§˜uPyžB^€ÒðŠÈµµ±ªwSÀ=Pîû3�ÿ¥Ô§”Òñò)ÐYÛF§Û×Aï":}!4½Wéðë Ðð�ý¾ôǦÑÑô±0±°”N–/€™]ké`ýn0µÑ§sþ&˜;’Γgѱ³aöj:uLßB‡n…q/Jgîƒ/JG†/J'M€/JH€-ï6Z¿6¯¢åk`÷ Z½¶�j£µöS`[-µö©¦•ú pcM -”ï WdÐxÖ2¸3ñþ{\ò%�~3 nõ}‘ßì ×¼kiì.ÖL#þÉps¯ ¨Ü®.L¥vúR¸;êkjþ8.÷}ŽZ¯õƒÛÞ¹mTn¿4ί« båHX˜H¥ä…�1ôc*|1RzÜÀлzBЦ*Ölƒ¬…ÿ2à¿%�6ø)Ÿ1þムpæ%ŸþõÏ'—NƒEANMFø{qCVP8Là/{@ßç°qÛH8Ù§ÿjŸ‹ 8¸"`E’,[éî9o5€´ ‡@&б:x¬çœ™fض�#¹/ûOÛ.�€ D¢¶mft*ï,Ox”g<È ^q/Ÿ¸â„n¸“þ,‘øÆÀ²«LÛv–e�aBܸ{ÖÃQ7îžÃ“‰…ƒ,ä‹K—÷ðfaá g?'ξŸ�«ÎŸÓ—_6§NßþHiy¤øåŸ ràè§ŸÍ�£ )©‰Õª�<±Z܆f-«6dbµ¼Ÿ¹¬ÿÍ�МË»Y ²r3¨2:M§�*» T€FHcЗ„²›6ÂËtJ¶�JCJ÷•P®6P!mÄlHˆ&£ÓP�¤!m‰)Œè@4BÕ#�4#��êŒòH¥I9”šD*Œ¨(M�T�Ät*Ž@b)*Hí)Ží`3@i Iô‰¤(N�Ä4Eƒ Á�(„A1¤]gP`€HÌ?Cƒ5lÛéͽ3Ù®bÛIÝÆ¶êÔ¶m›©Û¬mÛ6b;Ÿ§¹ÿ,g^=ýÑÿÄÿ”·çUË~ªbIÅ·ó/k}¯óUK~¨dIõ/O]»·ó^Ÿé먰ü‰ý¡ãõŸ¶† ëg ˆÁhíK¤òW§d Xÿâ©üÛ•u`,}á:j­=#…Ô¥©µñò4ÌŒ^Ní?F!rì¿Ô^y( 4œG#³ê!´ÁBYÒº½ÖÒÐò~´Š†6„ÞY4V}&JΪ¢±êó¡á=L£÷ùÈûwÓè$ªþ$^è#ëÏ¢á9>Ôü™4>ÃË>Jãó|(ÝA �ÝL @å¤Ý”r¢¬ ˜ª¾ˆªó­¨‹ˆ©5áÃwSÖ„%~¡°¿9�â.Aiý�·µ>J.§À«QœXA�«(:š"�EÑ[ù. �«)2h‚üÙz.òoSèûÈ¥Ê(´"…l/Ší‰ì5{²Ë(öid¿¡Øoáí¤Ø]^S nÚ‰‚;õ¢àžÃ(xèX >ü` >d9€‚»·£àöu)¸ÖRìfdß§ØÏ�O±‘=žbOD¶ŶEn9…®Ž!÷$…N@~ …ŽD¾Ö:ŠÜœ@áAŠ|EmJìˆâ×(ð=”Œ À‘(‰}Aqß!dÅ„ï û¡ÝÊê‰ðŵÍvPÐÎfˆº‚‚.BdükŠùÒGô>ÕRÓ*ã(ä^(eþ¤ˆ¿2PëP@ЪwQÀ�PN|Fç?�C½å6:¾½%tÆt{ ôn£Ó·@Ó‘¿àA·î�töçºÐoµ�Žnj ÝÊèdyO˜92 ƒÁ0u¼æn¥s·Ã`l<›£þ:µÈ‡Ù=ž¡CÏÇa:ù �y) óé7èÈ›iØH¿A'ÞÉÀNú :ðN¶Ò/ÓúëØK=GËÏ&a3±˜V—ÆaןL‹s}ØöÆÑÚ#18p=-Ý7N¯¡…ÿ.€+‡•ÑxÕQpgÀ6Þ1.uXI£ëö‚[Í ÁŸ[ÀµúoÑØ‡ à^b6 -JÁÉš¸ ®SFíŠàn÷ ÔÜÒ.·øžZ¿·†Ûu_¤Æ«õáz­{¨|¿Ç•Q©üÈØw%Öî)�?`ä§M 'ñ8#¦$!êÄ2†”Ÿ i]eÉÏ]!/yÚÇUÌVtjöANMFÜwnCVP8LÃ/w€ÕЖ$I±Ee_0éÿøÒLOM×{ŠqyW¬/3³AŽ$I’‚è£*ì =•Y½Ã ¯ý"ÏÈ8i϶m›³mÛ¶mÛ¶mÛ{7’Ié�åc†x X¸´JUÕJò�˜–Gå.¹¾‘sP¾XÈâ<`ÜÅòk•ÿß�÷äiXn¿÷õA¹ÒlvÀ{`P›Cåîðcð¿,ø”¦[’^{vàxÈšÓÅ\ð=—�¢§†hÎÅ;ô <å±àgv‘÷Úˆ'wcZ¥ÊdzKøOš ½næ�ãk36¸šý‚7©Žwª»\­áÏÙ/|ÓFxÎ9v )$8›ÛDÞ› ;îð¹\qun¹hŠÈx»´r^Îí‚;äå/·çvò"Ÿ¼Í×¶Š ¿ÏJïØ¥gáåî™"øhJÞB(í3Ë•�}ÁñA¾˜YDïÈ !šX›y‚ä´mûðæx0óˆ-îŒîîJ'3Ó‡8Ò¶Ûy53ç4»³Ë–|:sÝ !öÁ«ï‡3Wp‰¸]ñNÌnÎð/ñ=\ᯙ-|Á…Ò¸¼8ó½ú{æSVb}rÛ,BêYí§Y‰X‰wfø¹Î‚×åGΨfg!ò¯K;ˆï,…\ˆø•Z»óä⩳ȸø)#¸­¶Èý…“FØ,‡-âüc‘vëMÞç 8ÛšY¥;›\Yqt•m0¸ª¸àú�}4´³$¢µŸ×�aË£5'�™ ?Õ\äù_¬YÔõÃa¯:°7ÇT#•W]&7Wi=U½ÿVŒË3U‡g¥‘ª#cªîª£{¥Æª£[EqÕAqSxÕ½CÕQV WºƒËš}g‹Îšƒ�“µŠª9f¢ýOͱqlK[“l»UFÅAÁÙ~ ÿƒcÛ–&êEÏÙ¶M»ÕÓûüÈÇÕ', ÏkVmŒ_pS>­Up¶ô‡®5:tñ÷„òF¥è­^Â4Eþ �6z™ÒU'èñ 5x©Ò¿{M#¶Ê^x (–jÄ\øa}&¢ðW…"_}An•Ya$Ë]8@ÄÚøÑëŸ÷ÍL~ð6záwÂs/fØè#áî'uŽtxÞ‘òÎÈ‘½k[æ/ƒ§qûïoöàgÔ‚_¦Ó[‘¤Q‰ÞNÔ�4:Áçb|Ä`üóŒ™?”¼>^°ùÈ9XIÒñhÁÉ g¹¾«{×�ç]ð0Rá'6‰3ñ®èÛ­ðR;wýo£~ÿÄÙØÌ‘÷1 >ˆÅù(ë‡àó©÷ðÇßDÞÇ�»>a³{/´1xÝ·ßÀìý€f×?â= Zï ¤á»ý ySx_Lþn¿6½öÎ{£˜òÑ>Ñ'Àòþx'îòå˜Þ²GÀ@‹éü`žÖcà“z²ƒp�‚Hþ£)Ô±€J ~óÎEþ ÃcÁÞÁGV¯P G×:¸Ë)ü„LÏuq˜ó˜OžG„ð ÿ¡L8<&žaJóÖ ã_‹$ozŠ�él� »ßèï7ÚËccwÿªš>e“xtLBç?�ÙχÏf‡HÕ=ѵ .�{ðêçÌȉpXœ/÷?h\Wâ£ÅÇÁJ*”ý9d†ßΟ», ‹yG¢™]ÒÒÜ Q¼à¼ANMF¦vnCVP8L�/v€ÕЖ$I‘$™Gƒìþÿ'7TfVÆÒ“/3ó=ñ]3äF’$72�nÈÞäîteÕ ÅSzíWöl@”€¨s¶mÛ¶mÛ¶mÛ[œmÛöªgþ 7’Ié 阱w_àKîÒ…†Ú¢V¤‰+s�È,ù6 Wpsep7îÂÛæ®Áâ^°ë˜ø ­†Ú7So‡ƒ"qða-ä(d3ÇÞtîâ›9%´(hµHfKGÑJiÊCïÚ U�ÕʬëFûÉ8ª÷ójôÁ}ðv×Û`£z|â¢êZQÓ·zDÛÇ1/' |U�dZTãâ‹Áb1wHÌêBA¥û.Vž;«ÄÍÚgíl'žj‡D¾xúbý¯Æø ¨bÃëlù‚ÚkŒ(øuOêÒY ‚ù9ùøD!5Œ¸â¦ÕÞ¾™ˆßH:á¢dÛ¼Äq $ÿ#ËÖöGs鿆’ÿµrÒm %p~¬ÚÚ_Í/(éd)Ié´Sˆ¦;JÒG 'Ÿ…vj8ù‹¨.ÇŸˆ8®Äùòë‰6–£ªÐÔRÛ9¸ÒÀçÊâ/ÏdŒ¦|vV"QÀ¹v‰›i…íNû%ØKU‰Ã_N¶•w%þ' ­e[hó¸}7y•mfG õ§«È m³|™o2ö&ãS€�í¨‘ŒÃ£¶Å[Æ)ï6¥^)a o*:çPŒƒŽœct8j)ç‚E‹‡œûÕ‚•s?¸’º¦<Áə±xÏ9ùÃQë9G¶Õ›s?{3§äN6èçÝĬ<â7c‚øÜþ/ãÈ´íM…dDÙþJ¢æK¦Ó¥lûÏ|;ÜoSÎùv| þ‹¸Ê¹;9ÞTr¶ádã_P~Ë•üE ùÄFé¹™>õ�ô’)ù…­ Ï ‡eŠ´}æD,´Ÿ'²·p 6ÿ0K ë/:³ŒÞ¶”ùHÈ9’_YDg�cÈÏ  Cp îò ŽÐå?&ù¦Âæ-Ü�Bc³Gs+îⓟŸ�G¶âÍ3˜ úÌ)´—î@OœyŒ$÷˜ùL÷¹‹@°=kôÝ7�3CN<Ï™òÌQÎݘ >c A <v•˜ó%3nx9Ýy†ÂaD{ÈŸm$ßÄæŠ[Ó¸ÌÊê›)ðH¬¼ÁÄ<Á4Þ¡3wþ(`–xǃ±È„o;ã…,°´W¸„áõc,üo¯r AkGÐ_¼’;ÁôºÑgïx5lù‚á5cŒ~î±òDu¬×ßlx½®PÍZѼ:œ»ÊïA…ƒ =½Âõq2 'y Ì>‚::™Æð÷$(›c“1bïi`�¡O*¯4CO„R�NÆEÎJž “h€Ž ¯rŸ+ûóA‡*¸ÿÎlÙ†™Ý×’ï)�¿LîM¦�@OêçÎ[¤ÈŸÈÒÓ¢¤Ãžð)¨xbÜ…C“íá¶"žÚ/¤èiãËÇ%žø¢%…@~N€¡+n–à︋‡à¥È"]*Gö/¤ìì‹x@ªÞ8º÷™ŒËŸ8&yz»Œî8½�£œ³aÀæ$ðšÅŠ¿qANMFÄwnCVP8L¬/w€ÕЖ$I‘]EÖìêÿ™v¶»¦Kð–â'f–Z —™/Ù¶Û6Úÿ\¹ÏÀ÷=€‚sÅ=) X6š}¶mÛ¶mÛ¶mÛ¶mÛ¶}—Ý+ ¸‘¤HJoH»ÇŒýwáÎâ\ºa”(:sJ´ØŽˆs✄MØ#¹È!|ú% ¢"~K 8¸>ô¼x]÷ÛȱbVúÿkQ: —.6¦H݉Š˨jqòÓ\#¾Ä\²é÷¢ñ„ÒÅíl!~C},ýŽ—ŸÔRæò¨ø›-Ä}T&‹7óÚîCIŒþ4›‰³¨0ÎM˜dQqÒMûK:U“X5ëÚ~ˆ‡gqµÈ��ðQú¹¸Ÿ}nr•ʸö%”-Àì&vˆ´�Ø¡ :šÝ~ŠQÈ¡»]SG3Ãý¨DNäê]Ci—gé´ó‘¸@—ò}7“HË„Ñ8˜”Õ™ärTpOOC•3Ï[†¸mÛ'ÞEÅå̪gcš»ꟙäw¦žmïJK¼ÍLÒÈ—ÆøÇJÃ3—ø!Zö®”ÄçÌ%Æ1¾)6"˜Ù>"åý»„x�ÙäQNdËB…3ßSéaæ‹*oh>³:Ú¾‰ýZeâïö±§.¶gbÿÈeÍBHþj'†€ôWiÐ…×öÃ,EYi÷¦=‹!º‡“§«Mš?hߥf9,™3ÕToQ­¶mÕ»zlêÓ[Êm§'�TÜ·¶ù§¼_q—oØ‹ gI`d™5‡³l±XsbÉ<ÀÅw͉ŸLÖYÔ×]S¯:¢¶È½ê°[TxÕAx(¦êpÌ…ïB¡U‡"—áZuÄTªîÂXuˆ�ôçšÉŸl„ÅTÍ‘i;”Ts�a³4jÚl‚øª˜ø~pruTî·íeXUr>=6¡à>㨒z#U¶m³ë�’ð™ÄXµð¸°Tª�hù@µ¯ÑdÆ+°b­%¯‰ê¬îñ*.ñS§_).¯ Rê R} '�VIó€=6SºU«[ê¯v¸Þ ø¦‘*$ÿj™±u…!›µ×²ÖÒéF4jq5zâšEÕ:ÿ/ƒ±D¤îv¡„±ÇŒwàbhäÈ7XÏ|CœŒÛu t’ÞG톈{aãAŸÀO÷Ý�<æH˜3ü8b¤Ä)؈P÷x¡¾¬S:ücÅìhá9ÎYø¡�¶Æ ïÐ)œ‡A/ŽFŠƒ3q°Iã$®»s÷ÝQ· ^gÃüânŒÄ=›ßù˜òí}â*ä-Оµ·¹ü°uâž.ì­|~»mw¿÷v0Çõ-çtNo‰Æ$ïm9Â,ÞE£Zß*¼É¢óÖx%ßè�žc“{{�côn¢á<‚k1jòà œH��4HÍgÿ2H¶‰·™×~ºí‘`“ăƒò7ÓÒcYù.+ñL”<š÷ò~Nøñy<¿IÓáYõ€Ù:Tßizê1ý‚£ê 'üâa�™üÑsílç‘1%:Žß%Ò›^,´†�Á£{ªm ê¸Ç¸ÐpÈS$È5€Êëc‰'¤å*ØÌbe=²†Ø]T¯…kxÀºl}ð £8+WÃë@Žù@"Aûš7ANMFüwnCVP8Lä/w€ÕPl$É‘$™çÜë¯òҙgÒɱmÛm›3tLÕzçü{.û;G¶ÏY�$›¶Õ϶mÛ¶mÛ¶móÚ¶mÛ¶í·ßÙ§¿¸¡ÃÇñÉçâUŠR“üN%ó«ëŒ·�2 |þ8Ž�‹Gæÿäwª¥¸xM¾<Æ Ç`ý_cÖø±¤mòUj3nÆ+×4àÖ_™7y_“‹6ù2Ó&_s�•>t~Œ3%&y5CöÔ¸hv}ìgJlòjÆ?z^»‹üo?^¬%É;YògL¸`t˜^-UÉ;¥|ÆU£°â1¶e^òn¦»·/û¾š›¼›…²¸mö�a‘\11·÷žš}'vÉ£­öîýù°²”'×”b÷ZàÉŸ}c)K®Éj]Ü™\N%¹*U½üo5¹*5“[ÀeÏ¥‰Nråä·)_¦<þL®œadIÀ5K�“kÓɳvÀ‡)Ol’kGKS®XÒÄ<¹zbå¹dç0H®žakÊÀ…É—äú‰Áôsrý¿�×�ãlò½ ¼ú“¥©$I WÏ]=2?yL)6{Og%š˜ÏcSò(Ùüöh—éÉ£J¶çí�_“ËÉÃô:ðÓìZª’‡•Z£;ðc¼’1HªæsÜKª¹*y¨®Ö.EI™ªßÝ�–>tjòH�|fZòÀ̳àsÆãä�| |qP*ÉãRÕaÀ÷ÖÉãÔø!‹’ÇÉ"àgú&Óà—kiò0]üN¯äQNoà‰NMMò T9x6ÑI¤:ÀS³oV'�ɳ/ðÜu:yŒž^Xb Mâ €¼rM*ÿ’Gd›c<ðzò$y„ó1pÁóöŸ<@<ÚWÜÓ‹’Ü>ή�w’ÛópÑ«OrsúÙDàª9°”%·Î2÷àº}YùŸÜ85Æ àŽ^On¬×�{ãä¶jÜôÔ1Ó›j¸§ŽÀ]ퟹÉ-3_û÷ubÖ&7,u®IÀ Yš­ÉíòŸ.ÖÈ®Ô$7KÕµXÅs©Mî弬Ó{É­ô!°rÆ»äFÎ÷ÀR3¾%·áO`±%Œ“›¨Ž%«mâ Ýäj` Àz›8ÑIn Æ6x‡Mœè$ß®†6x�M&߬¿-x—%L>$ßêü¼SŸ$ßÈWÀ{õZÑ&ßÅ;À»õDj’oIUOï—í¥5ù†¢{�Ü˲>¹<e °gdirqVø2 ØÅÇ%#¹Ts½ ìãîSÃ’ ¥ý��üì4Ã6¹L]=:{Yâø1¹H{.ÛéùÔ$¤*×�ÝKcòvmrlötM+É›Y✠ìêPÓ·œqÎÁÀ¾fÇÑ‚lîÚ’ ÉKÙhlö7&—œäg§'Ø{¥{ò¥ú²7p†ç’¼,Úäs~´$àîȆä“ÒÄ=ÀI>LÌ„ä/�÷ip–)»�d`ù—üÈà:ì¹¼ ANMFâzpCVP8LÊ/zÕЖ$I‘$™ÇàÿrCUfTÆ>»l-Ã33_ˆ@n#É‘t¦¯ëBÿFtEdOã´¾ùž=’ #)ƒbmÛ¶mülÛ¶mÛ¶mÛ6϶o˜@p#I‘”Þ�v�f羓á &LQåË®ËT!dá íDœƒ•£â¦ �b¼pìÞ ¼,­¨4eHÜJœ ž’ÿÄiÐCä¸îFC]n*ABØ#Ïfžz%o•á¨tÔ¡�Þ]tk9"Ìuò]T sCºÃƒ‹2�ê–Ÿæ:ùSŒ]”í»É×è\A¾ü0[‰Ç0šbp#k$E¾š­>‰*â…'ñ“),};{ˆŸA …ðF抿³‡üTÝKºÆ:Œ‘¿f/ñ>ôYýbû2*T~™½ÄŸ0‰Èèz‘Tög¹ÀÁéE·;¯XŸ”c”í/º¿ÀÌâÃÑ .v×»3‡Ä`hçµw£êgž·gßc\È0oæ [º~ÂðM)Wg&9ÈFjÛ߆ý3“Ü≺½ÿÅöÌ%×™½‹Å™K msbof“s;' Gg6qÜxy gf>1tÌ|b¹íõFUÎ"¢ê[ºØ¼fLÿõnþ÷êLþùiõ‰”­YÈÇÜ�•EEÌR1ËQ ¿×šüN+¾Äs¤v)äØj“8ºà¢—ÏrHÕy/ůz“¿™tg ¢fA$îlò¬âäÅi׫Ø,‰ˆŸ,H­9L?™<¨9qdÛ4ªW5÷ŠƒÊö%F³(4¶=£ê0ó09Xu8d[œU�<µ¹!ŸVÝS.„™L³¬'fÔÝ#S2uÇ�öå®Qw n¦NÝQºFź#Jæ©»ïM8êŽð˜O‰¯ÚýÝ–Ï«î+Ûb¾êpÍvXYuXcû¢;Wq±ýEÕýdÛâEÍÄ{.ÄqAcÍa“mû‡šC““qâsÅä÷“CœvXS°…ƒ /*Ž(ùŒ\¯îùXÕ±\R\VKÜÑP^¶ÕF¼äKyR+<[¹“õk�ÃÈ+äD¥pb-³ È¿uŸ­ÎAJ�‘ÄõÌ,n«„M÷)MA¨‘Ä?w“ ¶ÆÞkËT%þLúˆ¢lœ‰�$ŒŸ 0 Ý,(¤¬=ïÃÿÇÓ½cþIþ»ÿAÈ]VC÷„²q§ `äaao~ fÆ�ÌÑPÝ3;Ͱ?Èñæ#'x&>�™üÄ&à 5ùoÄÄ_žÔ�„XÞ/�Gk§ÁÀñ†!NdŒÉÌÌ< ;ºBª�‹ ´�é|�p:(GG Ç8o€‚”±1bL¾kW½�éÍΩ|÷×í#S»7ó»Ú:2Â?è q"�ÛFzޝhC4Ô§[ÆhþÒãBDn)ÿ}ëlCâVAª‡€¾ïmqí>†x`%þç'0Lõå÷ìäO#ä…x››üÀTðP€[\g†÷<ñ{0LºÄS[q›bðp((èÌŠ1ÄFêýΑ‘pCzLÄ]bú¯ zyXL�îÓÏåWb0n6]PÞôEž(Q�7±ÐY=¾Ê¡qg^bÍk��x?o|ù _—€{K;Ñt„£áv<¦s¹ žàHÓZ¤‹�¹â¿ø"žcˆ‹a¨-ÈÏyTs9,$öä8“¼aDoødANMF wnCVP8L/w€ÕHlI’$ªfç¿ÇûÝLwM¥rI’$)D?yv÷ÞÙª°¬žÅpG{òtH€$É´­~Æ·mÛ¶mÛ¶mÛ¶mÛ¶Íg|<\ß»•¢Þ|>ÿ”{<ú­½"—š·ÍïæãJ\ ©ïꕵW>Ú×®èå+Ú`|ì*Ë€µ×4×ò>¡5>îWCê»\^]ñXý(ïÍG´ßNþ˜«›Øðªù·~èå•Vt‹Lk¬§š„ðªþ]=üؽ])D[?åW·&1\‹mu�SEtÕíõ±ëäHã תeÙa*‹¶}<*åZ¸“§v}Ñ·×cµÈÛp'·¨&ÚòïgžœwsÙUJôòsWlî„»õ‚Ýö泌ˆ%Ü�k™çÍ_ôÔ+p­eñ„û±®5Λ�螯,Í�°§yá*&zòù»TÞ„=õ‘•CtçãQ)áaW,v[Ñ�ݶ±†]‰2ÕE×íVa_<ËÑŸÕq1a_œž}DW«_LغºN¼D_n¯µW„­1®¡¢k«ƒbÂæµ–‹¾Öž6Ç0RtåÑv1a;³—Ña{Œé"zý¹ÊÆFÄæYIôŠL Cig=w{å|“+n/ÑÓÕAa�k˜è™?¹’Åê+�èÉr(ŒjމþÿX•Ã0Ïj¢ÿr? Ë#Ñß�U=Œ£–èON†qõŒè—¼ñ„qñXùE?kÏÍ\ÑO>†�ù,úþ\%ÃHW)Ñ×êÌ0Ò™%úʵ02×EÞü«%ŒŒÅ?¿ÏÏ a¨«âcõ C�¾k/ C�…9†š£Íó0´>Ï·04߆&*–04–¸Ãи†Öø&4 ­ù†Ö¯Í�0ÔÜ^{Gjv­5) 53Ú„¡¦ƒ•# õ•C”ad�}­î #ÍaÑ×£ÝÂHº‰¾¼RÆÆå™Fô�3a WE?�Õ9 tuýØMT—Þ‚D¿kÏ ãœ¥¢?&[aX^YEW7…aÎÑš3Î0*ÏÜ¢ÿWׇQl=1é%ÎÊ(z¶ö„0ˆñ¢§v@>†1æ£ÿþ¢çZ'L‰Ñš¢W«{³MôÒNWcˆD‘ZôÚt #ì.¢+9pFtÉïÌùŽÏ'³èšiNoŒi+ººöæp¸n]ön^‡£Í+ƒD×­üùNœ•_t‡1áØxh!º·fj8ÖÌÝt{-‡Â¡r{‰îú”áHy Ý7éó=h¾ù�A´C Ô˜p\bµ€h�U!‰á°$j%Ñ.Ó(ŽpTœ¦‘hí«'·ÓI´Óéމ1ýE{ͰpJ #E»u\8ÄŒíg|8™,zãÃÎ4Ñ{ÞîL½Ë5²1á­1ÎÑût@<á�ñè`Ñ;=»ÄÞ·«—è½´ˆ=¼)vÓVôn§NÂ[’¨ Dï×r5&¼¡þõYYt‚ȯ°=!>‹ŠÎ°³æuØlÞ{d�╲¹¶rß�4¢s쀵…�œð$:É7ïÕÅakÜÞ¢ÃWØ7cDçiãć I4-E'Ú¥n'Ì”�édî<7Í ;«èT�àåp¸Å¯¤¢sÝ^ÎìÆ„Ë1,r{‹Ž6c c¥³ètS&¿Ã¥b•�ï™¡Þ œ{VFÑoþkÖ…—f«ÿþ¢!®^±…§±›A¢9Z.¿Ã“âª(šdÒ×Sá?NÚéDÃ\U�íÍçÆ^ùb¶9UDodtkgui-6.7.46/examples/animation-dci/main.cpp000066400000000000000000000120361522615413000210700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DGUI_USE_NAMESPACE static QString iconModeToString(DDciIcon::Mode mode) { switch (mode) { case DDciIcon::Normal: return "Normal"; case DDciIcon::Hover: return "Hover"; case DDciIcon::Pressed: return "Pressed"; case DDciIcon::Disabled: return "Disabled"; default: break; } return nullptr; } class IconWidget : public QMainWindow { public: IconWidget(const QString &iconName) { setCentralWidget(label = new QLabel(this)); label->setAcceptDrops(true); centralWidget()->setAttribute(Qt::WA_MouseTracking); centralWidget()->installEventFilter(this); statusBar()->addWidget(message = new QLabel()); auto normal = new QPushButton("Normal"); connect(normal, &QPushButton::clicked, this, [this] { player.setMode(DDciIcon::Normal); }); auto hover = new QPushButton("Hover"); connect(hover, &QPushButton::clicked, this, [this] { player.setMode(DDciIcon::Hover); }); auto pressed = new QPushButton("Pressed"); connect(pressed, &QPushButton::clicked, this, [this] { player.setMode(DDciIcon::Pressed); }); auto disabled = new QPushButton("Disabled"); connect(disabled, &QPushButton::clicked, this, [this] { player.setMode(DDciIcon::Disabled); }); auto open = new QPushButton("..."); connect(open, &QPushButton::clicked, this, [this] { QString dciFile = QFileDialog::getOpenFileName(this, "select a dci icon file", "", "*.dci"); player.setIcon(DDciIcon(dciFile)); player.setMode(DDciIcon::Normal); }); QWidget *menuWidget = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(menuWidget); layout->addWidget(normal); layout->addWidget(hover); layout->addWidget(pressed); layout->addWidget(disabled); layout->addWidget(open); setMenuWidget(menuWidget); icon = DDciIcon::fromTheme(iconName); connect(&player, &DDciIconPlayer::updated, this, [this] { auto image = player.currentImage(); label->setPixmap(QPixmap::fromImage(image)); }); connect(&player, &DDciIconPlayer::modeChanged, this, [this] (DDciIcon::Mode old, DDciIcon::Mode newMode) { message->setText(QString("Old State: %1, Current State: %2") .arg(iconModeToString(old)) .arg(iconModeToString(newMode))); }); DDciIconPalette p("pink"); player.setPalette(p); player.setDevicePixelRatio(devicePixelRatioF()); player.setIcon(icon); } private: bool event(QEvent *event) override { if (event->type() == QEvent::WindowActivate) { player.play(DDciIcon::Normal); } return QMainWindow::event(event); } bool eventFilter(QObject *watched, QEvent *event) { if (watched != label) return QMainWindow::eventFilter(watched, event); if (event->type() == QEvent::Enter) { player.setMode(DDciIcon::Hover); } else if (event->type() == QEvent::Leave) { if (player.mode() == DDciIcon::Hover) player.setMode(DDciIcon::Normal); } else if (event->type() == QEvent::MouseButtonPress) { player.setMode(DDciIcon::Pressed); } else if (event->type() == QEvent::MouseButtonRelease) { player.setMode(label->hasMouseTracking() ? DDciIcon::Hover : DDciIcon::Normal); } else if (event->type() == QEvent::DragEnter) { event->accept(); } else if (event->type() == QEvent::Drop) { auto de = static_cast(event); if (de->mimeData()->hasFormat("text/uri-list")) { QString uris = de->mimeData()->data("text/uri-list"); QUrl url(uris.split("\r\n").value(0)); DDciIcon icon(url.path()); if (!icon.isNull()) { player.setIcon(icon); player.setMode(DDciIcon::Normal); } } } else { return false; } return true; } DDciIcon icon; DDciIconPlayer player; QLabel *message = nullptr; QLabel *label = nullptr; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); IconWidget *window = new IconWidget(QStringLiteral("test_heart")); window->setMinimumSize(300, 300); window->show(); return app.exec(); } dtkgui-6.7.46/examples/animation-dci/test_dci_icon.qrc000066400000000000000000000003341522615413000227530ustar00rootroot00000000000000 dci_heart.dci 3depict.dci dtkgui-6.7.46/examples/dnd-example/000077500000000000000000000000001522615413000171205ustar00rootroot00000000000000dtkgui-6.7.46/examples/dnd-example/CMakeLists.txt000066400000000000000000000014571522615413000216670ustar00rootroot00000000000000find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) set(BIN1 dnd-test-client) set(BIN2 dnd-test-server) set(TARGET1 ${BIN1}${DTK_VERSION_MAJOR}) set(TARGET2 ${BIN2}${DTK_VERSION_MAJOR}) add_executable(${TARGET1} dnd-test-client.cpp ) target_link_libraries(${TARGET1} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::DBus ${LIB_NAME} ) add_executable(${TARGET2} dnd-test-server.cpp ) target_link_libraries(${TARGET2} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::DBus ${LIB_NAME} ) set_target_properties(${TARGET1} PROPERTIES OUTPUT_NAME ${BIN1}) set_target_properties(${TARGET2} PROPERTIES OUTPUT_NAME ${BIN2}) install(TARGETS ${TARGET1} DESTINATION "${TOOL_INSTALL_DIR}") install(TARGETS ${TARGET2} DESTINATION "${TOOL_INSTALL_DIR}") dtkgui-6.7.46/examples/dnd-example/dnd-test-client.cpp000066400000000000000000000050471522615413000226300ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dfiledragclient.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include DGUI_USE_NAMESPACE static DFileDragClient *c; static QProgressBar *p; class DropArea : public QFrame { Q_OBJECT public: explicit DropArea(QString s) : lb(new QLabel(s, this)) , le(new QLineEdit(this)) { setLayout(new QVBoxLayout); setFrameShape(Shape::Box); layout()->addWidget(lb); layout()->addWidget(le); lb->setAlignment(Qt::AlignmentFlag::AlignCenter); le->setText("/tmp"); le->setPlaceholderText(QString("do not accept drop when edit is empty")); setAcceptDrops(true); } protected: void dragEnterEvent(QDragEnterEvent *e) { if (DFileDragClient::checkMimeData(e->mimeData())) { if (le->text().isEmpty()) e->ignore(); // or e->setDropAction(Qt::IgnoreAction); else e->acceptProposedAction(); DFileDragClient::setTargetUrl(e->mimeData(), QUrl(le->text())); } } void dragMoveEvent(QDragMoveEvent *e) { if (DFileDragClient::checkMimeData(e->mimeData())) { e->acceptProposedAction(); DFileDragClient::setTargetUrl(e->mimeData(), QUrl(le->text())); } } void dropEvent(QDropEvent *e) { if (DFileDragClient::checkMimeData(e->mimeData())) { e->acceptProposedAction(); DFileDragClient::setTargetUrl(e->mimeData(), QUrl(le->text())); c = new DFileDragClient(e->mimeData()); connect(c, &DFileDragClient::progressChanged, p, &QProgressBar::setValue); } } private: QLabel *lb; QLineEdit *le; }; int main(int argc, char **argv) { QApplication a(argc, argv); QDialog d; d.show(); QHBoxLayout *lo = new QHBoxLayout(); lo->addWidget(new DropArea("area 51")); lo->addWidget(new DropArea("area 61")); QScopedPointer pp (new QProgressBar()); p = pp.data(); p->setMinimum(0); p->setMaximum(100); QVBoxLayout *hlo = new QVBoxLayout(); d.setLayout(hlo); hlo->addLayout(lo); hlo->addWidget(p); a.exec(); } #include "dnd-test-client.moc" dtkgui-6.7.46/examples/dnd-example/dnd-test-server.cpp000066400000000000000000000050621522615413000226550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dfiledragserver.h" #include "dfiledrag.h" #include #include #include #include #include #include #include #include #include #include DGUI_USE_NAMESPACE static int p; static DFileDragServer *s = nullptr; static QLabel *lbr = nullptr; class DraggableLabel : public QLabel { Q_OBJECT public: using QLabel::QLabel; Q_SIGNALS: void dragFinished(); protected: void mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::MouseButton::LeftButton) { dragpos = e->pos(); } } void mouseMoveEvent(QMouseEvent *e) { if (!(e->buttons() & Qt::MouseButton::LeftButton) || s) { return; } if ((e->pos() - dragpos).manhattanLength() < QApplication::startDragDistance()) { return; } s = new DFileDragServer(); DFileDrag *drag = new DFileDrag(this, s); QMimeData *m = new QMimeData(); m->setText("your stuff here"); drag->setMimeData(m); connect(drag, &DFileDrag::targetUrlChanged, [drag] { lbr->setText(drag->targetUrl().toString()); }); Qt::DropAction res = drag->exec(Qt::MoveAction); if (res!= Qt::IgnoreAction) Q_EMIT dragFinished(); else { s->deleteLater(); s = nullptr; } } private: QPoint dragpos; }; int main(int argc, char **argv) { QApplication a(argc, argv); QDialog d; d.show(); DraggableLabel l("Drag me", &d); l.setAlignment(Qt::AlignCenter); QTimer t; t.setInterval(50); t.setSingleShot(false); QProgressBar pg; pg.setMinimum(0); pg.setMaximum(100); QLabel lb; lbr = &lb; lb.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QObject::connect(&l, &DraggableLabel::dragFinished, [&t] { p = -1; t.start(); }); QObject::connect(&t, &QTimer::timeout, [&t, &pg] { if (QRandomGenerator::global()->generate() & 1) { s->setProgress(++p); pg.setValue(p); if(p == 100) { t.stop(); s->deleteLater(); s = nullptr; } } }); QVBoxLayout lo; lo.addWidget(&l); lo.addWidget(&pg); lo.addWidget(&lb); d.setLayout(&lo); a.exec(); } #include "dnd-test-server.moc" dtkgui-6.7.46/examples/frameless-window/000077500000000000000000000000001522615413000202105ustar00rootroot00000000000000dtkgui-6.7.46/examples/frameless-window/CMakeLists.txt000066400000000000000000000005421522615413000227510ustar00rootroot00000000000000find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS X11Extras) pkg_check_modules(XCB IMPORTED_TARGET xcb) set(BIN_NAME frameless-window) add_executable(${BIN_NAME} main.cpp ) target_link_libraries(${BIN_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::GuiPrivate Qt${QT_VERSION_MAJOR}::X11Extras PkgConfig::XCB ) dtkgui-6.7.46/examples/frameless-window/main.cpp000066400000000000000000000121701522615413000216410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include void setWindowProperty(quint32 WId, xcb_atom_t propAtom, xcb_atom_t typeAtom, const void *data, quint32 len, uint8_t format) { xcb_connection_t* conn = QX11Info::connection(); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, WId, propAtom, typeAtom, format, len, data); xcb_flush(conn); } void clearWindowProperty(quint32 WId, xcb_atom_t propAtom) { xcb_delete_property_checked(QX11Info::connection(), WId, propAtom); } xcb_atom_t internAtom(xcb_connection_t *connection, const char *name, bool only_if_exists) { if (!name || *name == 0) return XCB_NONE; xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, only_if_exists, strlen(name), name); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookie, 0); if (!reply) return XCB_NONE; xcb_atom_t atom = reply->atom; free(reply); return atom; } xcb_atom_t internAtom(const char *name, bool only_if_exists) { return internAtom(QX11Info::connection(), name, only_if_exists); } bool isSupported(xcb_atom_t targetAtom) { // get _NET_SUPPORTED from root window QVector net_wm_atoms; xcb_window_t root = QX11Info::appRootWindow(); int offset = 0; int remaining = 0; xcb_connection_t *xcb_connection = QX11Info::connection(); auto _net_supported = internAtom(QT_STRINGIFY(_NET_SUPPORTED), false); do { xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection, false, root, _net_supported, XCB_ATOM_ATOM, offset, 1024); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection, cookie, NULL); if (!reply) break; remaining = 0; if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); int s = net_wm_atoms.size(); net_wm_atoms.resize(s + len); memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t)); remaining = reply->bytes_after; offset += len; } free(reply); } while (remaining > 0); return net_wm_atoms.contains(targetAtom); } bool setNoTitlebar(quint32 WId, bool on) { xcb_atom_t _deepin_no_titlebar = internAtom(QT_STRINGIFY(_DEEPIN_NO_TITLEBAR), false); if (!isSupported(_deepin_no_titlebar)) return false; quint8 value = on; setWindowProperty(WId, _deepin_no_titlebar, XCB_ATOM_CARDINAL, &value, 1, 8); // force enable window decorations, becouse we need the window shadow and border, its contains in decorations. xcb_atom_t _deepin_force_decorate = internAtom(QT_STRINGIFY(_DEEPIN_FORCE_DECORATE), false); if (on) { quint8 value = on; setWindowProperty(WId, _deepin_force_decorate, XCB_ATOM_CARDINAL, &value, 1, 8); } else { clearWindowProperty(WId, _deepin_force_decorate); } return true; } QObject *createNativeSettingsFor(QWindow *window) { // The platform function in dxcb plugin: // https://github.com/linuxdeepin/qt5platform-plugins/blob/master/src/dnativesettings.h static QFunctionPointer build_function = qApp->platformFunction("_d_buildNativeSettings"); if (!build_function) { return nullptr; } QObject *obj = new QObject(window); bool ok = reinterpret_cast(build_function)(obj, window->winId()); if (!ok) { delete obj; return nullptr; } return obj; } class Window : public QWindow { public: bool handleMoveing = false; private: void mouseMoveEvent(QMouseEvent *e) override { if (handleMoveing && e->buttons() == Qt::LeftButton) { handle()->startSystemMove(); } else { QWindow::mouseMoveEvent(e); } } }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); Window window; window.resize(200, 200); if (setNoTitlebar(window.winId(), true)) { // If enabled no titlebar mode, the window is no min/max/close buttons, you need to implement it by Qt widgets. // Like as https://github.com/linuxdeepin/dtkwidget/blob/master/src/widgets/dtitlebar.cpp window.handleMoveing = true; auto nativeSettings = createNativeSettingsFor(&window); if (nativeSettings) { nativeSettings->setProperty("DTK/WindowRadius", "100,100"); nativeSettings->setProperty("borderWidth", 2); nativeSettings->setProperty("borderColor", QColor(Qt::red)); nativeSettings->setProperty("shadowOffset", "30,30"); nativeSettings->setProperty("shadowRadius", 30); nativeSettings->setProperty("shadowColor", QColor(Qt::blue)); // See more properties in DPlatformTheme } } window.show(); return app.exec(); } dtkgui-6.7.46/examples/test-taskbar/000077500000000000000000000000001522615413000173265ustar00rootroot00000000000000dtkgui-6.7.46/examples/test-taskbar/CMakeLists.txt000066400000000000000000000006451522615413000220730ustar00rootroot00000000000000find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) set(BIN taskbar) set(TARGET_NAME ${BIN}${DTK_VERSION_MAJOR}) add_executable(${TARGET_NAME} testtaskbarwindow.h testtaskbarwindow.cpp main.cpp ) target_link_libraries(${TARGET_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Gui ${LIB_NAME} ) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN}) dtkgui-6.7.46/examples/test-taskbar/main.cpp000066400000000000000000000030401522615413000207530ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include "testtaskbarwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); auto name = QUuid::createUuid().toString() + QStringLiteral(".desktop"); a.setDesktopFileName(name); QDir appDir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); QFile desktopFile(appDir.absoluteFilePath(name)); if(!desktopFile.exists()) { desktopFile.open(QIODevice::WriteOnly); desktopFile.write("[Desktop Entry]\n"); desktopFile.write("Type=Application\n"); desktopFile.write("Version=1.1\n"); desktopFile.write("Name=" + QApplication::applicationDisplayName().toUtf8() + "\n"); desktopFile.write("Exec=" + QApplication::applicationFilePath().toUtf8() + "\n"); desktopFile.close(); } TestTaskbarWindow *pTaskbarWindow = new TestTaskbarWindow; pTaskbarWindow->showMaximized(); //这里删除用于测试的desktop文件 QObject::connect(pTaskbarWindow, &TestTaskbarWindow::closeWindow, [&desktopFile] { QFile::remove(desktopFile.fileName()); }); //控制中心修改字体大å°�å�¯ä»¥çœ‹åˆ°æ‰“å�°è¾“出 QObject::connect(DGuiApplicationHelper::instance()->fontManager(), &DFontManager::fontChanged, [] { qDebug() << DGuiApplicationHelper::instance()->fontManager()->baseFont(); }); return a.exec(); } dtkgui-6.7.46/examples/test-taskbar/testtaskbarwindow.cpp000066400000000000000000000050361522615413000236150ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "testtaskbarwindow.h" #include #include #include TestTaskbarWindow::TestTaskbarWindow(QWidget *parent) : QWidget(parent) { QHBoxLayout *pHBoxLayout_1 = new QHBoxLayout; m_pProgressBox = new QCheckBox("progress"); m_pProgress = new QSlider(Qt::Horizontal); m_pProgress->setRange(0, 100); m_pProgress->setMinimumWidth(300); pHBoxLayout_1->addWidget(m_pProgressBox); pHBoxLayout_1->addWidget(m_pProgress); QHBoxLayout *pHBoxLayout_2 = new QHBoxLayout; m_pCounterBox = new QCheckBox("counter"); m_pNumEdit = new QLineEdit; m_pNumEdit->setMinimumWidth(300); m_pNumEdit->setValidator(new QIntValidator); pHBoxLayout_2->addWidget(m_pCounterBox); pHBoxLayout_2->addWidget(m_pNumEdit); m_pUrgencyBox= new QCheckBox("test urgency"); QHBoxLayout *pHBoxLayout_3 = new QHBoxLayout; pHBoxLayout_3->addWidget(m_pUrgencyBox); QVBoxLayout *pVBoxLayout = new QVBoxLayout; setLayout(pVBoxLayout); pVBoxLayout->addStretch(); pVBoxLayout->addLayout(pHBoxLayout_1); pVBoxLayout->addSpacing(30); pVBoxLayout->addLayout(pHBoxLayout_2); pVBoxLayout->addSpacing(50); pVBoxLayout->addLayout(pHBoxLayout_3); pVBoxLayout->addStretch(); m_pTaskbarControl = new DTaskbarControl(this); m_pTaskbarControl->setProgress(false, 0); m_pTaskbarControl->setCounter(false, 0); connect(m_pProgressBox, &QCheckBox::stateChanged, this, [this] (int state) { m_pTaskbarControl->setProgress(state == Qt::Checked, static_cast(m_pProgress->value()) / 100); }); connect(m_pCounterBox, &QCheckBox::stateChanged, this, [this] (int state) { m_pTaskbarControl->setCounterVisible(state == Qt::Checked); }); connect(m_pProgress, &QSlider::valueChanged, this, [this] (int value) { m_pTaskbarControl->setProgress(m_pProgressBox->checkState() == Qt::Checked, static_cast(value) / 100); }); connect(m_pNumEdit, &QLineEdit::textChanged, [this] (const QString &str) { m_pTaskbarControl->setCounter(m_pCounterBox->checkState() == Qt::Checked, str.toInt()); }); connect(m_pUrgencyBox, &QCheckBox::stateChanged, this, [this] (int state) { m_pTaskbarControl->setUrgency(state == Qt::Checked); }); } TestTaskbarWindow::~TestTaskbarWindow() { } void TestTaskbarWindow::closeEvent(QCloseEvent *event) { Q_EMIT closeWindow(); event->accept(); } dtkgui-6.7.46/examples/test-taskbar/testtaskbarwindow.h000066400000000000000000000017051522615413000232610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef TESTTASKBARWINDOW_H #define TESTTASKBARWINDOW_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dtaskbarcontrol.h" DGUI_USE_NAMESPACE class TestTaskbarWindow : public QWidget { Q_OBJECT public: explicit TestTaskbarWindow(QWidget *parent = nullptr); ~TestTaskbarWindow(); protected: void closeEvent(QCloseEvent *event); Q_SIGNALS: void closeWindow(); private: DTaskbarControl *m_pTaskbarControl; QCheckBox *m_pProgressBox; QCheckBox *m_pCounterBox; QLineEdit *m_pNumEdit; QSlider *m_pProgress; QCheckBox *m_pUrgencyBox; }; #endif // TESTTASKBARWINDOW_H dtkgui-6.7.46/include/000077500000000000000000000000001522615413000145275ustar00rootroot00000000000000dtkgui-6.7.46/include/DtkGui/000077500000000000000000000000001522615413000157165ustar00rootroot00000000000000dtkgui-6.7.46/include/DtkGui/DDciIcon000066400000000000000000000000261522615413000172530ustar00rootroot00000000000000#include "ddciicon.h" dtkgui-6.7.46/include/DtkGui/DDciIconImagePlayer000066400000000000000000000000341522615413000213720ustar00rootroot00000000000000#include "ddciiconplayer.h" dtkgui-6.7.46/include/DtkGui/DDciIconPalette000066400000000000000000000000351522615413000205720ustar00rootroot00000000000000#include "ddciiconpalette.h" dtkgui-6.7.46/include/DtkGui/DDciIconPlayer000066400000000000000000000000341522615413000204270ustar00rootroot00000000000000#include "ddciiconplayer.h" dtkgui-6.7.46/include/DtkGui/DDesktopServices000066400000000000000000000000361522615413000210610ustar00rootroot00000000000000#include "ddesktopservices.h" dtkgui-6.7.46/include/DtkGui/DFileDrag000066400000000000000000000000271522615413000174210ustar00rootroot00000000000000#include "dfiledrag.h" dtkgui-6.7.46/include/DtkGui/DFileDragClient000066400000000000000000000000351522615413000205570ustar00rootroot00000000000000#include "dfiledragclient.h" dtkgui-6.7.46/include/DtkGui/DFileDragServer000066400000000000000000000000351522615413000206070ustar00rootroot00000000000000#include "dfiledragserver.h" dtkgui-6.7.46/include/DtkGui/DFontManager000066400000000000000000000000321522615413000201410ustar00rootroot00000000000000#include "dfontmanager.h" dtkgui-6.7.46/include/DtkGui/DForeignWindow000066400000000000000000000000341522615413000205230ustar00rootroot00000000000000#include "dforeignwindow.h" dtkgui-6.7.46/include/DtkGui/DGuiApplicationHelper000066400000000000000000000000431522615413000220120ustar00rootroot00000000000000#include "dguiapplicationhelper.h" dtkgui-6.7.46/include/DtkGui/DIcon000066400000000000000000000000231522615413000166300ustar00rootroot00000000000000#include "dicon.h" dtkgui-6.7.46/include/DtkGui/DIconTheme000066400000000000000000000000301522615413000176110ustar00rootroot00000000000000#include "dicontheme.h" dtkgui-6.7.46/include/DtkGui/DImageHandler000066400000000000000000000000331522615413000202610ustar00rootroot00000000000000#include "dimagehandler.h" dtkgui-6.7.46/include/DtkGui/DNativeSettings000066400000000000000000000000351522615413000207120ustar00rootroot00000000000000#include "dnativesettings.h" dtkgui-6.7.46/include/DtkGui/DPalette000066400000000000000000000000261522615413000173410ustar00rootroot00000000000000#include "dpalette.h" dtkgui-6.7.46/include/DtkGui/DPlatformHandle000066400000000000000000000000351522615413000206430ustar00rootroot00000000000000#include "dplatformhandle.h" dtkgui-6.7.46/include/DtkGui/DPlatformTheme000066400000000000000000000000341522615413000205110ustar00rootroot00000000000000#include "dplatformtheme.h" dtkgui-6.7.46/include/DtkGui/DRegionMonitor000066400000000000000000000000341522615413000205350ustar00rootroot00000000000000#include "dregionmonitor.h" dtkgui-6.7.46/include/DtkGui/DSvgRenderer000066400000000000000000000000321522615413000201660ustar00rootroot00000000000000#include "dsvgrenderer.h" dtkgui-6.7.46/include/DtkGui/DTaskbarControl000066400000000000000000000000351522615413000206730ustar00rootroot00000000000000#include "dtaskbarcontrol.h" dtkgui-6.7.46/include/DtkGui/DThumbnailProvider000066400000000000000000000000401522615413000213750ustar00rootroot00000000000000#include "dthumbnailprovider.h" dtkgui-6.7.46/include/DtkGui/DWindowGroupLeader000066400000000000000000000000401522615413000213400ustar00rootroot00000000000000#include "dwindowgroupleader.h" dtkgui-6.7.46/include/DtkGui/DWindowManagerHelper000066400000000000000000000000421522615413000216430ustar00rootroot00000000000000#include "dwindowmanagerhelper.h" dtkgui-6.7.46/include/filedrag/000077500000000000000000000000001522615413000163045ustar00rootroot00000000000000dtkgui-6.7.46/include/filedrag/dfiledrag.h000066400000000000000000000012341522615413000203760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILEDRAG_H #define DFILEDRAG_H #include #include #include #include DGUI_BEGIN_NAMESPACE class DFileDragServer; class DFileDragPrivate; class DFileDrag : public QDrag, public DCORE_NAMESPACE::DObject { Q_OBJECT public: explicit DFileDrag(QObject *source, DFileDragServer *server); QUrl targetUrl(); void setMimeData(QMimeData *data); Q_SIGNALS: void targetUrlChanged(QUrl url); private: D_DECLARE_PRIVATE(DFileDrag) }; DGUI_END_NAMESPACE #endif // DFILEDRAG_H dtkgui-6.7.46/include/filedrag/dfiledragclient.h000066400000000000000000000017641522615413000216050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILEDRAGCLIENT_H #define DFILEDRAGCLIENT_H #include "dfiledragcommon.h" #include #include #include class QMimeData; DGUI_BEGIN_NAMESPACE class DFileDragClientPrivate; class DFileDragClient : public QObject, public DCORE_NAMESPACE::DObject { Q_OBJECT public: explicit DFileDragClient(const QMimeData *data, QObject *parent = nullptr); int progress() const; DFileDragState state() const; Q_SIGNALS: void progressChanged(int progress); void stateChanged(DFileDragState state); void serverDestroyed(); public: static bool checkMimeData(const QMimeData *data); static void setTargetData(const QMimeData *data, QString key, QVariant value); static void setTargetUrl(const QMimeData *data, QUrl url); private: D_DECLARE_PRIVATE(DFileDragClient) }; DGUI_END_NAMESPACE #endif // DFILEDRAGCLIENT_H dtkgui-6.7.46/include/filedrag/dfiledragcommon.h000066400000000000000000000006101522615413000216040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILEDRAGCOMMON_H #define DFILEDRAGCOMMON_H #include DGUI_BEGIN_NAMESPACE enum DFileDragState { Failed = -1, Stalled, Paused, Running, Finished, CustomState = 0x100 }; DGUI_END_NAMESPACE #endif // DFILEDRAGCOMMON_H dtkgui-6.7.46/include/filedrag/dfiledragserver.h000066400000000000000000000015731522615413000216330ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILEDRAGSERVER_H #define DFILEDRAGSERVER_H #include "dfiledragcommon.h" #include #include #include class QMimeData; DGUI_BEGIN_NAMESPACE class DFileDragServerPrivate; class DFileDragServer : public QObject, public DCORE_NAMESPACE::DObject { Q_OBJECT public: explicit DFileDragServer(QObject *parent = nullptr); ~DFileDragServer(); QVariant targetData(const QString &key) const; public Q_SLOTS: void setProgress(int progress); void setState(DFileDragState state); Q_SIGNALS: void targetDataChanged(const QString &key); private: D_DECLARE_PRIVATE(DFileDragServer) friend class DDndSourceInterface; friend class DFileDrag; }; DGUI_END_NAMESPACE #endif // DFILEDRAGSERVER_H dtkgui-6.7.46/include/global/000077500000000000000000000000001522615413000157675ustar00rootroot00000000000000dtkgui-6.7.46/include/global/dtkgui_global.h000066400000000000000000000007501522615413000207510ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTKGUI_GLOBAL_H #define DTKGUI_GLOBAL_H #pragma once #include #define DGUI_NAMESPACE Gui #define DTK_GUI_NAMESPACE DTK_NAMESPACE::Gui #define DGUI_BEGIN_NAMESPACE namespace DTK_NAMESPACE { namespace DGUI_NAMESPACE { #define DGUI_END_NAMESPACE }} #define DGUI_USE_NAMESPACE using namespace DTK_GUI_NAMESPACE; #endif // DTKGUI_GLOBAL_H dtkgui-6.7.46/include/kernel/000077500000000000000000000000001522615413000160075ustar00rootroot00000000000000dtkgui-6.7.46/include/kernel/dforeignwindow.h000066400000000000000000000015561522615413000212140ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFOREIGNWINDOW_H #define DFOREIGNWINDOW_H #include #include #include DGUI_BEGIN_NAMESPACE class DForeignWindowPrivate; class DForeignWindow : public QWindow, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT Q_PROPERTY(QString wmClass READ wmClass NOTIFY wmClassChanged) Q_PROPERTY(quint32 pid READ pid NOTIFY pidChanged) public: explicit DForeignWindow(QWindow *parent = 0); static DForeignWindow *fromWinId(WId id); QString wmClass() const; quint32 pid() const; Q_SIGNALS: void wmClassChanged(); void pidChanged(); protected: bool event(QEvent *) Q_DECL_OVERRIDE; private: D_DECLARE_PRIVATE(DForeignWindow) }; DGUI_END_NAMESPACE #endif // DFOREIGNWINDOW_H dtkgui-6.7.46/include/kernel/dguiapplicationhelper.h000066400000000000000000000145021522615413000225360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DGUIAPPLICATIONHELPER_H #define DGUIAPPLICATIONHELPER_H #include #include #include #include #include DGUI_BEGIN_NAMESPACE class DPlatformTheme; class DFontManager; class DGuiApplicationHelperPrivate; class DGuiApplicationHelper : public QObject, public DCORE_NAMESPACE::DObject { Q_OBJECT D_DECLARE_PRIVATE(DGuiApplicationHelper) Q_PROPERTY(ColorType themeType READ themeType NOTIFY themeTypeChanged) Q_PROPERTY(ColorType paletteType READ paletteType WRITE setPaletteType NOTIFY paletteTypeChanged) Q_PROPERTY(bool hasUserManual READ hasUserManual) public: enum ColorType { UnknownType, LightType, DarkType }; Q_ENUM(ColorType) enum SingleScope { UserScope, GroupScope, WorldScope }; Q_ENUM(SingleScope) enum SizeMode { NormalMode, CompactMode }; Q_ENUM(SizeMode) enum Attribute { UseInactiveColorGroup = 1 << 0, ColorCompositing = 1 << 1, DontSaveApplicationTheme = 1 << 2, /* readonly flag */ ReadOnlyLimit = 1 << 22, IsDeepinPlatformTheme = ReadOnlyLimit << 0, IsDXcbPlatform = ReadOnlyLimit << 1, IsXWindowPlatform = ReadOnlyLimit << 2, IsTableEnvironment = ReadOnlyLimit << 3, IsDeepinEnvironment = ReadOnlyLimit << 4, IsSpecialEffectsEnvironment = ReadOnlyLimit << 5, IsWaylandPlatform = ReadOnlyLimit << 6, IsTreelandPlatform Q_DECL_ENUMERATOR_DEPRECATED_X("Use DGuiApplicationHelper::IsWaylandPlatform instead") = IsWaylandPlatform, HasAnimations = ReadOnlyLimit << 7, HasInWindowBlur = ReadOnlyLimit << 8, }; Q_ENUM(Attribute) Q_DECLARE_FLAGS(Attributes, Attribute) #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) typedef DGuiApplicationHelper *(*HelperCreator)(); D_DECL_DEPRECATED static void registerInstanceCreator(HelperCreator creator); #endif static DGuiApplicationHelper *instance(); ~DGuiApplicationHelper(); static QColor adjustColor(const QColor &base, qint8 hueFloat, qint8 saturationFloat, qint8 lightnessFloat, qint8 redFloat, qint8 greenFloat, qint8 blueFloat, qint8 alphaFloat); static QImage adjustColor(const QImage &base, qint8 hueFloat, qint8 saturationFloat, qint8 lightnessFloat, qint8 redFloat, qint8 greenFloat, qint8 blueFloat, qint8 alphaFloat); static QColor blendColor(const QColor &substrate, const QColor &superstratum); static DPalette standardPalette(ColorType type); static void generatePaletteColor(DPalette &base, QPalette::ColorRole role, ColorType type); static void generatePaletteColor(DPalette &base, DPalette::ColorType role, ColorType type); static void generatePalette(DPalette &base, ColorType type = UnknownType); static DPalette fetchPalette(const DPlatformTheme *theme); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) Q_DECL_DEPRECATED_X("Use UseInactiveColorGroup enum with setAttribute.") static void setUseInactiveColorGroup(bool on); Q_DECL_DEPRECATED_X("Use ColorCompositing enum with setAttribute.") static void setColorCompositingEnabled(bool on); #endif static bool isXWindowPlatform(); static bool isTabletEnvironment(); static bool isSpecialEffectsEnvironment(); static void setAttribute(Attribute attribute, bool enable); static bool testAttribute(Attribute attribute); DPlatformTheme *systemTheme() const; DPlatformTheme *applicationTheme() const; #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED DPlatformTheme *windowTheme(QWindow *window) const; #endif DPalette applicationPalette() const; DPalette applicationPalette(ColorType paletteType) const; void setApplicationPalette(const DPalette &palette); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED DPalette windowPalette(QWindow *window) const; #endif const DFontManager *fontManager() const; static ColorType toColorType(const QColor &color); static ColorType toColorType(const QPalette &palette); ColorType themeType() const; ColorType paletteType() const; static bool setSingleInstance(const QString &key, SingleScope singleScope = UserScope); static void setSingleInstanceInterval(int interval = 3000); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED static void setSingelInstanceInterval(int interval = 3000); #endif // 获å�–帮助手册目录 static QStringList userManualPaths(const QString &appName); bool hasUserManual() const; static bool loadTranslator(const QString &fileName, const QString &appName, const QList &localeFallback = QList() << QLocale::system()); static bool loadTranslator(const QString &fileName, const QList &translateDirs, const QList &localeFallback); static bool loadTranslator(const QList &localeFallback = QList() << QLocale::system()); public Q_SLOTS: #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED_X("Plase use setPaletteType") void setThemeType(ColorType themeType); #endif void setPaletteType(ColorType paletteType); void handleHelpAction(); static void openUrl(const QString &url); DGuiApplicationHelper::SizeMode sizeMode() const; void setSizeMode(const DGuiApplicationHelper::SizeMode mode); void resetSizeMode(); static inline bool isCompactMode() { return instance()->sizeMode() == DGuiApplicationHelper::CompactMode; } Q_SIGNALS: void themeTypeChanged(ColorType themeType); void paletteTypeChanged(ColorType paletteType); void newProcessInstance(qint64 pid, const QStringList &arguments); void fontChanged(const QFont &font); void applicationPaletteChanged(); void sizeModeChanged(DGuiApplicationHelper::SizeMode sizeMode); protected: explicit DGuiApplicationHelper(); virtual void initialize(); private: D_PRIVATE_SLOT(void _q_initApplicationTheme(bool)) D_PRIVATE_SLOT(void _q_sizeModeChanged(int)) friend class _DGuiApplicationHelper; }; DGUI_END_NAMESPACE #endif // DGUIAPPLICATIONHELPER_H dtkgui-6.7.46/include/kernel/dnativesettings.h000066400000000000000000000027461522615413000214040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DNATIVESETTINGS_H #define DNATIVESETTINGS_H #include #include #include DGUI_BEGIN_NAMESPACE class DNativeSettingsPrivate; class DNativeSettings : public QObject, public DCORE_NAMESPACE::DObject { Q_OBJECT D_DECLARE_PRIVATE(DNativeSettings) Q_PROPERTY(QByteArrayList allKeys READ allKeys WRITE __setAllKeys NOTIFY allKeysChanged) public: explicit DNativeSettings(quint32 window, const QByteArray &domain = QByteArray(), QObject *parent = nullptr); bool isValid() const; QByteArrayList allKeys() const; QVariant getSetting(const QByteArray &name) const; void setSetting(const QByteArray &name, const QVariant &value); Q_SIGNALS: void allKeysChanged(); void propertyChanged(const QByteArray &name, const QVariant &value); protected: DNativeSettings(DNativeSettingsPrivate &dd, const QMetaObject *metaObject, quint32 window, QObject *parent); DNativeSettings(const QMetaObject *metaObject, quint32 window, const QByteArray &domain, QObject *parent); bool init(const QMetaObject *metaObject, quint32 window); private: void __setAllKeys(const QByteArrayList &keys); friend class DNativeSettingsPrivate; }; DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE QDebug operator<<(QDebug debug, const DTK_GUI_NAMESPACE::DNativeSettings &settings); QT_END_NAMESPACE #endif // DNATIVESETTINGS_H dtkgui-6.7.46/include/kernel/dpalette.h000066400000000000000000000074541522615413000177740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPALETTE_H #define DPALETTE_H #include #include #include DGUI_BEGIN_NAMESPACE class DPalettePrivate; class DPalette : public QPalette { Q_GADGET public: enum ColorType { NoType, ItemBackground, //列表项的背景色 TextTitle, //标题型文本的颜色 TextTips, //æ��示性文本的颜色 TextWarning, //警告类型的文本颜色 TextLively, //活跃å¼�文本颜色(ä¸�å�—活动色影å“�) LightLively, //活跃å¼�按钮(recommend button)背景色中的亮色(ä¸�å�—活跃色影å“�) DarkLively, //活跃å¼�按钮(recommend button)背景色中的暗色,会从亮色æ¸�å�˜åˆ°æš—色(ä¸�å�—活跃色影å“�) FrameBorder, //控件边框颜色 PlaceholderText, //å� ä½�类型的文本颜色,å�¯ç”¨äºŽè¾“入框å� ä½�内容等æ��示性文字 FrameShadowBorder, //用于跟阴影å� åŠ çš„è¾¹æ¡†é¢œè‰² ObviousBackground, //明显的背景色 NColorTypes }; Q_ENUM(ColorType) DPalette(); DPalette(const QPalette &palette); DPalette(const DPalette &palette); ~DPalette(); DPalette &operator=(const DPalette &palette); inline const QColor &color(ColorGroup cg, ColorType ct) const { return brush(cg, ct).color(); } const QBrush &brush(ColorGroup cg, ColorType ct) const; inline void setColor(ColorGroup cg, ColorType ct, const QColor &color) { setBrush(cg, ct, color); } inline void setColor(ColorType ct, const QColor &color) { setColor(All, ct, color); } inline void setBrush(ColorType ct, const QBrush &brush) { setBrush(All, ct, brush); } void setBrush(ColorGroup cg, ColorType ct, const QBrush &brush); inline const QColor &color(ColorType ct) const { return color(Current, ct); } inline const QBrush &brush(ColorType ct) const { return brush(Current, ct); } inline const QBrush &itemBackground() const { return brush(ItemBackground); } inline const QBrush &textTitle() const { return brush(TextTitle); } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) D_DECL_DEPRECATED inline const QBrush &textTiele() const { return textTitle();} #endif inline const QBrush &textTips() const { return brush(TextTips); } inline const QBrush &textWarning() const { return brush(TextWarning); } inline const QBrush &textLively() const { return brush(TextLively); } inline const QBrush &lightLively() const { return brush(LightLively); } inline const QBrush &darkLively() const { return brush(DarkLively); } inline const QBrush &frameBorder() const { return brush(FrameBorder); } inline const QBrush &placeholderText() const { return brush(PlaceholderText); } inline const QBrush &frameShadowBorder() const { return brush(FrameShadowBorder); } using QPalette::color; using QPalette::brush; using QPalette::setBrush; using QPalette::setColor; protected: QScopedPointer d; friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const DPalette &p); }; DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE /***************************************************************************** DPalette stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM Q_GUI_EXPORT QDataStream &operator<<(QDataStream &ds, const DTK_GUI_NAMESPACE::DPalette &p); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &ds, DTK_GUI_NAMESPACE::DPalette &p); #endif // QT_NO_DATASTREAM #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const DTK_GUI_NAMESPACE::DPalette &); #endif QT_END_NAMESPACE #endif // DPALETTE_H dtkgui-6.7.46/include/kernel/dplatformhandle.h000066400000000000000000000171001522615413000213230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMHANDLE_H #define DPLATFORMHANDLE_H #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QWindow; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE // TODO: class DPlatformHandle will be removed in the future class DPlatformHandle : public QObject { Q_OBJECT Q_PROPERTY(int windowRadius READ windowRadius WRITE setWindowRadius NOTIFY windowRadiusChanged) Q_PROPERTY(int borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged) Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged) Q_PROPERTY(int shadowRadius READ shadowRadius WRITE setShadowRadius NOTIFY shadowRadiusChanged) Q_PROPERTY(QPoint shadowOffset READ shadowOffset WRITE setShadowOffset NOTIFY shadowOffsetChanged) Q_PROPERTY(QColor shadowColor READ shadowColor WRITE setShadowColor NOTIFY shadowColorChanged) Q_PROPERTY(EffectScene windowEffect READ windowEffect WRITE setWindowEffect NOTIFY windowEffectChanged) Q_PROPERTY(EffectType windowStartUpEffect READ windowStartUpEffect WRITE setWindowStartUpEffect NOTIFY windowStartUpEffectChanged) Q_PROPERTY(QPainterPath clipPath READ clipPath WRITE setClipPath NOTIFY clipPathChanged) Q_PROPERTY(QRegion frameMask READ frameMask WRITE setFrameMask NOTIFY frameMaskChanged) Q_PROPERTY(QMargins frameMargins READ frameMargins NOTIFY frameMarginsChanged) Q_PROPERTY(bool translucentBackground READ translucentBackground WRITE setTranslucentBackground NOTIFY translucentBackgroundChanged) Q_PROPERTY(bool enableSystemResize READ enableSystemResize WRITE setEnableSystemResize NOTIFY enableSystemResizeChanged) Q_PROPERTY(bool enableSystemMove READ enableSystemMove WRITE setEnableSystemMove NOTIFY enableSystemMoveChanged) Q_PROPERTY(bool enableBlurWindow READ enableBlurWindow WRITE setEnableBlurWindow NOTIFY enableBlurWindowChanged) Q_PROPERTY(bool autoInputMaskByClipPath READ autoInputMaskByClipPath WRITE setAutoInputMaskByClipPath NOTIFY autoInputMaskByClipPathChanged) Q_PROPERTY(WId realWindowId READ realWindowId CONSTANT) public: explicit DPlatformHandle(QWindow *window, QObject *parent = 0); ~DPlatformHandle(); static QString pluginVersion(); static bool isDXcbPlatform(); static void enableDXcbForWindow(QWindow *window); static void enableDXcbForWindow(QWindow *window, bool redirectContent); static bool isEnabledDXcb(const QWindow *window); static bool setEnabledNoTitlebarForWindow(QWindow *window, bool enable); static bool isEnabledNoTitlebar(const QWindow *window); struct WMBlurArea { qint32 x = 0; qint32 y = 0; qint32 width = 0; qint32 height = 0; qint32 xRadius = 0; qint32 yRaduis = 0; }; enum WallpaperScaleMode { FollowScreen = 0x00000000, FollowWindow = 0x00010000 }; enum WallpaperFillMode { PreserveAspectCrop = 0x00000000, PreserveAspectFit = 0x00000001 }; enum EffectScene { EffectNoRadius = 0x01, // å�–消窗å�£åœ†è§’ EffectNoShadow = 0x02, // å�–消窗å�£é˜´å½± EffectNoBorder = 0x04, // å�–消窗å�£è¾¹æ¡† EffectNoStart = 0x10, // å�–消å�¯åŠ¨åœºæ™¯åŠ¨æ•ˆ EffectNoClose = 0x20, // å�–消关闭场景动效 EffectNoMaximize = 0x40, // å�–消最大化场景动效 EffectNoMinimize = 0x80 // å�–消最å°�化场景动效 }; enum EffectType { EffectNormal = 0x01, // 标准缩放动效 EffectCursor = 0x02, // é¼ æ ‡ä½�置展开动效 EffectTop = 0x04, // 从上往下展开 EffectBottom = 0x08, // 从下往上展开 EffectOut = 0x10 // 由外å�‘内 }; Q_ENUM(EffectScene) Q_ENUM(EffectType) Q_DECLARE_FLAGS(EffectScenes, EffectScene) Q_DECLARE_FLAGS(EffectTypes, EffectType) Q_ENUM(EffectScenes) Q_ENUM(EffectTypes) static bool setWindowBlurAreaByWM(QWindow *window, const QVector &area); static bool setWindowBlurAreaByWM(QWindow *window, const QList &paths); static bool setWindowWallpaperParaByWM(QWindow *window, const QRect &area, WallpaperScaleMode sMode, WallpaperFillMode fMode); static bool connectWindowManagerChangedSignal(QObject *object, std::function slot); static bool connectHasBlurWindowChanged(QObject *object, std::function slot); bool setWindowBlurAreaByWM(const QVector &area); bool setWindowBlurAreaByWM(const QList &paths); static void setDisableWindowOverrideCursor(QWindow *window, bool disable); int windowRadius() const; int borderWidth() const; QColor borderColor() const; int shadowRadius() const; QPoint shadowOffset() const; QColor shadowColor() const; EffectScene windowEffect(); EffectType windowStartUpEffect(); QPainterPath clipPath() const; QRegion frameMask() const; QMargins frameMargins() const; bool translucentBackground() const; bool enableSystemResize() const; bool enableSystemMove() const; bool enableBlurWindow() const; bool autoInputMaskByClipPath() const; WId realWindowId() const; static WId windowLeader(); public Q_SLOTS: void setWindowRadius(int windowRadius); void setBorderWidth(int borderWidth); void setBorderColor(const QColor &borderColor); void setWindowEffect(EffectScenes effectScene); void setWindowStartUpEffect(EffectTypes effectType); void setShadowRadius(int shadowRadius); void setShadowOffset(const QPoint &shadowOffset); void setShadowColor(const QColor &shadowColor); void setClipPath(const QPainterPath &clipPath); void setFrameMask(const QRegion &frameMask); void setTranslucentBackground(bool translucentBackground); void setEnableSystemResize(bool enableSystemResize); void setEnableSystemMove(bool enableSystemMove); void setEnableBlurWindow(bool enableBlurWindow); void setAutoInputMaskByClipPath(bool autoInputMaskByClipPath); Q_SIGNALS: void frameMarginsChanged(); void windowRadiusChanged(); void borderWidthChanged(); void borderColorChanged(); void shadowRadiusChanged(); void shadowOffsetChanged(); void shadowColorChanged(); void windowEffectChanged(); void windowStartUpEffectChanged(); void clipPathChanged(); void frameMaskChanged(); void translucentBackgroundChanged(); void enableSystemResizeChanged(); void enableSystemMoveChanged(); void enableBlurWindowChanged(); void autoInputMaskByClipPathChanged(); protected: bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; private: QWindow *m_window; }; inline DPlatformHandle::WMBlurArea dMakeWMBlurArea(quint32 x, quint32 y, quint32 width, quint32 height, quint32 xr = 0, quint32 yr = 0) { DPlatformHandle::WMBlurArea a; a.x = x; a.y = y; a.width = width; a.height = height; a.xRadius = xr; a.yRaduis = yr; return a; } DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE DGUI_USE_NAMESPACE QDebug operator<<(QDebug deg, const DPlatformHandle::WMBlurArea &area); QT_END_NAMESPACE #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Q_DECLARE_METATYPE(QPainterPath) Q_DECLARE_METATYPE(QMargins) #endif Q_DECLARE_METATYPE(QRegion) Q_DECLARE_OPERATORS_FOR_FLAGS(DPlatformHandle::EffectScenes) Q_DECLARE_OPERATORS_FOR_FLAGS(DPlatformHandle::EffectTypes) #endif // DPLATFORMHANDLE_H dtkgui-6.7.46/include/kernel/dplatformtheme.h000066400000000000000000000264731522615413000212070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMTHEME_H #define DPLATFORMTHEME_H #include #include #include DGUI_BEGIN_NAMESPACE class DPlatformThemePrivate; // TODO: class DPlatformTheme will be removed in the future class DPlatformTheme : public DNativeSettings { Q_OBJECT D_DECLARE_PRIVATE(DPlatformTheme) Q_PROPERTY(int cursorBlinkTime READ cursorBlinkTime WRITE setCursorBlinkTime NOTIFY cursorBlinkTimeChanged) Q_PROPERTY(int cursorBlinkTimeout READ cursorBlinkTimeout WRITE setCursorBlinkTimeout NOTIFY cursorBlinkTimeoutChanged) Q_PROPERTY(bool cursorBlink READ cursorBlink WRITE setCursorBlink NOTIFY cursorBlinkChanged) Q_PROPERTY(int doubleClickDistance READ doubleClickDistance WRITE setDoubleClickDistance NOTIFY doubleClickDistanceChanged) Q_PROPERTY(int doubleClickTime READ doubleClickTime WRITE setDoubleClickTime NOTIFY doubleClickTimeChanged) Q_PROPERTY(int dndDragThreshold READ dndDragThreshold WRITE setDndDragThreshold NOTIFY dndDragThresholdChanged) Q_PROPERTY(int windowRadius READ windowRadius WRITE setWindowRadius NOTIFY windowRadiusChanged) Q_PROPERTY(QByteArray themeName READ themeName WRITE setThemeName NOTIFY themeNameChanged) Q_PROPERTY(QByteArray iconThemeName READ iconThemeName WRITE setIconThemeName NOTIFY iconThemeNameChanged) Q_PROPERTY(QByteArray soundThemeName READ soundThemeName WRITE setSoundThemeName NOTIFY soundThemeNameChanged) // Font Q_PROPERTY(QByteArray fontName READ fontName WRITE setFontName NOTIFY fontNameChanged) Q_PROPERTY(QByteArray monoFontName READ monoFontName WRITE setMonoFontName NOTIFY monoFontNameChanged) Q_PROPERTY(qreal fontPointSize READ fontPointSize WRITE setFontPointSize NOTIFY fontPointSizeChanged) Q_PROPERTY(QByteArray gtkFontName READ gtkFontName WRITE setGtkFontName NOTIFY gtkFontNameChanged) Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged) Q_PROPERTY(QColor darkActiveColor READ darkActiveColor WRITE setDarkActiveColor NOTIFY darkActiveColorChanged) #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) // QPalette Q_PROPERTY(QColor window READ window WRITE setWindow NOTIFY windowChanged) Q_PROPERTY(QColor windowText READ windowText WRITE setWindowText NOTIFY windowTextChanged) Q_PROPERTY(QColor base READ base WRITE setBase NOTIFY baseChanged) Q_PROPERTY(QColor alternateBase READ alternateBase WRITE setAlternateBase NOTIFY alternateBaseChanged) Q_PROPERTY(QColor toolTipBase READ toolTipBase WRITE setToolTipBase NOTIFY toolTipBaseChanged) Q_PROPERTY(QColor toolTipText READ toolTipText WRITE setToolTipText NOTIFY toolTipTextChanged) Q_PROPERTY(QColor text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor button READ button WRITE setButton NOTIFY buttonChanged) Q_PROPERTY(QColor buttonText READ buttonText WRITE setButtonText NOTIFY buttonTextChanged) Q_PROPERTY(QColor brightText READ brightText WRITE setBrightText NOTIFY brightTextChanged) Q_PROPERTY(QColor light READ light WRITE setLight NOTIFY lightChanged) Q_PROPERTY(QColor midlight READ midlight WRITE setMidlight NOTIFY midlightChanged) Q_PROPERTY(QColor dark READ dark WRITE setDark NOTIFY darkChanged) Q_PROPERTY(QColor mid READ mid WRITE setMid NOTIFY midChanged) Q_PROPERTY(QColor shadow READ shadow WRITE setShadow NOTIFY shadowChanged) Q_PROPERTY(QColor highlight READ highlight WRITE setHighlight NOTIFY highlightChanged) Q_PROPERTY(QColor highlightedText READ highlightedText WRITE setHighlightedText NOTIFY highlightedTextChanged) Q_PROPERTY(QColor link READ link WRITE setLink NOTIFY linkChanged) Q_PROPERTY(QColor linkVisited READ linkVisited WRITE setLinkVisited NOTIFY linkVisitedChanged) // DPalette Q_PROPERTY(QColor itemBackground READ itemBackground WRITE setItemBackground NOTIFY itemBackgroundChanged) Q_PROPERTY(QColor textTitle READ textTitle WRITE setTextTitle NOTIFY textTitleChanged) Q_PROPERTY(QColor textTips READ textTips WRITE setTextTips NOTIFY textTipsChanged) Q_PROPERTY(QColor textWarning READ textWarning WRITE setTextWarning NOTIFY textWarningChanged) Q_PROPERTY(QColor textLively READ textLively WRITE setTextLively NOTIFY textLivelyChanged) Q_PROPERTY(QColor lightLively READ lightLively WRITE setLightLively NOTIFY lightLivelyChanged) Q_PROPERTY(QColor darkLively READ darkLively WRITE setDarkLively NOTIFY darkLivelyChanged) Q_PROPERTY(QColor frameBorder READ frameBorder WRITE setFrameBorder NOTIFY frameBorderChanged) #endif // DSizeMode Q_PROPERTY(int sizeMode READ sizeMode NOTIFY sizeModeChanged) Q_PROPERTY(int scrollBarPolicy READ scrollBarPolicy NOTIFY scrollBarPolicyChanged) public: explicit DPlatformTheme(quint32 window, QObject *parent = nullptr); DPlatformTheme(quint32 window, DPlatformTheme *parent); ~DPlatformTheme(); bool isValid() const; DPlatformTheme *parentTheme() const; void setFallbackProperty(bool fallback); DPalette palette() const; DPalette fetchPalette(const DPalette &base, bool *ok = nullptr) const; void setPalette(const DPalette &palette); int cursorBlinkTime() const; int cursorBlinkTimeout() const; bool cursorBlink() const; int doubleClickDistance() const; int doubleClickTime() const; int dndDragThreshold() const; int windowRadius() const; int windowRadius(int defaultValue) const; QByteArray themeName() const; QByteArray iconThemeName() const; QByteArray soundThemeName() const; QByteArray fontName() const; QByteArray monoFontName() const; qreal fontPointSize() const; QByteArray gtkFontName() const; QColor activeColor() const; QColor darkActiveColor() const; bool isValidPalette() const; #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QColor window() const; QColor windowText() const; QColor base() const; QColor alternateBase() const; QColor toolTipBase() const; QColor toolTipText() const; QColor text() const; QColor button() const; QColor buttonText() const; QColor brightText() const; QColor light() const; QColor midlight() const; QColor dark() const; QColor mid() const; QColor shadow() const; QColor highlight() const; QColor highlightedText() const; QColor link() const; QColor linkVisited() const; QColor itemBackground() const; QColor textTitle() const; QColor textTips() const; QColor textWarning() const; QColor textLively() const; QColor lightLively() const; QColor darkLively() const; QColor frameBorder() const; #endif int sizeMode() const; int scrollBarPolicy() const; public Q_SLOTS: void setCursorBlinkTime(int cursorBlinkTime); void setCursorBlinkTimeout(int cursorBlinkTimeout); void setCursorBlink(bool cursorBlink); void setDoubleClickDistance(int doubleClickDistance); void setDoubleClickTime(int doubleClickTime); void setDndDragThreshold(int dndDragThreshold); void setThemeName(const QByteArray &themeName); void setIconThemeName(const QByteArray &iconThemeName); void setSoundThemeName(const QByteArray &soundThemeName); void setFontName(const QByteArray &fontName); void setMonoFontName(const QByteArray &monoFontName); void setFontPointSize(qreal fontPointSize); void setGtkFontName(const QByteArray &fontName); void setActiveColor(const QColor activeColor); void setDarkActiveColor(const QColor &activeColor); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void setWindow(const QColor &window); void setWindowText(const QColor &windowText); void setBase(const QColor &base); void setAlternateBase(const QColor &alternateBase); void setToolTipBase(const QColor &toolTipBase); void setToolTipText(const QColor &toolTipText); void setText(const QColor &text); void setButton(const QColor &button); void setButtonText(const QColor &buttonText); void setBrightText(const QColor &brightText); void setLight(const QColor &light); void setMidlight(const QColor &midlight); void setDark(const QColor &dark); void setMid(const QColor &mid); void setShadow(const QColor &shadow); void setHighlight(const QColor &highlight); void setHighlightedText(const QColor &highlightedText); void setLink(const QColor &link); void setLinkVisited(const QColor &linkVisited); void setItemBackground(const QColor &itemBackground); void setTextTitle(const QColor &textTitle); void setTextTips(const QColor &textTips); void setTextWarning(const QColor &textWarning); void setTextLively(const QColor &textLively); void setLightLively(const QColor &lightLively); void setDarkLively(const QColor &darkLively); void setFrameBorder(const QColor &frameBorder); #endif int dotsPerInch(const QString &screenName = QString()) const; void setDotsPerInch(const QString &screenName, int dpi); void setWindowRadius(int windowRadius); Q_SIGNALS: void cursorBlinkTimeChanged(int cursorBlinkTime); void cursorBlinkTimeoutChanged(int cursorBlinkTimeout); void cursorBlinkChanged(bool cursorBlink); void doubleClickDistanceChanged(int doubleClickDistance); void doubleClickTimeChanged(int doubleClickTime); void dndDragThresholdChanged(int dndDragThreshold); void themeNameChanged(QByteArray themeName); void iconThemeNameChanged(QByteArray iconThemeName); void soundThemeNameChanged(QByteArray soundThemeName); void fontNameChanged(QByteArray fontName); void monoFontNameChanged(QByteArray monoFontName); void fontPointSizeChanged(qreal fontPointSize); void gtkFontNameChanged(QByteArray fontName); void activeColorChanged(QColor activeColor); void darkActiveColorChanged(QColor activeColor); void paletteChanged(DPalette palette); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void windowChanged(QColor window); void windowTextChanged(QColor windowText); void baseChanged(QColor base); void alternateBaseChanged(QColor alternateBase); void toolTipBaseChanged(QColor toolTipBase); void toolTipTextChanged(QColor toolTipText); void textChanged(QColor text); void buttonChanged(QColor button); void buttonTextChanged(QColor buttonText); void brightTextChanged(QColor brightText); void lightChanged(QColor light); void midlightChanged(QColor midlight); void darkChanged(QColor dark); void midChanged(QColor mid); void shadowChanged(QColor shadow); void highlightChanged(QColor highlight); void highlightedTextChanged(QColor highlightedText); void linkChanged(QColor link); void linkVisitedChanged(QColor linkVisited); void itemBackgroundChanged(QColor itemBackground); void textTitleChanged(QColor textTitle); void textTipsChanged(QColor textTips); void textWarningChanged(QColor textWarning); void textLivelyChanged(QColor textLively); void lightLivelyChanged(QColor lightLively); void darkLivelyChanged(QColor darkLively); void frameBorderChanged(QColor frameBorder); #endif void dotsPerInchChanged(const QString &screen, int dpi); void windowRadiusChanged(int r); void sizeModeChanged(int sizeMode); void scrollBarPolicyChanged(int scrollBarPolicy); private: friend class DPlatformThemePrivate; }; DGUI_END_NAMESPACE #endif // DPLATFORMTHEME_H dtkgui-6.7.46/include/kernel/dregionmonitor.h000066400000000000000000000055401522615413000212230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DREGIONMONITOR_H #define DREGIONMONITOR_H #include #include #include DGUI_BEGIN_NAMESPACE class DRegionMonitorPrivate; class DRegionMonitor : public QObject, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT D_DECLARE_PRIVATE(DRegionMonitor) Q_DISABLE_COPY(DRegionMonitor) Q_PROPERTY(CoordinateType coordinateType READ coordinateType WRITE setCoordinateType NOTIFY coordinateTypeChanged) Q_PROPERTY(RegisterdFlags registerdFlags READ registerFlags WRITE setRegisterFlags NOTIFY registerdFlagsChanged) public: explicit DRegionMonitor(QObject *parent = nullptr); enum RegisterdFlag { Motion = 1 << 0, Button = 1 << 1, Key = 1 << 2 }; Q_DECLARE_FLAGS(RegisterdFlags, RegisterdFlag) enum WatchedFlags { Button_Left = 1, Button_Middle, Button_Right, Wheel_Up, Wheel_Down }; enum CoordinateType { ScaleRatio, Original }; Q_ENUM(CoordinateType) bool registered() const; QRegion watchedRegion() const; RegisterdFlags registerFlags() const; CoordinateType coordinateType() const; Q_SIGNALS: void buttonPress(const QPoint &p, const int flag) const; void buttonRelease(const QPoint &p, const int flag) const; void cursorMove(const QPoint &p) const; void cursorEnter(const QPoint &p) const; void cursorLeave(const QPoint &p) const; void keyPress(const QString &keyname) const; void keyRelease(const QString &keyname) const; void registerdFlagsChanged(RegisterdFlags flags) const; void coordinateTypeChanged(CoordinateType type) const; public Q_SLOTS: void registerRegion(); inline void registerRegion(const QRegion ®ion) { setWatchedRegion(region); registerRegion(); } void unregisterRegion(); void setWatchedRegion(const QRegion ®ion); void setRegisterFlags(RegisterdFlags flags); void setCoordinateType(CoordinateType type); private: Q_PRIVATE_SLOT(d_func(), void _q_ButtonPress(const int, const int, const int, const QString&)) Q_PRIVATE_SLOT(d_func(), void _q_ButtonRelease(const int, const int, const int, const QString&)) Q_PRIVATE_SLOT(d_func(), void _q_CursorMove(const int, const int, const QString &)) Q_PRIVATE_SLOT(d_func(), void _q_CursorEnter(const int, const int, const QString &)) Q_PRIVATE_SLOT(d_func(), void _q_CursorLeave(const int, const int, const QString &)) Q_PRIVATE_SLOT(d_func(), void _q_KeyPress(const QString &, const int, const int, const QString &)) Q_PRIVATE_SLOT(d_func(), void _q_KeyRelease(const QString &, const int, const int, const QString &)) }; Q_DECLARE_OPERATORS_FOR_FLAGS (DRegionMonitor::RegisterdFlags); DGUI_END_NAMESPACE #endif // DREGIONMONITOR_H dtkgui-6.7.46/include/kernel/dwindowgroupleader.h000066400000000000000000000014021522615413000220620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DWINDOWGROUPLEADER_H #define DWINDOWGROUPLEADER_H #include #include QT_BEGIN_NAMESPACE class QWindow; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE class DWindowGroupLeaderPrivate; class DWindowGroupLeader { public: explicit DWindowGroupLeader(quint32 groupId = 0); ~DWindowGroupLeader(); quint32 groupLeaderId() const; quint32 clientLeaderId() const; void addWindow(QWindow *window); void removeWindow(QWindow *window); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(DWindowGroupLeader) }; DGUI_END_NAMESPACE #endif // DWINDOWGROUPLEADER_H dtkgui-6.7.46/include/kernel/dwindowmanagerhelper.h000066400000000000000000000104401522615413000223650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DWINDOWMANAGERHELPER_H #define DWINDOWMANAGERHELPER_H #include #include #include DGUI_BEGIN_NAMESPACE class DForeignWindow; class DWindowManagerHelperPrivate; class DWindowManagerHelper : public QObject, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT Q_PROPERTY(bool hasBlurWindow READ hasBlurWindow NOTIFY hasBlurWindowChanged) Q_PROPERTY(bool hasComposite READ hasComposite NOTIFY hasCompositeChanged) Q_PROPERTY(bool hasNoTitlebar READ hasNoTitlebar NOTIFY hasNoTitlebarChanged) Q_PROPERTY(bool hasWallpaperEffect READ hasWallpaperEffect NOTIFY hasWallpaperEffectChanged) public: enum MotifFunction { FUNC_RESIZE = (1L << 1), FUNC_MOVE = (1L << 2), FUNC_MINIMIZE = (1L << 3), FUNC_MAXIMIZE = (1L << 4), FUNC_CLOSE = (1L << 5), FUNC_ALL = FUNC_RESIZE | FUNC_MOVE | FUNC_MINIMIZE | FUNC_MAXIMIZE | FUNC_CLOSE }; Q_ENUM(MotifFunction) Q_DECLARE_FLAGS(MotifFunctions, MotifFunction) Q_FLAG(MotifFunctions) enum MotifDecoration { DECOR_BORDER = (1L << 1), DECOR_RESIZEH = (1L << 2), DECOR_TITLE = (1L << 3), DECOR_MENU = (1L << 4), DECOR_MINIMIZE = (1L << 5), DECOR_MAXIMIZE = (1L << 6), DECOR_ALL = DECOR_BORDER | DECOR_RESIZEH | DECOR_TITLE | DECOR_MENU | DECOR_MINIMIZE | DECOR_MAXIMIZE }; Q_ENUM(MotifDecoration) Q_DECLARE_FLAGS(MotifDecorations, MotifDecoration) Q_FLAG(MotifDecorations) enum WMName { OtherWM, DeepinWM, KWinWM }; Q_ENUM(WMName) enum WmWindowType { UnknowWindowType = 0x000000, NormalType = 0x000001, DesktopType = 0x000002, DockType = 0x000004, ToolbarType = 0x000008, MenuType = 0x000010, UtilityType = 0x000020, SplashType = 0x000040, DialogType = 0x000080, DropDownMenuType = 0x000100, PopupMenuType = 0x000200, TooltipType = 0x000400, NotificationType = 0x000800, ComboType = 0x001000, DndType = 0x002000, KdeOverrideType = 0x004000 }; Q_ENUM(WmWindowType) Q_DECLARE_FLAGS(WmWindowTypes, WmWindowType) Q_FLAG(WmWindowTypes) ~DWindowManagerHelper(); static DWindowManagerHelper *instance(); static void setMotifFunctions(const QWindow *window, MotifFunctions hints); static MotifFunctions setMotifFunctions(const QWindow *window, MotifFunctions hints, bool on); static MotifFunctions getMotifFunctions(const QWindow *window); static void setMotifDecorations(const QWindow *window, MotifDecorations hints); static MotifDecorations setMotifDecorations(const QWindow *window, MotifDecorations hints, bool on); static MotifDecorations getMotifDecorations(const QWindow *window); static void setWmWindowTypes(QWindow *window, WmWindowTypes types); static void setWmClassName(const QByteArray &name); static void popupSystemWindowMenu(const QWindow *window); bool hasBlurWindow() const; bool hasComposite() const; bool hasNoTitlebar() const; bool hasWallpaperEffect() const; QString windowManagerNameString() const; WMName windowManagerName() const; QVector allWindowIdList() const; QVector currentWorkspaceWindowIdList() const; QList currentWorkspaceWindows() const; quint32 windowFromPoint(const QPoint &p); Q_SIGNALS: void windowManagerChanged(); void hasBlurWindowChanged(); void hasCompositeChanged(); void hasNoTitlebarChanged(); void hasWallpaperEffectChanged(); void windowListChanged(); void windowMotifWMHintsChanged(quint32 winId); protected: explicit DWindowManagerHelper(QObject *parent = 0); private: D_DECLARE_PRIVATE(DWindowManagerHelper) }; DGUI_END_NAMESPACE Q_DECLARE_OPERATORS_FOR_FLAGS(DTK_GUI_NAMESPACE::DWindowManagerHelper::MotifFunctions) Q_DECLARE_OPERATORS_FOR_FLAGS(DTK_GUI_NAMESPACE::DWindowManagerHelper::MotifDecorations) Q_DECLARE_OPERATORS_FOR_FLAGS(DTK_GUI_NAMESPACE::DWindowManagerHelper::WmWindowTypes) #endif // DWINDOWMANAGERHELPER_H dtkgui-6.7.46/include/util/000077500000000000000000000000001522615413000155045ustar00rootroot00000000000000dtkgui-6.7.46/include/util/ddciicon.h000066400000000000000000000112121522615413000174260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include "ddciiconpalette.h" #include #include #include DCORE_BEGIN_NAMESPACE class DDciFile; DCORE_END_NAMESPACE DGUI_BEGIN_NAMESPACE typedef void* DDciIconMatchResult; class DDciIconImagePrivate; class DDciIconImage { friend class DDciIcon; public: DDciIconImage() = default; DDciIconImage(const DDciIconImage &other); DDciIconImage &operator=(const DDciIconImage &other) noexcept; DDciIconImage(DDciIconImage && other) noexcept; DDciIconImage &operator=(DDciIconImage &&other) noexcept; void swap(DDciIconImage &other) noexcept { d.swap(other.d); } ~DDciIconImage(); bool operator==(const DDciIconImage &other) const { return d == other.d; } bool operator!=(const DDciIconImage &other) const { return d != other.d; } inline bool isNull() const { return !d; } void reset(); QImage toImage(const DDciIconPalette &palette = DDciIconPalette()) const; void paint(QPainter *painter, const QRectF &rect, Qt::Alignment alignment = Qt::AlignCenter, const DDciIconPalette &palette = DDciIconPalette()) const; bool hasPalette() const; bool supportsAnimation() const; bool atBegin() const; bool atEnd() const; bool jumpToNextImage(); int loopCount() const; int maxImageCount() const; int currentImageDuration() const; int currentImageNumber() const; protected: DDciIconImage(const QSharedPointer &dd) : d(dd) {} QSharedPointer d; }; class DDciIconPrivate; class DDciIcon { public: enum Mode { Normal = 0, Disabled = 1, Hover = 2, Pressed = 3 }; enum Theme { Light = 0, Dark = 1 }; // IconAttibute is deprecated, please use IconAttribute instead. enum IconAttibute { HasPalette = 0x001 }; using IconAttribute = DDciIcon::IconAttibute; enum IconMatchedFlag { None = 0, DontFallbackMode = 0x01, RegardPaddingsAsSize = 0x02 }; Q_DECLARE_FLAGS(IconMatchedFlags, IconMatchedFlag) Q_FLAGS(IconMatchedFlags); DDciIcon(); explicit DDciIcon(const DCORE_NAMESPACE::DDciFile *dciFile); explicit DDciIcon(const QString &fileName); explicit DDciIcon(const QByteArray &data); DDciIcon(const DDciIcon &other); DDciIcon &operator=(const DDciIcon &other) noexcept; ~DDciIcon(); DDciIcon(DDciIcon && other) noexcept; DDciIcon &operator=(DDciIcon &&other) noexcept; void swap(DDciIcon &other) noexcept { d.swap(other.d); } bool isNull() const; DDciIconMatchResult matchIcon(int size, Theme theme, Mode mode, IconMatchedFlags flags = None) const; int actualSize(DDciIconMatchResult result) const; int actualSize(int size, Theme theme, Mode mode = Normal) const; QList availableSizes(Theme theme, Mode mode = Normal) const; bool isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr) const; static bool isSupportedAttribute(const DDciIconImage &image, IconAttribute attr); QPixmap pixmap(qreal devicePixelRatio, int iconSize, Theme theme, Mode mode = Normal, const DDciIconPalette &palette = DDciIconPalette()) const; QPixmap pixmap(qreal devicePixelRatio, int iconSize, DDciIconMatchResult result, const DDciIconPalette &palette = DDciIconPalette()) const; void paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, Theme theme, Mode mode = Normal, Qt::Alignment alignment = Qt::AlignCenter, const DDciIconPalette &palette = DDciIconPalette()) const; void paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, DDciIconMatchResult result, Qt::Alignment alignment = Qt::AlignCenter, const DDciIconPalette &palette = DDciIconPalette()) const; DDciIconImage image(DDciIconMatchResult result, int size, qreal devicePixelRatio) const; static DDciIcon fromTheme(const QString &name); static DDciIcon fromTheme(const QString &name, const DDciIcon &fallback); // TODO: Should be compatible with QIcon private: QSharedDataPointer d; #ifndef QT_NO_DATASTREAM friend QDataStream &operator<<(QDataStream &, const DDciIcon &); friend QDataStream &operator>>(QDataStream &, DDciIcon &); #endif }; #ifndef QT_NO_DATASTREAM QDataStream &operator<<(QDataStream &, const DDciIcon &); QDataStream &operator>>(QDataStream &, DDciIcon &); #endif DGUI_END_NAMESPACE Q_DECLARE_METATYPE(DTK_GUI_NAMESPACE::DDciIcon); dtkgui-6.7.46/include/util/ddciiconpalette.h000066400000000000000000000037161522615413000210170ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DDCIICONPALETTE_H #define DDCIICONPALETTE_H #include #include #include #include QT_BEGIN_NAMESPACE class QPalette; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE class DDciIconPalette { Q_GADGET Q_PROPERTY(QColor foreground READ foreground WRITE setForeground FINAL) Q_PROPERTY(QColor background READ background WRITE setBackground FINAL) Q_PROPERTY(QColor highlight READ highlight WRITE setHighlight FINAL) Q_PROPERTY(QColor highlightForeground READ highlightForeground WRITE setHighlightForeground FINAL) public: enum PaletteRole { NoPalette = -1, Foreground = 0, Background = 1, HighlightForeground = 2, Highlight = 3, PaletteCount }; DDciIconPalette(QColor foreground = QColor::Invalid, QColor background = QColor::Invalid, QColor highlight = QColor::Invalid, QColor highlightForeground = QColor::Invalid); bool operator==(const DDciIconPalette &other) const; bool operator!=(const DDciIconPalette &other) const; QColor foreground() const; void setForeground(const QColor &foreground); QColor background() const; void setBackground(const QColor &background); QColor highlightForeground() const; void setHighlightForeground(const QColor &highlightForeground); QColor highlight() const; void setHighlight(const QColor &highlight); static QString convertToString(const DDciIconPalette &palette); static DDciIconPalette convertFromString(const QString &data); static DDciIconPalette fromQPalette(const QPalette &pa); private: QVector colors; }; DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const DTK_GUI_NAMESPACE::DDciIconPalette &); #endif QT_END_NAMESPACE #endif // DDCIICONPALETTE_H dtkgui-6.7.46/include/util/ddciiconplayer.h000066400000000000000000000054611522615413000206540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include #include #include #include DGUI_BEGIN_NAMESPACE class DDciIconImage; class DDciIconPalette; class DDciIconImagePlayerPrivate; class DDciIconImagePlayer : public QObject, public DCORE_NAMESPACE::DObject { D_DECLARE_PRIVATE(DDciIconImagePlayer) Q_OBJECT Q_PROPERTY(DGUI_NAMESPACE::DDciIconImagePlayer::State state READ state NOTIFY stateChanged) public: enum State { NotRunning, WaitingRead, Running }; Q_ENUM(State) enum Flag { Continue = 1, CacheAll = 2, InvertedOrder = 4, IgnoreLastImageLoop = 8, AllowNonLastImageLoop = 16, ClearCacheOnStop = 32 }; Q_DECLARE_FLAGS(Flags, Flag) explicit DDciIconImagePlayer(QObject *parent = nullptr); void setImages(const QVector &images); QVector images() const; const DDciIconImage ¤tImage() const; bool currentLoopForever() const; bool setPalette(const DDciIconPalette &palette); DDciIconPalette palette() const; void setLoopCount(int count); int loopCount() const; void abortLoop(); QImage readImage(); State state() const; void clearCache(); public Q_SLOTS: bool start(float speed = 1.0, DGUI_NAMESPACE::DDciIconImagePlayer::Flags flags = {}); void stop(); Q_SIGNALS: void started(); void updated(); void finished(); void stateChanged(); private: void timerEvent(QTimerEvent *event) override; }; class DDciIconPlayerPrivate; class DDciIconPlayer : public QObject, public DCORE_NAMESPACE::DObject { D_DECLARE_PRIVATE(DDciIconPlayer) Q_OBJECT public: enum State { Idle, Busy }; Q_ENUM(State) explicit DDciIconPlayer(QObject *parent = nullptr); State state() const; void setIcon(const DDciIcon &icon); DDciIcon icon() const; void setTheme(DDciIcon::Theme theme); DDciIcon::Theme theme() const; void setMode(DDciIcon::Mode mode); DDciIcon::Mode mode() const; void setIconSize(int size); int iconSize() const; void setDevicePixelRatio(qreal devicePixelRatio); qreal devicePixelRatio() const; void setPalette(const DDciIconPalette &palette); QImage currentImage() const; void play(DDciIcon::Mode mode); void play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags); void stop(); void abort(); Q_SIGNALS: void stateChanged(); void updated(); void modeChanged(DDciIcon::Mode oldMode, DDciIcon::Mode newMode); private: D_PRIVATE_SLOT(void _q_playFromQueue(int)) }; DGUI_END_NAMESPACE Q_DECLARE_OPERATORS_FOR_FLAGS(DTK_GUI_NAMESPACE::DDciIconImagePlayer::Flags) dtkgui-6.7.46/include/util/ddesktopservices.h000066400000000000000000000047441522615413000212470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include #include #include DGUI_BEGIN_NAMESPACE class DDesktopServices { public: enum SystemSoundEffect { SSE_Notifications, SEE_Screenshot, SSE_EmptyTrash, SSE_SendFileComplete, SSE_BootUp, SSE_Shutdown, SSE_Logout, SSE_WakeUp, SSE_VolumeChange, SSE_LowBattery, SSE_PlugIn, SSE_PlugOut, SSE_DeviceAdded, SSE_DeviceRemoved, SSE_Error, }; static bool showFolder(const QString &localFilePath, const QString &startupId = QString()); static bool showFolders(const QList &localFilePaths, const QString &startupId = QString()); static bool showFolder(const QUrl &url, const QString &startupId = QString()); static bool showFolders(const QList &urls, const QString &startupId = QString()); static bool showFileItemProperty(const QString &localFilePath, const QString &startupId = QString()); static bool showFileItemProperties(const QList &localFilePaths, const QString &startupId = QString()); static bool showFileItemProperty(const QUrl &url, const QString &startupId = QString()); static bool showFileItemProperties(const QList &urls, const QString &startupId = QString()); static bool showFileItem(const QString &localFilePath, const QString &startupId = QString()); static bool showFileItems(const QList &localFilePaths, const QString &startupId = QString()); static bool showFileItem(const QUrl &url, const QString &startupId = QString()); static bool showFileItems(const QList &urls, const QString &startupId = QString()); static bool trash(const QString &localFilePath); static bool trash(const QList &localFilePaths); static bool trash(const QUrl &url); static bool trash(const QList &urls); static bool playSystemSoundEffect(const SystemSoundEffect &effect); static bool playSystemSoundEffect(const QString &name); static bool previewSystemSoundEffect(const SystemSoundEffect &effect); static bool previewSystemSoundEffect(const QString &name); static QString getNameByEffectType(const SystemSoundEffect &effect); static QString errorMessage(); }; DGUI_END_NAMESPACE #ifdef Q_OS_LINUX Q_DECLARE_METATYPE(DTK_GUI_NAMESPACE::DDesktopServices::SystemSoundEffect) #endif dtkgui-6.7.46/include/util/dfontmanager.h000066400000000000000000000053541522615413000203310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFONTSIZEMANAGER_H #define DFONTSIZEMANAGER_H #include #include #include #include DGUI_BEGIN_NAMESPACE class DFontManagerPrivate; class DFontManager : public QObject , public DTK_CORE_NAMESPACE::DObject { Q_OBJECT Q_PROPERTY(QFont t1 READ t1 NOTIFY fontChanged) Q_PROPERTY(QFont t2 READ t2 NOTIFY fontChanged) Q_PROPERTY(QFont t3 READ t3 NOTIFY fontChanged) Q_PROPERTY(QFont t4 READ t4 NOTIFY fontChanged) Q_PROPERTY(QFont t5 READ t5 NOTIFY fontChanged) Q_PROPERTY(QFont t6 READ t6 NOTIFY fontChanged) Q_PROPERTY(QFont t7 READ t7 NOTIFY fontChanged) Q_PROPERTY(QFont t8 READ t8 NOTIFY fontChanged) Q_PROPERTY(QFont t9 READ t9 NOTIFY fontChanged) Q_PROPERTY(QFont t10 READ t10 NOTIFY fontChanged) Q_PROPERTY(QFont baseFont READ baseFont WRITE setBaseFont RESET resetBaseFont NOTIFY fontChanged) public: enum SizeType { T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NSizeTypes }; Q_ENUM(SizeType) DFontManager(QObject *parent = nullptr); ~DFontManager() override; Q_INVOKABLE int fontPixelSize(SizeType type) const; Q_INVOKABLE void setFontPixelSize(SizeType type, int size); Q_INVOKABLE static int fontPixelSize(const QFont &font); Q_INVOKABLE static QFont get(int pixelSize, const QFont &base); inline const QFont get(SizeType type, const QFont &base) const { return get(fontPixelSize(type), base); } inline const QFont get(SizeType type) const { return get(type, baseFont()); } QFont baseFont() const; void setBaseFont(const QFont &font); void resetBaseFont(); inline const QFont t1() const { return get(T1); } inline const QFont t2() const { return get(T2); } inline const QFont t3() const { return get(T3); } inline const QFont t4() const { return get(T4); } inline const QFont t5() const { return get(T5); } inline const QFont t6() const { return get(T6); } inline const QFont t7() const { return get(T7); } inline const QFont t8() const { return get(T8); } inline const QFont t9() const { return get(T9); } inline const QFont t10() const { return get(T10); } inline const QFont t11() const { return get(T11); } Q_SIGNALS: void fontChanged(); private: D_DECLARE_PRIVATE(DFontManager) }; DGUI_END_NAMESPACE #endif // DFONTSIZEMANAGER_H dtkgui-6.7.46/include/util/dicon.h000066400000000000000000000010121522615413000167430ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DICON_H #define DICON_H #include #include DGUI_BEGIN_NAMESPACE class DIcon : public QIcon { public: explicit DIcon(const QIcon &other); virtual ~DIcon(); QPixmap pixmap(const QSize &size, qreal devicePixelRatio, Mode mode = Normal, State state = Off); static QPixmap loadNxPixmap(const QString &fileName); }; DGUI_END_NAMESPACE #endif // DICON_H dtkgui-6.7.46/include/util/dicontheme.h000066400000000000000000000030221522615413000177710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DICONTHEME_H #define DICONTHEME_H #include #include #include DGUI_BEGIN_NAMESPACE namespace DIconTheme { enum Option { DontFallbackToQIconFromTheme = 1 << 0, IgnoreBuiltinIcons = 1 << 1, IgnoreDciIcons = 1 << 2, IgnoreIconCache = 1 << 3 }; Q_DECLARE_FLAGS(Options, Option) class CachedData; class Cached { CachedData *data = nullptr; public: Cached(); ~Cached(); int maxCost() const; void setMaxCost(int cost); void clear(); QIcon findQIcon(const QString &iconName, Options options = Options(), const QIcon &fallback = QIcon()); QString findDciIconFile(const QString &iconName, const QString &themeName, const QString &fallback = {}); }; Cached *cached(); QIcon findQIcon(const QString &iconName, Options options = Options()); QIcon findQIcon(const QString &iconName, const QIcon &fallback, Options options = Options()); QIconEngine *createIconEngine(const QString &iconName, Options options = DontFallbackToQIconFromTheme); QString findDciIconFile(const QString &iconName, const QString &themeName); QStringList dciThemeSearchPaths(); void setDciThemeSearchPaths(const QStringList &path); bool isBuiltinIcon(const QIcon &icon); bool isXdgIcon(const QIcon &icon); } DGUI_END_NAMESPACE #endif // DICONTHEME_H dtkgui-6.7.46/include/util/dimagehandler.h000066400000000000000000000052121522615413000204410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DIMAGEHANDLER_H #define DIMAGEHANDLER_H #include #include #include #include DGUI_BEGIN_NAMESPACE class DImageHandlerPrivate; class DImageHandler : public QObject, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT public: explicit DImageHandler(QObject *parent = nullptr); ~DImageHandler(); void setFileName(const QString &fileName); QString fileName() const; QImage readImage(); QImage thumbnail(const QSize &size, Qt::AspectRatioMode mode); QString imageFormat() const; QSize imageSize(); QHash findAllMetaData(); void clearCache(); bool saveImage(const QString &fileName, const QString &format = QString()); bool saveImage(const QImage &image, const QString &fileName, const QString &format = QString()); bool rotateImage(QImage &image, int angle); bool rotateImageFile(const QString &fileName, int angle); bool isReadable() const; bool isWriteable() const; bool isRotatable() const; QString lastError() const; static QStringList supportFormats(); static QString detectImageFormat(const QString &fileName); static QImage oldColorFilter(const QImage &img); static QImage warmColorFilter(const QImage &img, int intensity = 30); static QImage coolColorFilter(const QImage &img, int intensity = 30); static QImage grayScaleColorFilter(const QImage &img); static QImage antiColorFilter(const QImage &img); static QImage metalColorFilter(const QImage &img); static QImage bilateralFilter(const QImage &img, double spatialDecay = 0.02, double photometricStandardDeviation = 10); static QImage contourExtraction(const QImage &img); static QImage binaryzation(const QImage &img); static QImage grayScale(const QImage &img); static QImage laplaceSharpen(const QImage &img); static QImage sobelEdgeDetector(const QImage &img); static QImage changeLightAndContrast(const QImage &img, int light = 100, int contrast = 150); static QImage changeBrightness(const QImage &img, int brightness); static QImage changeTransparency(const QImage &img, int transparency); static QImage changeStauration(const QImage &img, int saturation); static QImage replacePointColor(const QImage &img, QColor oldColor, QColor newColor); static QImage flipHorizontal(const QImage &img); static QImage flipVertical(const QImage &img); private: D_DECLARE_PRIVATE(DImageHandler) Q_DISABLE_COPY(DImageHandler) }; DGUI_END_NAMESPACE #endif // DIMAGEHANDLER_H dtkgui-6.7.46/include/util/dsvgrenderer.h000066400000000000000000000031311522615413000203450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DSVGRENDERER_H #define DSVGRENDERER_H #include #include #include #include QT_BEGIN_NAMESPACE class QPainter; QT_END_NAMESPACE #ifdef Q_OS_LINUX DGUI_BEGIN_NAMESPACE class DSvgRendererPrivate; class DSvgRenderer : public QObject, public DTK_CORE_NAMESPACE::DObject { Q_PROPERTY(QRectF viewBox READ viewBoxF WRITE setViewBox) public: explicit DSvgRenderer(QObject *parent = Q_NULLPTR); DSvgRenderer(const QString &filename, QObject *parent = Q_NULLPTR); DSvgRenderer(const QByteArray &contents, QObject *parent = Q_NULLPTR); ~DSvgRenderer(); bool isValid() const; QSize defaultSize() const; QRect viewBox() const; QRectF viewBoxF() const; void setViewBox(const QRect &viewbox); void setViewBox(const QRectF &viewbox); QRectF boundsOnElement(const QString &id) const; bool elementExists(const QString &id) const; QImage toImage(const QSize sz, const QString &elementId = QString()) const; public Q_SLOTS: bool load(const QString &filename); bool load(const QByteArray &contents); void render(QPainter *p); void render(QPainter *p, const QRectF &bounds); void render(QPainter *p, const QString &elementId, const QRectF &bounds = QRectF()); private: D_DECLARE_PRIVATE(DSvgRenderer) }; DGUI_END_NAMESPACE #else #include DGUI_BEGIN_NAMESPACE typedef QSvgRenderer DSvgRenderer; DGUI_END_NAMESPACE #endif #endif // DSVGRENDERER_H dtkgui-6.7.46/include/util/dtaskbarcontrol.h000066400000000000000000000021221522615413000210460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTASKBARCONTROL_H #define DTASKBARCONTROL_H #include #include #include #include DGUI_BEGIN_NAMESPACE class DTaskbarControlPrivate; class DTaskbarControl : public QObject, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT public: explicit DTaskbarControl(QObject *parent = nullptr); ~DTaskbarControl(); void setProgress(bool progressVisible, double progress); void setCounter(bool counterVisible, int counter); int counter() const; void setCounterVisible(bool counterVisible); bool counterVisible() const; void setUrgency(bool val); Q_SIGNALS: void counterChanged(int counter); void counterVisibleChanged(bool visible); void progressChanged(double progress); void progressVisibleChanged(bool visible); protected: virtual void sendMessage(const QVariantMap ¶ms); private: D_DECLARE_PRIVATE(DTaskbarControl) }; DGUI_END_NAMESPACE #endif // DTASKBARCONTROL_H dtkgui-6.7.46/include/util/dthumbnailprovider.h000066400000000000000000000034651522615413000215670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILETHUMBNAILPROVIDER_H #define DFILETHUMBNAILPROVIDER_H #include #include #include #include #include QT_BEGIN_NAMESPACE class QMimeType; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE class DThumbnailProviderPrivate; class DThumbnailProvider : public QThread, public DTK_CORE_NAMESPACE::DObject { Q_OBJECT public: enum Size { Small = 64, Normal = 128, Large = 256, }; static DThumbnailProvider *instance(); bool hasThumbnail(const QFileInfo &info) const; bool hasThumbnail(const QMimeType &mimeType) const; QString thumbnailFilePath(const QFileInfo &info, Size size) const; QString createThumbnail(const QFileInfo &info, Size size); typedef std::function CallBack; void appendToProduceQueue(const QFileInfo &info, Size size, CallBack callback = 0); void removeInProduceQueue(const QFileInfo &info, Size size); QString errorString() const; qint64 defaultSizeLimit() const; void setDefaultSizeLimit(qint64 size); qint64 sizeLimit(const QMimeType &mimeType) const; void setSizeLimit(const QMimeType &mimeType, qint64 size); Q_SIGNALS: void thumbnailChanged(const QString &sourceFilePath, const QString &thumbnailPath) const; void createThumbnailFinished(const QString &sourceFilePath, const QString &thumbnailPath) const; void createThumbnailFailed(const QString &sourceFilePath) const; protected: explicit DThumbnailProvider(QObject *parent = 0); ~DThumbnailProvider(); void run() Q_DECL_OVERRIDE; private: D_DECLARE_PRIVATE(DThumbnailProvider) }; DGUI_END_NAMESPACE #endif // DFILETHUMBNAILPROVIDER_H dtkgui-6.7.46/linglong.yaml000066400000000000000000000011131522615413000155750ustar00rootroot00000000000000package: id: dtkgui name: dtkgui kind: lib version: 5.6.3 descriptipon: | Deepin Tool Kit Gui library \ DtkGui is base library of Deepin Qt/C++ applications. base: id: org.deepin.base version: 23.0.0 depends: - id: qtbase/5.15.7 - id: qtsvg/5.15.7 - id: dtkcommon/5.6.0.1 - id: gsettings-qt/0.3.1.1 - id: dtkcore/5.6.0.2 - id: libqtxdg/3.6.0.1 - id: freeimage/3.18.0 source: kind: local variables: extra_args: | -DBUILD_EXAMPLE=OFF \ -DBUILD_DOCS=OFF \ -DBUILD_VERSION=${VERSION} \ -DVERSION=${VERSION} build: kind: cmake dtkgui-6.7.46/misc/000077500000000000000000000000001522615413000140375ustar00rootroot00000000000000dtkgui-6.7.46/misc/DtkGuiConfig.cmake.in000066400000000000000000000013311522615413000177610ustar00rootroot00000000000000@PACKAGE_INIT@ include(CMakeFindDependencyMacro) find_dependency(Dtk@DTK_NAME_SUFFIX@Core) find_dependency(Qt@QT_VERSION_MAJOR@Network) find_dependency(Qt@QT_VERSION_MAJOR@Gui) include(${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_NAME_SUFFIX@GuiTargets.cmake) set(DtkGui_LIBRARIES Dtk@DTK_NAME_SUFFIX@::Gui) get_target_property(DtkGui_INCLUDE_DIRS Dtk@DTK_NAME_SUFFIX@::Gui INTERFACE_INCLUDE_DIRECTORIES) get_target_property(DtkGui_LIBRARY_DIRS Dtk@DTK_NAME_SUFFIX@::Gui INTERFACE_LINK_DIRECTORIES) set(DtkGui_TOOL_DIRS "@PACKAGE_TOOL_INSTALL_DIR@") check_required_components(Dtk@DTK_NAME_SUFFIX@Gui) # Keep deprecated variables for compatibility set(DTKGUI_INCLUDE_DIR ${DtkGui_INCLUDE_DIRS}) set(DTKGUI_TOOL_DIR ${DtkGui_TOOL_DIRS}) dtkgui-6.7.46/misc/dtkgui.pc.in000066400000000000000000000006031522615413000162560ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/@LIBRARY_INSTALL_DIR@ includedir=${prefix}/@INCLUDE_INSTALL_DIR@ tooldir=${prefix}/@PACKAGE_TOOL_INSTALL_DIR@ Name: dtk@DTK_NAME_SUFFIX@gui Description: Development ToolKit Gui Devel Library Version: @DTK_VERSION@ Libs: -L${libdir} -ldtk@DTK_NAME_SUFFIX@gui Cflags: -I${includedir} Requires: dtk@DTK_NAME_SUFFIX@core dtkgui-6.7.46/misc/org.deepin.dtk.ui.preference.json000066400000000000000000000020111522615413000222700ustar00rootroot00000000000000{ "magic": "dsg.config.meta", "version": "1.0", "contents": { "titlebarHeight": { "value": -1, "serial": 0, "name": "The height of DTitleBar", "name[zh_CN]": "标题æ �高度", "description": "Configure the height of the DTitleBar", "description[zh_CN]": "é…�置标题æ �的高度", "permissions": "readwrite", "visibility": "public" }, "themeType": { "value": 0, "serial": 0, "flags": [], "name": "The application theme type", "name[zh_CN]": "应用主题的颜色", "description": "The application theme type, which can be set to follow the system theme (0), light theme (1), dark theme (2)", "description[zh_CN]": "应用主题的颜色,å�¯ä»¥è®¾ç½®ä¸ºè·Ÿéš�系统(0)ã€�浅色(1)ã€� 深色(2),默认为跟éš�系统", "permissions": "readwrite", "visibility": "public" } } } dtkgui-6.7.46/misc/qt_lib_dtkgui.pri.in000066400000000000000000000011261522615413000200010ustar00rootroot00000000000000QT.dtkgui.VERSION = @DTK_VERSION@ QT.dtkgui.MAJOR_VERSION = @DTK_VERSION_MAJOR@ QT.dtkgui.MINOR_VERSION = @DTK_VERSION_MINOR@ QT.dtkgui.PATCH_VERSION = @DTK_VERSION_PATCH@ QT.dtkgui.name = dtkgui QT.dtkgui.module = dtk@DTK_NAME_SUFFIX@gui QT.dtkgui.tools = @CMAKE_INSTALL_PREFIX@/@TOOL_INSTALL_DIR@ QT.dtkgui.libs = @CMAKE_INSTALL_PREFIX@/@LIBRARY_INSTALL_DIR@ QT.dtkgui.includes = @CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ QT.dtkgui.frameworks = QT.dtkgui.depends = core gui dtkcore gui_private dbus network QT.dtkgui.module_config = v2 internal_module ltcg QT.dtkgui.DEFINES = QT_MODULES += dtkgui-6.7.46/rpm/000077500000000000000000000000001522615413000137025ustar00rootroot00000000000000dtkgui-6.7.46/rpm/dtkgui.spec000066400000000000000000000035261522615413000160530ustar00rootroot00000000000000Name: dtkgui Version: 6.7.46 Release: 1%{?dist} Summary: Deepin dtkgui License: LGPLv3+ URL: https://github.com/linuxdeepin/dtkgui %if 0%{?fedora} Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz %else Source0: %{name}-%{version}.orig.tar.xz %endif BuildRequires: qt5-qtx11extras-devel BuildRequires: dtkcommon-devel BuildRequires: dtkcore-devel BuildRequires: librsvg2-devel BuildRequires: gtest-devel BuildRequires: gcc-c++ BuildRequires: annobin BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(gsettings-qt) BuildRequires: pkgconfig(gmock) %if 0%{?fedora} BuildRequires: qt5-qtbase-private-devel %{?_qt5:Requires: %{_qt5}%{?_isa} = %{_qt5_version}} %endif BuildRequires: make %description Dtkgui is the GUI module for DDE look and feel. %package devel Summary: Development package for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} Requires: dtkcore-devel%{?_isa} %description devel Header files and libraries for %{name}. %prep %autosetup %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} %files %doc README.md %license LICENSE %{_libdir}/lib%{name}.so.5* %{_libexecdir}/dtk5/deepin-gui-settings %{_libexecdir}/dtk5/taskbar %{_libexecdir}/dtk5/dde-kwin-debug %files devel %{_includedir}/libdtk-*/ %{_libdir}/pkgconfig/dtkgui.pc %{_qt5_archdatadir}/mkspecs/modules/qt_lib_dtkgui.pri %{_libdir}/cmake/DtkGui/ %{_libdir}/lib%{name}.so %changelog * Thu Jun 09 2020 uoser - 5.2.2.1-1 - Update to 5.2.2.1 dtkgui-6.7.46/src/000077500000000000000000000000001522615413000136735ustar00rootroot00000000000000dtkgui-6.7.46/src/CMakeLists.txt000066400000000000000000000071001522615413000164310ustar00rootroot00000000000000if("${QT_VERSION_MAJOR}" STREQUAL "6") find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets WaylandClient) if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0") set(QT_NO_PRIVATE_MODULE_WARNING ON) find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate) endif() else() find_package(Qt5 REQUIRED COMPONENTS WaylandClient XkbCommonSupport) endif() add_library(${LIB_NAME} SHARED) include(dbus/dbus.cmake) include(filedrag/dfiledrag.cmake) include(kernel/kernel.cmake) include(private/private.cmake) include(util/util.cmake) include(plugins/plugins.cmake) target_sources(${LIB_NAME} PRIVATE ${dbus_SRC} ${filedrag_SRC} ${kernel_SRC} ${util_SRC} ${private_SRC} ) target_include_directories(${LIB_NAME} PUBLIC $ $ $ $ $ $ $ $ ) target_include_directories(${LIB_NAME} PRIVATE $ ) target_link_libraries(${LIB_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network Dtk${DTK_NAME_SUFFIX}::Core PRIVATE Qt${QT_VERSION_MAJOR}::GuiPrivate Qt${QT_VERSION_MAJOR}::CorePrivate Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::WaylandClientPrivate ) if("${QT_VERSION_MAJOR}" STREQUAL "5") target_link_libraries(${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::XkbCommonSupportPrivate ) endif() if(DTK_DISABLE_LIBRSVG) find_package(Qt${QT_VERSION_MAJOR}Svg REQUIRED) target_link_libraries(${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Svg) else() target_link_libraries(${LIB_NAME} PRIVATE PkgConfig::librsvg) endif() if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND) target_link_libraries(${LIB_NAME} PRIVATE ${libraw_LIBRARIES} FreeImage::FreeImage ) target_include_directories(${LIB_NAME} PRIVATE ${libraw_INCLUDE_DIRS} ) endif() if(NOT DTK_DISABLE_LIBXDG) target_link_libraries(${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}XdgIconLoader ) endif() set_target_properties(${LIB_NAME} PROPERTIES VERSION ${DTK_VERSION} SOVERSION ${DTK_VERSION_MAJOR} EXPORT_NAME Gui ) target_include_directories(${LIB_NAME} INTERFACE $ ) target_link_directories(${LIB_NAME} INTERFACE $ ) install(TARGETS ${LIB_NAME} EXPORT Dtk${DTK_NAME_SUFFIX}GuiTargets DESTINATION "${LIBRARY_INSTALL_DIR}") install(EXPORT Dtk${DTK_NAME_SUFFIX}GuiTargets NAMESPACE Dtk${DTK_NAME_SUFFIX}:: FILE Dtk${DTK_NAME_SUFFIX}GuiTargets.cmake DESTINATION "${CONFIG_INSTALL_DIR}") install(DIRECTORY ../include/util/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") install(DIRECTORY ../include/DtkGui/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") install(DIRECTORY ../include/global/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") install(DIRECTORY ../include/kernel/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") install(DIRECTORY ../include/filedrag/ DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*") set(EnableCov CACHE BOOL OFF) if (EnableCov) dtk_setup_code_coverage(${LIB_NAME}) endif() dtkgui-6.7.46/src/dbus/000077500000000000000000000000001522615413000146305ustar00rootroot00000000000000dtkgui-6.7.46/src/dbus/dbus.cmake000066400000000000000000000002011522615413000165600ustar00rootroot00000000000000set(dbus_SRC ${CMAKE_CURRENT_LIST_DIR}/xeventmonitor_interface.h ${CMAKE_CURRENT_LIST_DIR}/xeventmonitor_interface.cpp ) dtkgui-6.7.46/src/dbus/xeventmonitor_interface.cpp000066400000000000000000000036421522615413000223020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "xeventmonitor_interface.h" static void registerAreaListMetaType() { // FIX å�–消注册qRegisterMetaType,会影å“� dock 使用 RegisterAreas dbus接å�£ // 因为 libdframeworkdbus-dev 也会注册 "AreaList" 为 MonitorRect // qRegisterMetaType("AreaList"); qDBusRegisterMetaType(); } Q_CONSTRUCTOR_FUNCTION(registerAreaListMetaType); QDBusArgument &operator<<(QDBusArgument &a, const ComDeepinApiXEventMonitorInterface::AreaList &rects) { // com.deepin.api.XEventMonitor.RegisterAreas // (Array of [Struct of (Int32, Int32, Int32, Int32)] areas, Int32 flag) // use [x1, y1, x2, y2] instead of [x1, y1, w, h] a.beginArray(qRegisterMetaType()); for (const auto &r : rects) { a.beginStructure(); a << r.left() << r.top() << r.right() << r.bottom(); a.endStructure(); } a.endArray(); return a; } const QDBusArgument &operator>>(const QDBusArgument &a, ComDeepinApiXEventMonitorInterface::AreaList &rects) { a.beginArray(); rects.clear(); int x1 = 0 , y1 = 0 , x2 = 0 , y2 = 0 ; while (!a.atEnd()) { a.beginStructure(); a >> x1 >> y1 >> x2 >> y2; a.endStructure(); rects.append(QRect(QPoint(x1, y1), QPoint(x2, y2))); } a.endArray(); return a; } ComDeepinApiXEventMonitorInterface::ComDeepinApiXEventMonitorInterface(const QString &service, const QString &path, const char *interface, QObject *parent, const QDBusConnection &con) : QDBusAbstractInterface(service, path, interface, con, parent) { } ComDeepinApiXEventMonitorInterface::~ComDeepinApiXEventMonitorInterface() { } dtkgui-6.7.46/src/dbus/xeventmonitor_interface.h000066400000000000000000000051431522615413000217450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef XEVENTMONITOR_INTERFACE_H #define XEVENTMONITOR_INTERFACE_H #include #include #include #include #include #include #include #include class ComDeepinApiXEventMonitorInterface: public QDBusAbstractInterface { Q_OBJECT public: typedef QList AreaList; ComDeepinApiXEventMonitorInterface(const QString &service, const QString &path, const char *interface, QObject *parent = nullptr, const QDBusConnection &con = QDBusConnection::sessionBus()); ~ComDeepinApiXEventMonitorInterface(); public Q_SLOTS: // METHODS inline QDBusPendingReply RegisterArea(int in0, int in1, int in2, int in3, int in4) { QList argumentList; argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3) << QVariant::fromValue(in4); return asyncCallWithArgumentList(QStringLiteral("RegisterArea"), argumentList); } inline QDBusPendingReply RegisterAreas(AreaList in0, int in1) { QList argumentList; argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); return asyncCallWithArgumentList(QStringLiteral("RegisterAreas"), argumentList); } inline QDBusPendingReply RegisterFullScreen() { QList argumentList; return asyncCallWithArgumentList(QStringLiteral("RegisterFullScreen"), argumentList); } inline QDBusPendingReply UnregisterArea(const QString &in0) { QList argumentList; argumentList << QVariant::fromValue(in0); return asyncCallWithArgumentList(QStringLiteral("UnregisterArea"), argumentList); } Q_SIGNALS: // SIGNALS void ButtonPress(int in0, int in1, int in2, const QString &in3); void ButtonRelease(int in0, int in1, int in2, const QString &in3); void CancelAllArea(); void CursorInto(int in0, int in1, const QString &in2); void CursorMove(int in0, int in1, const QString &in2); void CursorOut(int in0, int in1, const QString &in2); void KeyPress(const QString &in0, int in1, int in2, const QString &in3); void KeyRelease(const QString &in0, int in1, int in2, const QString &in3); }; namespace com { namespace deepin { namespace api { typedef ::ComDeepinApiXEventMonitorInterface XEventMonitor; } } } #endif dtkgui-6.7.46/src/filedrag/000077500000000000000000000000001522615413000154505ustar00rootroot00000000000000dtkgui-6.7.46/src/filedrag/dfiledrag.cmake000066400000000000000000000003161522615413000203730ustar00rootroot00000000000000file(GLOB FILEDRAG_HEADER ${CMAKE_CURRENT_LIST_DIR}/../../include/filedrag/*.h ) file(GLOB FILEDRAG_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(filedrag_SRC ${FILEDRAG_HEADER} ${FILEDRAG_SOURCE} ) dtkgui-6.7.46/src/filedrag/dfiledrag.cpp000066400000000000000000000035711522615413000201030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dfiledrag.h" #include "dfiledragserver.h" #include "private/dfiledragcommon_p.h" #include "private/dfiledragserver_p.h" #include #include DGUI_BEGIN_NAMESPACE /*! @private */ class DFileDragPrivate : DCORE_NAMESPACE::DObjectPrivate { DFileDragPrivate(DFileDrag *q, DFileDragServer *_srv) : DObjectPrivate(q) , srv(_srv) {} DFileDragServer *srv; D_DECLARE_PUBLIC(DFileDrag) }; /*! \class Dtk::Gui::DFileDrag \inmodule dtkgui \brief 继承自QDrag,一般在文件拖拽å�‘é€�æ–¹ mouseMoveEvent 中å�‘起拖拽,设置å�‘é€�æ•°æ�® å’Œ DFileDragServer é…�å�ˆä½¿ç”¨. \sa Dtk::Gui::DFileDragServer */ /*! \fn void DFileDrag::targetUrlChanged(QUrl url) \brief ä¿¡å�·ä¼šåœ¨æŽ¥æ”¶æ–¹è°ƒç”¨ setTargetUrl 时被å�‘é€�. å�¯ä»¥ç”¨äºŽèŽ·å�–被拖拽至的目标目录 \a url å�‘生改å�˜çš„目标链接. */ DFileDrag::DFileDrag(QObject *source, DFileDragServer *server) : QDrag(source) , DObject(*new DFileDragPrivate(this, server)) { Q_D(DFileDrag); connect(d->srv, &DFileDragServer::targetDataChanged, this, [this, d](const QString &key) { if (key == DND_TARGET_URL_KEY) { Q_EMIT this->targetUrlChanged(QUrl(d->srv->targetData(key).value())); } }); } /*! \brief DFileDrag::targetUrl \return 返回拖拽文件接收方设置的接收路径 */ QUrl DFileDrag::targetUrl() { Q_D(DFileDrag); return QUrl(d->srv->targetData(DND_TARGET_URL_KEY).value()); } /*! \brief DFileDrag::setMimeData \a data \brief å�‘起拖拽文件å‰�设置å�‘é€�æ•°æ�®æŽ¥å�£ */ void DFileDrag::setMimeData(QMimeData *data) { Q_D(DFileDrag); d->srv->d_func()->writeMimeData(data); QDrag::setMimeData(data); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/filedrag/dfiledragclient.cpp000066400000000000000000000160111522615413000212730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dfiledragclient.h" #include "private/dfiledragcommon_p.h" #include #include #include #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE class DDndClientSignalRelay : public QObject { Q_OBJECT public Q_SLOTS: void progressChanged(QString uuid, int progress); void stateChanged(QString uuid, int state); void serverDestroyed(QString uuid); private: static QWeakPointer relayref; friend class DFileDragClient; }; class DFileDragClientPrivate : DCORE_NAMESPACE::DObjectPrivate { explicit DFileDragClientPrivate(DFileDragClient *q) : DCORE_NAMESPACE::DObjectPrivate(q) {} QUuid uuid; QString service; QSharedPointer iface; QSharedPointer relay; static QHash connectionmap; static QHash> ifacemap; D_DECLARE_PUBLIC(DFileDragClient) friend class DDndClientSignalRelay; }; QHash DFileDragClientPrivate::connectionmap; QHash> DFileDragClientPrivate::ifacemap; QWeakPointer DDndClientSignalRelay::relayref; void DDndClientSignalRelay::progressChanged(QString uuid, int progress) { if (DFileDragClientPrivate::connectionmap.contains(uuid)) { Q_EMIT DFileDragClientPrivate::connectionmap[uuid]->progressChanged(progress); } } void DDndClientSignalRelay::stateChanged(QString uuid, int state) { if (DFileDragClientPrivate::connectionmap.contains(uuid)) { Q_EMIT DFileDragClientPrivate::connectionmap[uuid]->stateChanged(static_cast(state)); } } void DDndClientSignalRelay::serverDestroyed(QString uuid) { if (DFileDragClientPrivate::connectionmap.contains(uuid)) { Q_EMIT DFileDragClientPrivate::connectionmap[uuid]->serverDestroyed(); DFileDragClientPrivate::connectionmap[uuid]->deleteLater(); DFileDragClientPrivate::connectionmap.remove(uuid); } } /*! \class Dtk::Gui::DFileDragClient \inmodule dtkgui \brief æ��供拖拽文件时与文件å�‘é€�方交互的接å�£. */ /*! \fn void DFileDragClient::progressChanged(int progress) \a progress 当å‰�进度 \brief ä¿¡å�·ä¼šåœ¨å½“å‰�进度å�˜åŒ–时被å�‘é€�. */ /*! \fn void DFileDragClient::stateChanged(DFileDragState state) \a state 改å�˜å�Žçš„æ–°çжæ€� \brief ä¿¡å�·ä¼šåœ¨å½“å‰�状æ€�å�˜åŒ–时被å�‘é€�. */ /*! \fn void DFileDragClient::serverDestroyed() \brief ä¿¡å�·ä¼šåœ¨å�‘é€�æ–¹æž�构销æ¯�å‰�被å�‘é€�. \note DFileDragClient 收到å�Žä¼šè‡ªåˆ é™¤(deletelater),因此ä¸�用去管ç�† new 出æ�¥çš„ DFileDragClient */ DFileDragClient::DFileDragClient(const QMimeData *data, QObject *parent) : QObject(parent) , DCORE_NAMESPACE::DObject(*new DFileDragClientPrivate(this)) { D_D(DFileDragClient); Q_ASSERT(checkMimeData(data)); d->service = data->data(DND_MIME_SERVICE); d->uuid = QUuid(data->data(DND_MIME_UUID)); d->connectionmap[d->uuid.toString()] = this; if (DDndClientSignalRelay::relayref.isNull()) { d->relay = QSharedPointer(new DDndClientSignalRelay); DDndClientSignalRelay::relayref = d->relay.toWeakRef(); } else { d->relay = DDndClientSignalRelay::relayref.toStrongRef(); } if (!DFileDragClientPrivate::ifacemap.contains(d->service)) { QDBusConnection sessionBus(QDBusConnection::sessionBus()); d->iface = QSharedPointer(new QDBusInterface(d->service, DND_OBJPATH, DND_INTERFACE, sessionBus), [d](QDBusInterface* intf){ QDBusConnection sessionBus(QDBusConnection::sessionBus()); sessionBus.disconnect(d->service, DND_OBJPATH, DND_INTERFACE, "progressChanged", "si", d->relay.data(), SLOT(progressChanged(QString, int))); sessionBus.disconnect(d->service, DND_OBJPATH, DND_INTERFACE, "stateChanged", "si", d->relay.data(), SLOT(stateChanged(QString, int))); sessionBus.disconnect(d->service, DND_OBJPATH, DND_INTERFACE, "serverDestroyed", "s", d->relay.data(), SLOT(serverDestroyed(QString))); intf->deleteLater(); DFileDragClientPrivate::ifacemap.remove(d->service); }); DFileDragClientPrivate::ifacemap[d->service] = d->iface.toWeakRef(); sessionBus.connect(d->service, DND_OBJPATH, DND_INTERFACE, "progressChanged", "si", d->relay.data(), SLOT(progressChanged(QString, int))); sessionBus.connect(d->service, DND_OBJPATH, DND_INTERFACE, "stateChanged", "si", d->relay.data(), SLOT(stateChanged(QString, int))); sessionBus.connect(d->service, DND_OBJPATH, DND_INTERFACE, "serverDestroyed", "s", d->relay.data(), SLOT(serverDestroyed(QString))); } else { d->iface = DFileDragClientPrivate::ifacemap[d->service].toStrongRef(); } } /*! \brief DFileDragClient::progress \return 返回当å‰�拖拽的进度 */ int DFileDragClient::progress() const { D_D(const DFileDragClient); return QDBusReply(d->iface->call("progress", d->uuid.toString())).value(); } /*! \brief DFileDragClient::state \return 返回当å‰�状æ€�,è§� DFileDragState */ DFileDragState DFileDragClient::state() const { D_D(const DFileDragClient); return static_cast(QDBusReply(d->iface->call("state", d->uuid.toString())).value()); } /*! \brief DFileDragClient::checkMimeData \a data \return 包å�« DND_MIME_PID æ ¼å¼�的数æ�®æ—¶è¿”回 true,å�¦åˆ™è¿”回 false \note 通常在接收拖放数æ�®çš„应用的dropEvent(QDropEvent *event)函数中检测当å‰� event->mimeData() 是å�¦æ˜¯ DFileDrag */ bool DFileDragClient::checkMimeData(const QMimeData *data) { return data->hasFormat(DND_MIME_SERVICE) && data->hasFormat(DND_MIME_PID); } /*! \brief DFileDragClient::setTargetData \a data 拖放时传入的data,用于获å�–å’Œå�‘é€�æ•°æ�®çš„应用dbus通讯需è¦�的一些信æ�¯ \a key \a value \note å�‘文件å�‘é€�方设置自定义数æ�® */ void DFileDragClient::setTargetData(const QMimeData *data, QString key, QVariant value) { Q_ASSERT(checkMimeData(data)); QString service(data->data(DND_MIME_SERVICE)); QString uuid(data->data(DND_MIME_UUID)); QDBusInterface iface(service, DND_OBJPATH, DND_INTERFACE, QDBusConnection::sessionBus()); QDBusReply pid = QDBusConnection::sessionBus().interface()->servicePid(service); if (QString::number(pid).toUtf8() != data->data(DND_MIME_PID)) { return; } iface.call("setData", uuid, key, value.toString()); } /*! \brief DFileDragClient::setTargetUrl \a data \a url \note 告知文件å�‘é€�方拖拽目标路径 */ void DFileDragClient::setTargetUrl(const QMimeData *data, QUrl url) { setTargetData(data, DND_TARGET_URL_KEY, QVariant::fromValue(url.toString())); } DGUI_END_NAMESPACE #include "dfiledragclient.moc" dtkgui-6.7.46/src/filedrag/dfiledragserver.cpp000066400000000000000000000121131522615413000213220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dfiledragserver.h" #include "private/dfiledragcommon_p.h" #include #include #include #include #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE class DDndSourceInterface; /*! @private */ class DFileDragServerPrivate : public DCORE_NAMESPACE::DObjectPrivate { QMap data; QUuid uuid; explicit DFileDragServerPrivate(DFileDragServer *q); ~DFileDragServerPrivate(); void writeMimeData(QMimeData *dest); QSharedPointer dbusif; static QHash servermap; static QWeakPointer dbusifinst; D_DECLARE_PUBLIC(DFileDragServer) friend class DDndSourceInterface; }; QWeakPointer DFileDragServerPrivate::dbusifinst; QHash DFileDragServerPrivate::servermap; class DDndSourceInterface : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", DND_INTERFACE) public: explicit DDndSourceInterface(QObject *parent = nullptr) : QObject(parent) {} Q_SIGNALS: void serverDestroyed(QString uuid); void stateChanged(QString uuid, int state); void progressChanged(QString uuid, int progress); public Q_SLOTS: void setData(QString uuid, QString key, QString value) { DFileDragServer *srv = DFileDragServerPrivate::servermap.value(uuid); Q_ASSERT(srv); DFileDragServerPrivate *d = srv->d_func(); if (d->data.value(key) != value) { d->data[key] = value; Q_EMIT srv->targetDataChanged(key); } } int state(QString uuid) const {return m_statemap.value(uuid);} int progress(QString uuid) const {return m_progressmap.value(uuid);} private: QHash m_statemap; QHash m_progressmap; friend class DFileDragServer; }; /*! \class Dtk::Gui::DFileDragServer \inmodule dtkgui \brief æ��供拖拽文件时与文件接收方交互的接å�£. */ /*! \fn void DFileDragServer::targetDataChanged(const QString &key) \brief ä¿¡å�·ä¼šåœ¨æŽ¥æ”¶æ–¹è°ƒç”¨ setData å�˜åŒ–时被å�‘é€�, \a key 为改å�˜çš„键值. */ DFileDragServer::DFileDragServer(QObject *parent) : QObject(parent) , DCORE_NAMESPACE::DObject(*new DFileDragServerPrivate(this)) { D_D(DFileDragServer); DFileDragServerPrivate::servermap[d->uuid.toString()] = this; } DFileDragServer::~DFileDragServer() { D_D(DFileDragServer); Q_EMIT d->dbusif->serverDestroyed(d->uuid.toString()); DFileDragServerPrivate::servermap.remove(d->uuid.toString()); } /*! \brief DFileDragServer::targetData. \a key \return 返回文件接收方设置数æ�® \a key 对应的 value */ QVariant DFileDragServer::targetData(const QString &key) const { D_D(const DFileDragServer); return d->data.value(key); } /*! \brief DFileDragServer::setProgress. \a progress 当å‰�进度 \brief 拖拽进度更新,接收方会å�—到 progressChanged ä¿¡å�·. */ void DFileDragServer::setProgress(int progress) { D_D(DFileDragServer); if (d->dbusif && progress != d->dbusif->m_progressmap.value(d->uuid.toString())) { d->dbusif->m_progressmap[d->uuid.toString()] = progress; Q_EMIT d->dbusif->progressChanged(d->uuid.toString(), progress); } } /*! \brief DFileDragServer::setState. \a state \brief 改å�˜çжæ€�,接收方会å�—到 stateChanged ä¿¡å�·. */ void DFileDragServer::setState(DFileDragState state) { D_D(DFileDragServer); if (d->dbusif && state != d->dbusif->m_statemap.value(d->uuid.toString())) { d->dbusif->m_statemap[d->uuid.toString()] = state; Q_EMIT d->dbusif->stateChanged(d->uuid.toString(), state); } } DFileDragServerPrivate::DFileDragServerPrivate(DFileDragServer *q) : DCORE_NAMESPACE::DObjectPrivate(q) , uuid(QUuid::createUuid()) { if (dbusifinst.isNull()) { dbusif = QSharedPointer(new DDndSourceInterface(), [](DDndSourceInterface *intf){ QDBusConnection::sessionBus().unregisterObject(DND_OBJPATH); intf->deleteLater(); }); dbusifinst = dbusif.toWeakRef(); QDBusConnection::sessionBus().registerObject(DND_OBJPATH, DND_INTERFACE, dbusif.data(), QDBusConnection::RegisterOption::ExportAllContents); } else { dbusif = dbusifinst.toStrongRef(); } } DFileDragServerPrivate::~DFileDragServerPrivate() { } void DFileDragServerPrivate::writeMimeData(QMimeData *dest) { dest->setData(DND_MIME_SERVICE, QDBusConnection::sessionBus().baseService().toUtf8()); // qApp->applicationPid() not right in ll-box auto pid = QDBusConnection::sessionBus().interface()->servicePid(QDBusConnection::sessionBus().baseService()); dest->setData(DND_MIME_PID, QString::number(pid).toUtf8()); dest->setData(DND_MIME_UUID, uuid.toString().toUtf8()); } DGUI_END_NAMESPACE #include "dfiledragserver.moc" dtkgui-6.7.46/src/kernel/000077500000000000000000000000001522615413000151535ustar00rootroot00000000000000dtkgui-6.7.46/src/kernel/dforeignwindow.cpp000066400000000000000000000115001522615413000207010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dforeignwindow.h" #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE #define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name // propertys DEFINE_CONST_CHAR(WmClass); DEFINE_CONST_CHAR(ProcessId); class DForeignWindowPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate { public: explicit DForeignWindowPrivate(DForeignWindow *qq) : DObjectPrivate(qq) {} }; /*! \class Dtk::Gui::DForeignWindow \inmodule dtkgui \brief 一个用于获å�–本地窗å�£ä¿¡æ�¯çš„ç±». 继承于 QWindow,支æŒ� QWindow::geometry QWindow::x QWindow::y QWindow::width QWindow::height QWindow::title QWindow::flags QWindow::visibility QWindow::type QWindow::windowStates QWindow::windowState 等接å�£çš„使用,å�¦å¤–扩展 增加了一部分接å�£ï¼Œæ–¹é�¢æ›´åŠ è¯¦ç»†çš„èŽ·å�–窗å�£ä¿¡æ�¯ã€‚ä¾�赖于 dxcb æ�’件,在未加载 dxcb æ�’件的应用中使用时结果未知 \sa DWindowManagerHelper::currentWorkspaceWindows \sa Dtk::Widget::DApplication::loadDXcbPlugin \sa Dtk::Widget::DApplication::isDXcbPlatform */ /*! \property DForeignWindow::wmClass \brief 窗å�£ WM_CLASS 的值 \note å�ªè¯» \ref {https://tronche.com/gui/x/icccm/sec-4.html#WM_CLASS}{WM_CLASS} */ /*! \property DForeignWindow::pid \brief 窗å�£æ‰€å±žè¿›ç¨‹çš„ pid \note å�ªè¯» \ref {https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html}{_NET_WM_PID} */ /*! \fn void DForeignWindow::wmClassChanged() \brief ä¿¡å�·ä¼šåœ¨ wmClass 属性改å�˜æ—¶è¢«å�‘é€�. \sa DForeignWindow::wmClass */ /*! \fn void DForeignWindow::pidChanged() \brief ä¿¡å�·ä¼šåœ¨ pid 属性的值改å�˜æ—¶è¢«å�‘é€�. \sa DForeignWindow::pid */ /*! \brief 直接构造一个 DForeignWindow 对象和使用 QWindow 对象没有区别. \a parent \sa DForeignWindow::fromWinId */ DForeignWindow::DForeignWindow(QWindow *parent) : QWindow(parent) , DObject(*new DForeignWindowPrivate(this)) { } /*! \brief DForeignWindow::fromWinId. 使用这个窗å�£id创建一个 DForeignWindow 对象,此对象ä¸�会被加到 QGuiApplication::allWindows 中。一般应用在需è¦�获å�–一个本地窗å�£ä¿¡æ�¯çš„场景。示例: \code // a.cpp int main(int argc, char *argv[]) { DApplication a(argc, argv); QWidget w; w.setWindowTitle("deepin"); w.show(); QFile app_win_id("/tmp/window_id.txt"); if (app_win_id.open(QFile::WriteOnly)) { app_win_id.write(QByteArray::number(w.winId())); app_win_id.close(); } return a.exec(); } \endcode \code // b.cpp int main(int argc, char *argv[]) { DApplication::loadDXcbPlugin(); DApplication a(argc, argv); DForeignWindow *fw = nullptr; QFile app_win_id("/tmp/window_id.txt"); if (app_win_id.open(QFile::ReadOnly)) { fw = DForeignWindow::fromWinId(app_win_id.readAll().toInt()); } if (fw) { qDebug() << fw->title(); fw->connect(fw, &DForeignWindow::widthChanged, [&] { qDebug() << fw->width(); }); } return a.exec(); } \endcode å…ˆå�¯åŠ¨åº”ç”¨ a å†�å�¯åŠ¨åº”ç”¨ b 在应用 b å�¯åЍå�Žå°†çœ‹åˆ°å¦‚下输出: \code "deepin" \endcode 当改å�˜åº”用 a 中的窗å�£å®½åº¦æ—¶ï¼Œåœ¨åº”用 b 中会看到宽度的输出 \a id \return \warning ä¸�è¦�å°�试对由本应用创建的窗å�£è°ƒç”¨æ­¤æŽ¥å�£ï¼Œå�¯èƒ½ä¼šå¯¼è‡´çª—å�£è¡Œä¸ºå�‘生ä¸�å�¯é€†è½¬çš„å�˜åŒ– */ DForeignWindow *DForeignWindow::fromWinId(WId id) { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ForeignWindows)) { qWarning() << "DForeignWindow::fromWinId(): platform plugin does not support foreign windows."; return 0; } DForeignWindow *window = new DForeignWindow; window->setFlags(Qt::ForeignWindow); window->setProperty("_q_foreignWinId", QVariant::fromValue(id)); window->create(); return window; } QString DForeignWindow::wmClass() const { return property(_WmClass).toString(); } quint32 DForeignWindow::pid() const { return qvariant_cast(property(_ProcessId)); } bool DForeignWindow::event(QEvent *e) { if (e->type() == QEvent::DynamicPropertyChange) { QDynamicPropertyChangeEvent *event = static_cast(e); if (event->propertyName() == _WmClass) { Q_EMIT wmClassChanged(); return true; } else if (event->propertyName() == _ProcessId) { Q_EMIT pidChanged(); return true; } } return QWindow::event(e); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/kernel/dguiapplicationhelper.cpp000066400000000000000000002062551522615413000222450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dguiapplicationhelper.h" #include "private/dguiapplicationhelper_p.h" #include "dplatformhandle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #include #include #endif #include #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #include #include #include #endif #include #include #include #include #ifdef Q_OS_LINUX #include #include #include #endif #include "orgdeepindtkpreference.hpp" #ifdef Q_OS_UNIX class EnvReplaceGuard { public: EnvReplaceGuard(const int uid); ~EnvReplaceGuard(); char *m_backupLogName; char *m_backupHome; bool initialized = false; }; EnvReplaceGuard::EnvReplaceGuard(const int uid) { if (struct passwd *pwd = getpwuid(static_cast<__uid_t>(uid))) { m_backupLogName = getenv("LOGNAME"); m_backupHome = getenv("HOME"); setenv("LOGNAME", pwd->pw_name, 1); setenv("HOME", pwd->pw_dir, 1); initialized = true; } } EnvReplaceGuard::~EnvReplaceGuard() { if (initialized) { setenv("LOGNAME", m_backupLogName, 1); setenv("HOME", m_backupHome, 1); } } #endif DGUI_BEGIN_NAMESPACE #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) using HelperCreator = DGuiApplicationHelper::HelperCreator; #else using HelperCreator = DGuiApplicationHelper *(*)(); #endif #ifdef QT_DEBUG Q_LOGGING_CATEGORY(dgAppHelper, "dtk.dguihelper") #else Q_LOGGING_CATEGORY(dgAppHelper, "dtk.dguihelper", QtInfoMsg) #endif Q_GLOBAL_STATIC(QLocalServer, _d_singleServer) // Protocol changelog: // v1: version + pid + arguments // v2: version + pid + arguments + envs (KEY=VALUE pairs, filtered by whitelist) static quint8 _d_singleServerVersion = 2; Q_GLOBAL_STATIC(DFontManager, _globalFM) #define WINDOW_THEME_KEY "_d_platform_theme" #define DTK_ANIMATIONS_ENV "D_DTK_DISABLE_ANIMATIONS" #define DTK_DISABLE_INWINDOWBLUR_ENV "D_DTK_DISABLE_INWINDOWBLUR" Q_GLOBAL_STATIC_WITH_ARGS(OrgDeepinDTKPreference, _d_dconfig, (DTK_CORE_NAMESPACE::DConfig::globalThread(), nullptr, "org.deepin.dtk.preference", DTK_CORE_NAMESPACE::DSGApplication::id(), {}, false, nullptr)) // Keys allowed to be forwarded between single-instance client and server. static const QStringList s_singleInstanceForwardEnvKeys = { QStringLiteral("XDG_ACTIVATION_TOKEN") }; // Returns a filtered env list in KEY=VALUE format based on the allowed key list. static QStringList filteredSingleInstanceEnvs() { QStringList result; result.reserve(s_singleInstanceForwardEnvKeys.size()); for (const QString &key : s_singleInstanceForwardEnvKeys) { // Use qgetenv directly to avoid constructing a full QProcessEnvironment const QByteArray value = qgetenv(key.toLocal8Bit().constData()); if (!value.isNull()) result << key + QLatin1Char('=') + QString::fromLocal8Bit(value); } return result; } /*! @private */ class _DGuiApplicationHelper { public: #define INVALID_HELPER reinterpret_cast(1) inline DGuiApplicationHelper *helper() { // 临时存储一个无效的指针值, 用于此处æ�¡ä»¶å�˜é‡�的竞争 if (m_helper.testAndSetRelaxed(nullptr, INVALID_HELPER)) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) m_helper.storeRelaxed(creator()); m_helper.loadRelaxed()->initialize(); } return m_helper.loadRelaxed(); #else m_helper.store(creator()); m_helper.load()->initialize(); } return m_helper.load(); #endif } inline void clear() { if (m_helper != INVALID_HELPER) delete m_helper.fetchAndStoreRelaxed(nullptr); } static DGuiApplicationHelper *defaultCreator() { return new DGuiApplicationHelper(); } QAtomicPointer m_helper; static HelperCreator creator; }; class LoadManualServiceWorker : public QThread { public: explicit LoadManualServiceWorker(QObject *parent = nullptr); ~LoadManualServiceWorker() override; void checkManualServiceWakeUp(); protected: void run() override; }; LoadManualServiceWorker::LoadManualServiceWorker(QObject *parent) : QThread(parent) { if (!parent) connect(qApp, &QGuiApplication::aboutToQuit, this, std::bind(&LoadManualServiceWorker::exit, this, 0)); } LoadManualServiceWorker::~LoadManualServiceWorker() { } void LoadManualServiceWorker::run() { QDBusInterface("com.deepin.Manual.Search", "/com/deepin/Manual/Search", "com.deepin.Manual.Search"); } void LoadManualServiceWorker::checkManualServiceWakeUp() { if (this->isRunning()) return; start(); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) class Q_DECL_HIDDEN GuiApplicationEventFilter : public QObject { public: explicit GuiApplicationEventFilter(DGuiApplicationHelperPrivate *transmitter, QObject *parent = nullptr) : QObject(parent) , m_transmitter(transmitter) { } virtual bool eventFilter(QObject *watched, QEvent *event) override { if (watched != qApp) return QObject::eventFilter(watched, event); switch(event->type()) { case QEvent::ApplicationFontChange: { const QFont font(qGuiApp->font()); m_transmitter->q_func()->fontChanged(font); } break; case QEvent::ApplicationPaletteChange: { m_transmitter->onApplicationPaletteChanged(); break; } default: break; } return QObject::eventFilter(watched, event); } private: DGuiApplicationHelperPrivate *m_transmitter = nullptr; }; #endif HelperCreator _DGuiApplicationHelper::creator = _DGuiApplicationHelper::defaultCreator; Q_GLOBAL_STATIC(_DGuiApplicationHelper, _globalHelper) int DGuiApplicationHelperPrivate::waitTime = 3000; DGuiApplicationHelper::Attributes DGuiApplicationHelperPrivate::attributes = DGuiApplicationHelper::UseInactiveColorGroup; static const DGuiApplicationHelper::SizeMode InvalidSizeMode = static_cast(-1); DGuiApplicationHelperPrivate::DGuiApplicationHelperPrivate(DGuiApplicationHelper *qq) : DObjectPrivate(qq) , explicitSizeMode(InvalidSizeMode) { } void DGuiApplicationHelperPrivate::init() { if (qGuiApp) { initApplication(qGuiApp); } else { // ç¡®ä¿�qAddPreRoutineå�ªä¼šè¢«è°ƒç”¨ä¸€æ¬¡ static auto _ = [] {qAddPreRoutine(staticInitApplication); return true;}(); Q_UNUSED(_) } } void DGuiApplicationHelperPrivate::initApplication(QGuiApplication *app) { D_Q(DGuiApplicationHelper); if (!systemTheme) { // 需è¦�在QGuiApplication创建å�Žå†�创建DPlatformTheme,å�¦åˆ™DPlatformTheme无效. // qGuiApp->platformFunction()会报警告,并返回nullptr. systemTheme = new DPlatformTheme(0, q); // 直接对应到系统级别的主题, ä¸�å†�对外æ��供为æŸ�个å�•独程åº�设置主题的接å�£. // 程åº�设置自身主题相关的东西皆å�¯é€šè¿‡ setPaletteType å’Œ setApplicationPalette 实现. appTheme = systemTheme; } // è·Ÿéš�application销æ¯� qAddPostRoutine(staticCleanApplication); // 转å�‘程åº�自己å�˜åŒ–的信å�· #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) app->installEventFilter(new GuiApplicationEventFilter(this, app)); #else q->connect(app, &QGuiApplication::fontChanged, q, &DGuiApplicationHelper::fontChanged); q->connect(app, &QGuiApplication::paletteChanged, q, [this] { onApplicationPaletteChanged(); }); #endif if (Q_UNLIKELY(!appTheme)) { // 此时说明appThemeå�¯èƒ½å·²ç»�被åˆ�始化为了systemtheme if (QGuiApplicationPrivate::is_app_running) { _q_initApplicationTheme(); } else { // å»¶å�Žåˆ�始化数æ�®ï¼Œå› ä¸ºåœ¨è°ƒç”¨ clientLeader å‰�å¿…é¡»è¦�ä¿�è¯�QGuiApplicationå·²ç»�完全构造完æˆ� q->metaObject()->invokeMethod(q, "_q_initApplicationTheme", Qt::QueuedConnection, Q_ARG(bool, true)); } } else if (appTheme == systemTheme) { // 此时appTheme等价于systemTheme, å�¯ä»¥ç›´æŽ¥ä¿¡å�·é“¾æŽ¥ _q_initApplicationTheme(); } systemSizeMode = static_cast(systemTheme->sizeMode()); q->connect(systemTheme, SIGNAL(sizeModeChanged(int)), q, SLOT(_q_sizeModeChanged(int))); } void DGuiApplicationHelperPrivate::staticInitApplication() { if (!_globalHelper.exists()) return; if (DGuiApplicationHelper *helper = _globalHelper->helper()) helper->d_func()->initApplication(qGuiApp); } void DGuiApplicationHelperPrivate::staticCleanApplication() { if (_globalHelper.exists()) _globalHelper->clear(); } DPlatformTheme *DGuiApplicationHelperPrivate::initWindow(QWindow *window) const { DPlatformTheme *theme = new DPlatformTheme(window->winId(), q_func()->applicationTheme()); window->setProperty(WINDOW_THEME_KEY, QVariant::fromValue(theme)); theme->setParent(window); // è·Ÿéš�窗å�£é”€æ¯� auto onWindowThemeChanged = [window, this] { // 如果程åº�自定义了调色æ�¿, 则没有必è¦�å†�关心窗å�£è‡ªèº«å¹³å�°ä¸»é¢˜çš„å�˜åŒ– // 需è¦�注æ„�的是, 这里的信å�·å’Œäº‹ä»¶å�¯èƒ½ä¼šä¸Ž notifyAppThemeChanged 中的é‡�å¤� // 但是ä¸�能因此而移除这里的通知, 当窗å�£è‡ªèº«æ‰€å¯¹åº”的平å�°ä¸»é¢˜å�‘生å�˜åŒ–æ—¶, 这里 // 的通知机制就有了用武之地. if (Q_LIKELY(!isCustomPalette())) { qGuiApp->postEvent(window, new QEvent(QEvent::ThemeChange)); } }; window->connect(theme, &DPlatformTheme::themeNameChanged, window, onWindowThemeChanged); window->connect(theme, &DPlatformTheme::activeColorChanged, window, onWindowThemeChanged); window->connect(theme, &DPlatformTheme::paletteChanged, window, onWindowThemeChanged); return theme; } void DGuiApplicationHelperPrivate::_q_initApplicationTheme(bool notifyChange) { if (!appTheme) { // DPlatfromHandle::windowLeaderä¾�èµ–platformIntegration Q_ASSERT(QGuiApplicationPrivate::platformIntegration()); appTheme = new DPlatformTheme(DPlatformHandle::windowLeader(), systemTheme); } QGuiApplication *app = qGuiApp; auto onAppThemeChanged = [this] { // å�ªæœ‰å½“程åº�未自定义调色æ�¿æ—¶æ‰�需è¦�关心DPlatformTheme中themeNameå’Œpalette的改å�˜ if (!isCustomPalette()) notifyAppThemeChanged(); }; // 监å�¬ä¸Žç¨‹åº�主题相关的改å�˜ QObject::connect(appTheme, &DPlatformTheme::themeNameChanged, app, onAppThemeChanged); QObject::connect(appTheme, &DPlatformTheme::paletteChanged, app, onAppThemeChanged); QTimer *timer = new QTimer(app); timer->setInterval(100); timer->setSingleShot(true); QObject::connect(timer, &QTimer::timeout, timer, [this] { if (!appPalette) notifyAppThemeChanged(); }); QObject::connect(appTheme, &DPlatformTheme::activeColorChanged, app, [timer]{ timer->start(); }); QObject::connect(appTheme, &DPlatformTheme::darkActiveColorChanged, app, [timer] { timer->start(); }); // appTheme在此之å‰�å�¯èƒ½ç”±systemTheme所代替被使用,此时在创建appTheme // å¹¶åˆ�始化之å�Žï¼Œåº”当å�‘é€�ä¿¡å�·é€šçŸ¥ç¨‹åº�主题的改å�˜ if (notifyChange && appTheme->isValid()) { notifyAppThemeChanged(); } } void DGuiApplicationHelperPrivate::notifyAppThemeChanged() { D_Q(DGuiApplicationHelper); notifyAppThemeChangedByEvent(); QMetaObject::invokeMethod(q, [q] () { // 通知主题类型å�‘生å�˜åŒ–, 此处å�¯èƒ½å­˜åœ¨è¯¯æŠ¥çš„行为, ä¸�过ä¸�应该对此å�šé¢�外的约æ�Ÿ // 此信å�·çš„行为应当等价于 applicationPaletteChanged Q_EMIT q->themeTypeChanged(q->themeType()); // 通知调色æ�¿å¯¹è±¡çš„æ”¹å�˜ Q_EMIT q->applicationPaletteChanged(); }, Qt::QueuedConnection); } void DGuiApplicationHelperPrivate::notifyAppThemeChangedByEvent() { // https://github.com/qt/qtbase/commit/68a9c5fe513e147e4cffd29b50a4714813df411e #if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0) QWindowSystemInterfacePrivate::ThemeChangeEvent event; #else QWindowSystemInterfacePrivate::ThemeChangeEvent event(nullptr); #endif // 此事件会促使QGuiApplicationé‡�新从QPlatformTheme中获å�–系统级别的QPalette. // 而在deepinå¹³å�°ä¸‹, 系统级别的QPaletteæ�¥æº�自 \a applicationPalette() QGuiApplicationPrivate::processThemeChanged(&event); } void DGuiApplicationHelperPrivate::onApplicationPaletteChanged() { D_Q(DGuiApplicationHelper); // 如果用户没有自定义颜色类型, 则应该通知程åº�的颜色类型å�‘é€�å�˜åŒ– if (Q_LIKELY(!isCustomPalette())) { Q_EMIT q->themeTypeChanged(q->toColorType(qGuiApp->palette())); Q_EMIT q->applicationPaletteChanged(); } else { qWarning() << "DGuiApplicationHelper: Don't use QGuiApplication::setPalette on DTK application."; } } bool DGuiApplicationHelperPrivate::isCustomPalette() const { return appPalette || paletteType != DGuiApplicationHelper::UnknownType; } void DGuiApplicationHelperPrivate::setPaletteType(DGuiApplicationHelper::ColorType ct, bool emitSignal) { if (paletteType == ct) return; if (qGuiApp && qGuiApp->testAttribute(Qt::AA_SetPalette)) qWarning() << "DGuiApplicationHelper: Plase check 'QGuiApplication::setPalette'," " Don't use it on DTK application."; paletteType = ct; if (!emitSignal) { notifyAppThemeChangedByEvent(); return; } // 如果未固定调色æ�¿, 则paletteTypeçš„å�˜åŒ–å�¯èƒ½ä¼šå¯¼è‡´è°ƒè‰²æ�¿æ”¹å�˜, 应当通知程åº�æ›´æ–°æ•°æ�® if (!appPalette) notifyAppThemeChanged(); D_Q(DGuiApplicationHelper); Q_EMIT q->paletteTypeChanged(paletteType); } void DGuiApplicationHelperPrivate::initPaletteType() const { DCORE_USE_NAMESPACE if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::DontSaveApplicationTheme)) return; if (paletteTypeInited) return; const_cast(this)->paletteTypeInited = true; auto applyThemeType = [this](bool emitSignal){ int ct = _d_dconfig->themeType(); if (ct > DGuiApplicationHelper::DarkType || ct < DGuiApplicationHelper::UnknownType) ct = DGuiApplicationHelper::UnknownType; const_cast(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), emitSignal); }; // 读å�–é…�置文件中的主题类型并立å�³åº”用 DTK_CORE_NAMESPACE::DConfig dconfig("org.deepin.dtk.preference"); int ct = dconfig.value("themeType", DGuiApplicationHelper::UnknownType).toInt(); const_cast(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), false); QObject::connect(_d_dconfig.operator ()(), &OrgDeepinDTKPreference::themeTypeChanged, q_func(), [applyThemeType] { applyThemeType(true); }); } void DGuiApplicationHelperPrivate::_q_sizeModeChanged(int mode) { D_Q(DGuiApplicationHelper); qCInfo(dgAppHelper) << "Receiving that system size mode is set to [" << static_cast(mode) << "], and old system size mode is [" << systemSizeMode << "]"; const auto oldSizeMode = fetchSizeMode(); systemSizeMode = static_cast(mode); const auto currentSizeMode = fetchSizeMode(); if (oldSizeMode != currentSizeMode) Q_EMIT q->sizeModeChanged(currentSizeMode); } DGuiApplicationHelper::SizeMode DGuiApplicationHelperPrivate::fetchSizeMode(bool *isSystemSizeMode) const { if (isSystemSizeMode) *isSystemSizeMode = false; // `setSizeMode` > `D_DTK_SIZEMODE` > `systemSizeMode` if (explicitSizeMode != InvalidSizeMode) return explicitSizeMode; static const QString envSizeMode(qEnvironmentVariable("D_DTK_SIZEMODE")); if (!envSizeMode.isEmpty()) { bool ok = false; const auto mode = envSizeMode.toInt(&ok); if (ok) return static_cast(mode); } if (isSystemSizeMode) *isSystemSizeMode = true; return systemSizeMode; } /*! \class Dtk::Gui::DGuiApplicationHelper \inmodule dtkgui \brief DGuiApplicationHelper 应用程åº�çš„ GUI ,如主题ã€�调色æ�¿ç­‰. */ /*! \enum DGuiApplicationHelper::ColorType DGuiApplicationHelper::ColorType 定义了主题类型. \var DGuiApplicationHelper::ColorType DGuiApplicationHelper::UnknownType 未知主题(浅色主题或深色主题) \var DGuiApplicationHelper::ColorType DGuiApplicationHelper::LightType 浅色主题 \var DGuiApplicationHelper::ColorType DGuiApplicationHelper::DarkType 深色主题 */ /*! \enum DGuiApplicationHelper::Attribute DGuiApplicationHelper::Attribute 定义了功能属性 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::UseInactiveColorGroup 如果开å�¯ï¼Œå½“窗å�£å¤„于Inactive状æ€�时就会使用QPalette::Inactive的颜色,å�¦åˆ™çª—å�£å°†æ²¡æœ‰ä»»ä½•颜色å�˜åŒ–。 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ColorCompositing 是å�¦é‡‡ç”¨å�Šé€�明样å¼�的调色æ�¿ã€‚ \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ReadOnlyLimit 区分å�ªè¯»æžšä¸¾ã€‚ \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinPlatformTheme 获å�–当å‰�是å�¦ä½¿ç”¨deepinçš„platformthemeæ�’件,platformthemeæ�’ä»¶å�¯ä»¥ä¸ºQt程åº�æ��供特定的控件样å¼�,默认使用chameleon主题。 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDXcbPlatform 获å�–当å‰�使用的是ä¸�是dtkçš„xcb窗å�£æ�’件,dxcbæ�’ä»¶æ��供了窗å�£åœ†è§’和阴影功能。 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsXWindowPlatform 获å�–当å‰�是å�¦è¿�行在X11环境中。 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsTableEnvironment 获å�–当å‰�是å�¦è¿�行在deepinå¹³æ�¿çŽ¯å¢ƒä¸­ï¼Œæ£€æµ‹XDG_CURRENT_DESKTOP环境å�˜é‡�是ä¸�是tablet结尾。 \var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinEnvironment 获å�–当å‰�是å�¦è¿�行在deepin桌é�¢çŽ¯å¢ƒä¸­ï¼Œæ£€æµ‹XDG_CURRENT_DESKTOP环境å�˜é‡�是ä¸�是deepin。 */ DGuiApplicationHelper::DGuiApplicationHelper() : QObject(nullptr) , DObject(*new DGuiApplicationHelperPrivate(this)) { } void DGuiApplicationHelper::initialize() { D_D(DGuiApplicationHelper); d->init(); } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief 创建 DGuiApplicationHelper 对象. \param creator 函数指针 \note 一定è¦�先调用此函数,å†�使用 DGuiApplicationHelper::instance() */ void DGuiApplicationHelper::registerInstanceCreator(DGuiApplicationHelper::HelperCreator creator) { if (creator == _DGuiApplicationHelper::creator) return; _DGuiApplicationHelper::creator = creator; if (_globalHelper.exists()) { _globalHelper->clear(); } } #endif inline static int adjustColorValue(int base, qint8 increment, int max = 255) { return increment > 0 ? (max - base) * increment / 100.0 + base : base * (1 + increment / 100.0); } /*! \brief DGuiApplicationHelper::instance返回 DGuiApplicationHelper 对象 \return DGuiApplicationHelper对象 */ DGuiApplicationHelper *DGuiApplicationHelper::instance() { return _globalHelper->helper(); } DGuiApplicationHelper::~DGuiApplicationHelper() { _globalHelper->m_helper = nullptr; } static inline QColor adjustHSLColor(const QColor &base, qint8 hueFloat, qint8 saturationFloat, qint8 lightnessFloat, qint8 alphaFloat = 0) { if (Q_LIKELY(hueFloat || saturationFloat || lightnessFloat || alphaFloat)) { // 按HSLæ ¼å¼�调整 int H, S, L, A; base.getHsl(&H, &S, &L, &A); H = H > 0 ? adjustColorValue(H, hueFloat, 359) : H; S = adjustColorValue(S, saturationFloat); L = adjustColorValue(L, lightnessFloat); return QColor::fromHsl(H, S, L, A); } return base; } static inline QColor adjustRGBColor(const QColor &base, qint8 redFloat, qint8 greenFloat, qint8 blueFloat, qint8 alphaFloat = 0) { if (Q_LIKELY(redFloat || greenFloat || blueFloat || alphaFloat)) { // 按RGBæ ¼å¼�调整 int R, G, B, A; base.getRgb(&R, &G, &B, &A); R = adjustColorValue(R, redFloat); G = adjustColorValue(G, greenFloat); B = adjustColorValue(B, blueFloat); A = adjustColorValue(A, alphaFloat); return QColor(R, G, B, A); } return base; } /*! \brief 调整颜色. \note å�–值范围å�‡ä¸º -100 ~ 100 ,当三原色å�‚数为-100时,颜色为黑色,å�‚数为100时,颜色为白色. 以é€�明度( alphaFloat )为例,当å�‚数为负数时基础色的 alphaFloat 值å‡�少,现象å��å�‘é€�明, å�‚数为正数alphaFloat 值增加,现象å��ä¸�é€�明 \param base 基础色 \param hueFloat 色调 \param saturationFloat 饱和度 \param lightnessFloat 亮度 \param redFloat 红色 \param greenFloat 绿色 \param blueFloat è“�色 \param alphaFloat Alpha通é�“(é€�明度) \return ç»�过调整的颜色 */ QColor DGuiApplicationHelper::adjustColor(const QColor &base, qint8 hueFloat, qint8 saturationFloat, qint8 lightnessFloat, qint8 redFloat, qint8 greenFloat, qint8 blueFloat, qint8 alphaFloat) { if (Q_UNLIKELY(!base.isValid())) return base; // First do the adjust of spec of this color, Avoid precision loss caused by color spec conversion. if (Q_UNLIKELY(base.spec() == QColor::Hsl)) { QColor newColor = adjustHSLColor(base, hueFloat, saturationFloat, lightnessFloat, alphaFloat); return adjustRGBColor(newColor, redFloat, greenFloat, blueFloat); } // For other specs, first do RGB adjust QColor newColor = adjustRGBColor(base, redFloat, greenFloat, blueFloat, alphaFloat); return adjustHSLColor(newColor, hueFloat, saturationFloat, lightnessFloat); } /*! \brief 调整图片整体åƒ�素颜色. \note å�–值范围å�‡ä¸º -100 ~ 100 ,当三原色å�‚数为-100时,颜色为黑色,å�‚数为100时,颜色为白色. 以é€�明度( alphaFloat )为例,当å�‚数为负数时基础色的 alphaFloat 值å‡�少,现象å��å�‘é€�明, å�‚数为正数alphaFloat 值增加,现象å��ä¸�é€�明 \param base 基础色 \param hueFloat 色调 \param saturationFloat 饱和度 \param lightnessFloat 亮度 \param redFloat 红色 \param greenFloat 绿色 \param blueFloat è“�色 \param alphaFloat Alpha通é�“(é€�明度) \return ç»�过调整的图片 */ QImage DGuiApplicationHelper::adjustColor(const QImage &base, qint8 hueFloat, qint8 saturationFloat, qint8 lightnessFloat, qint8 redFloat, qint8 greenFloat, qint8 blueFloat, qint8 alphaFloat) { if (base.isNull()) return base; if (!hueFloat && !saturationFloat && !lightnessFloat && !redFloat && !greenFloat && !blueFloat && !alphaFloat) return base; QImage dest = base; for (int y = 0; y < dest.height(); ++y) { const QRgb *rgb = reinterpret_cast(base.scanLine(y)); for (int x = 0; x < dest.width(); ++x) { QColor base = QColor::fromRgba(rgb[x]); if (base.alpha() == 0) continue; QColor color = adjustColor(base, hueFloat, saturationFloat, lightnessFloat, redFloat, greenFloat, blueFloat, alphaFloat); dest.setPixel(x, y, color.rgba()); } } return dest; } /*! \brief 将两ç§�颜色混å�ˆï¼Œå�ˆæˆ�新的颜色. \param substrate 底层颜色 \param superstratum 上层颜色 \return æ··å�ˆé¢œè‰² */ QColor DGuiApplicationHelper::blendColor(const QColor &substrate, const QColor &superstratum) { QColor c2 = superstratum.toRgb(); if (c2.alpha() >= 255) return c2; QColor c1 = substrate.toRgb(); qreal c1_weight = 1 - c2.alphaF(); int r = c1_weight * c1.red() + c2.alphaF() * c2.red(); int g = c1_weight * c1.green() + c2.alphaF() * c2.green(); int b = c1_weight * c1.blue() + c2.alphaF() * c2.blue(); return QColor(r, g, b, c1.alpha()); } static QColor light_qpalette[QPalette::NColorRoles] { QColor(0, 0, 0, 0.7 * 255), //WindowText QColor("#e5e5e5"), //Button QColor("#e6e6e6"), //Light QColor("#e5e5e5"), //Midlight QColor("#e3e3e3"), //Dark QColor("#e4e4e4"), //Mid QColor(0, 0, 0, 0.7 * 255), //Text Qt::black, //BrightText QColor(0, 0, 0, 0.7 * 255), //ButtonText Qt::white, //Base QColor("#f8f8f8"), //Window QColor(0, 0, 0, 0.05 * 255), //Shadow QColor("#0081ff"), //Highlight Qt::white, //HighlightedText QColor("#0082fa"), //Link QColor("#ad4579"), //LinkVisited QColor(0, 0, 0, 0.03 * 255), //AlternateBase Qt::white, //NoRole QColor(255, 255, 255, 0.8 * 255), //ToolTipBase QColor(0, 0, 0, 0.85 * 255) //ToolTipText }; static QColor dark_qpalette[QPalette::NColorRoles] { QColor(255, 255, 255, 0.7 * 255), //WindowText QColor("#444444"), //Button QColor("#484848"), //Light QColor("#474747"), //Midlight QColor("#414141"), //Dark QColor("#434343"), //Mid QColor(255, 255, 255, 0.7 * 255), //Text Qt::white, //BrightText QColor(255, 255, 255, 0.7 * 255), //ButtonText QColor("#282828"), //Base QColor("#252525"), //Window QColor(0, 0, 0, 0.05 * 255), //Shadow QColor("#024CCA"), //Highlight QColor("#F1F6FF"), //HighlightedText QColor("#0082fa"), //Link QColor("#ad4579"), //LinkVisited QColor(0, 0, 0, 0.05 * 255), //AlternateBase Qt::black, //NoRole QColor(45, 45, 45, 0.8 * 255), //ToolTipBase QColor(255, 255, 255, 0.85 * 255) //ToolTipText }; static QColor light_dpalette[DPalette::NColorTypes] { QColor(), //NoType QColor(0, 0, 0, 255 * 0.03), //ItemBackground QColor(0, 0, 0, 0.85 * 255), //TextTitle QColor(0, 0, 0, 0.6 * 255), //TextTips QColor("#FF5736"), //TextWarning Qt::black, //TextLively QColor("#0081FF"), //LightLively QColor("#0081FF"), //DarkLively QColor(0, 0, 0, 0.05 * 255), //FrameBorder QColor(85, 85, 85, 0.4 * 255), //PlaceholderText QColor(0, 0, 0, 0.1 * 255), //FrameShadowBorder QColor(0, 0, 0, 0.1 * 255) //ObviousBackground }; static QColor dark_dpalette[DPalette::NColorTypes] { QColor(), //NoType QColor(255, 255, 255, 255 * 0.05), //ItemBackground QColor(255, 255, 255, 0.85 * 255), //TextTitle QColor(255, 255, 255, 0.6 * 255), //TextTips QColor("#E43F2E"), //TextWarning Qt::white, //TextLively QColor("#0059d2"), //LightLively QColor("#0059d2"), //DarkLively QColor(255, 255, 255, 0.1 * 255), //FrameBorder QColor(192, 198, 212, 0.4 * 255), //PlaceholderText QColor(0, 0, 0, 0.8 * 255), //FrameShadowBorder QColor(255, 255, 255, 0.1 * 255) //ObviousBackground }; /*! \brief æ ¹æ�®ä¸»é¢˜èŽ·å�–标准调色æ�¿. \param type 主题枚举值 \return 调色æ�¿ */ DPalette DGuiApplicationHelper::standardPalette(DGuiApplicationHelper::ColorType type) { static const DPalette *light_palette = nullptr, *dark_palette = nullptr; static const DPalette *alpha_light_palette = nullptr, *alpha_dark_palette = nullptr; const bool allowCompositingColor = DGuiApplicationHelper::testAttribute(ColorCompositing); if (type == LightType) { if (Q_UNLIKELY(allowCompositingColor)) { if (Q_LIKELY(alpha_light_palette)) { return *alpha_light_palette; } } if (Q_LIKELY(light_palette)) { return *light_palette; } } else if (type == DarkType) { if (Q_UNLIKELY(allowCompositingColor)) { if (Q_LIKELY(alpha_dark_palette)) { return *alpha_dark_palette; } } if (Q_LIKELY(dark_palette)) { return *dark_palette; } } else { return DPalette(); } DPalette *pa; const QColor *qcolor_list, *dcolor_list; if (type == DarkType) { pa = new DPalette(); if (allowCompositingColor) alpha_dark_palette = pa; else dark_palette = pa; qcolor_list = dark_qpalette; dcolor_list = dark_dpalette; } else { pa = new DPalette(); if (allowCompositingColor) alpha_light_palette = pa; else light_palette = pa; qcolor_list = light_qpalette; dcolor_list = light_dpalette; } for (int i = 0; i < DPalette::NColorRoles; ++i) { QPalette::ColorRole role = static_cast(i); QColor color = qcolor_list[i]; #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) if (role == QPalette::PlaceholderText) { color = dcolor_list[DPalette::PlaceholderText]; } #endif // 处ç�†å�Šé€�明色 if (allowCompositingColor) { switch (role) { case QPalette::Window: color = type == LightType ? adjustColor(color, 0, 0, 0, 0, 0, 0, -20) : adjustColor(color, 0, 0, -10, 0, 0, 0, -20); break; case QPalette::Base: color = adjustColor(color, 0, 0, 0, 0, 0, 0, -20); break; case QPalette::WindowText: case QPalette::Text: color = adjustColor(color, 0, 0, type == LightType ? -20 : +20, 0, 0, 0, -20); break; case QPalette::ButtonText: color = type == LightType ? adjustColor(color, 0, 0, -20, 0, 0, 0, -20) : adjustColor(color, 0, 0, +20, 0, 0, 0, 0); break; case QPalette::Button: case QPalette::Light: case QPalette::Mid: case QPalette::Midlight: case QPalette::Dark: color = adjustColor(color, 0, 0, -20, 0, 0, 0, -40); break; default: break; } } pa->setColor(DPalette::Active, role, color); generatePaletteColor(*pa, role, type); } for (int i = 0; i < DPalette::NColorTypes; ++i) { DPalette::ColorType role = static_cast(i); QColor color = dcolor_list[i]; // 处ç�†å�Šé€�明色 if (allowCompositingColor) { switch (role) { case DPalette::ItemBackground: color = adjustColor(color, 0, 0, 100, 0, 0, 0, type == LightType ? -80 : -90); break; case DPalette::TextTitle: color = adjustColor(color, 0, 0, -20, 0, 0, 0, -20); break; case DPalette::TextTips: color = type == LightType ? adjustColor(color, 0, 0, -40, 0, 0, 0, -40) : adjustColor(color, 0, 0, +40, 0, 0, 0, -50); break; default: break; } } pa->setColor(DPalette::Active, role, color); generatePaletteColor(*pa, role, type); } return *const_cast(pa); } template static void generatePaletteColor_helper(DPalette &base, M role, DGuiApplicationHelper::ColorType type) { if (type == DGuiApplicationHelper::UnknownType) { type = DGuiApplicationHelper::toColorType(base); } QColor disable_mask_color, inactive_mask_color; if (type == DGuiApplicationHelper::DarkType) { disable_mask_color = dark_qpalette[QPalette::Window]; inactive_mask_color = dark_qpalette[QPalette::Window]; disable_mask_color.setAlphaF(0.7); inactive_mask_color.setAlphaF(0.6); } else { disable_mask_color = light_qpalette[QPalette::Window]; inactive_mask_color = light_qpalette[QPalette::Window]; disable_mask_color.setAlphaF(0.6); inactive_mask_color.setAlphaF(0.4); } const QColor &color = base.color(QPalette::Normal, role); base.setColor(QPalette::Disabled, role, DGuiApplicationHelper::blendColor(color, disable_mask_color)); QPalette::ColorRole qr = static_cast(role); if (qr == QPalette::Text) { // disable text color olny -60% alpha base.setColor(QPalette::Disabled, role, DGuiApplicationHelper::adjustColor(color, 0, 0, 0, 0, 0, 0, -60)); } if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::Attribute::UseInactiveColorGroup)) base.setColor(QPalette::Inactive, role, DGuiApplicationHelper::blendColor(color, inactive_mask_color)); else base.setColor(QPalette::Inactive, role, color); } /*! \brief 获å�–调色æ�¿é¢œè‰². \param base 调色æ�¿ \param role 色ç � \param type 主题枚举值 \sa QPalette::ColorRole */ void DGuiApplicationHelper::generatePaletteColor(DPalette &base, QPalette::ColorRole role, DGuiApplicationHelper::ColorType type) { if (role == QPalette::Window) { const QBrush &window = base.brush(QPalette::Normal, role); base.setBrush(QPalette::Disabled, role, window); base.setBrush(QPalette::Inactive, role, window); return; } generatePaletteColor_helper(base, role, type); } /*! \brief 加工调色æ�¿çš„颜色. \overload 一般我们å�ªä¼šä¸ºè°ƒè‰²æ�¿çš„ QPalette::Normal 组设置颜色值, 但是 控件中也需è¦�使用其他组的颜色, 此函数使用一些固定规则为 \a base å¡«å…… QPalette::Disabled å’Œ QPalette::Inactive 分组的颜色. ä¸�å�Œçš„颜色类型会使用ä¸�å�Œçš„加工规则, 如果为 LightType 类型, 则将颜色的alpha通é�“调整为 0.6 å�Žä½œä¸º QPalette::Disabled 类的颜色使用, 调整为 0.4 å�Ž ä½œä¸º QPalette::Inactive 类的颜色使用. 如果为 DarkType 类型, 则将颜色的alpha通é�“调整为 0.7 å�Žä½œä¸º QPalette::Disabled 类的颜色使用, 调整为 0.6 å�Žä½œä¸º QPalette::Inactive 类的颜色使用. \param base 被加工的调色æ�¿ \param role 加工的项 \param type 加工时所使用的颜色类型, 如果值为 UnknownType 将使用 toColorType 获å�–颜色类型 */ void DGuiApplicationHelper::generatePaletteColor(DPalette &base, DPalette::ColorType role, DGuiApplicationHelper::ColorType type) { generatePaletteColor_helper(base, role, type); } /*! \brief 加工调色æ�¿çš„颜色. \overload å�Œ generatePaletteColor, 将直接调用 generatePaletteColor 加工 所有类型的调色æ�¿é¢œè‰². \param base 被加工的调色æ�¿ \param type 加工时所使用的颜色类型, 如果值为 UnknownType 将使用 toColorType 获å�–颜色类型 */ void DGuiApplicationHelper::generatePalette(DPalette &base, ColorType type) { // 先判断调色æ�¿çš„色调 if (type == UnknownType) { type = toColorType(base); } for (int i = 0; i < QPalette::NColorRoles; ++i) { QPalette::ColorRole role = static_cast(i); generatePaletteColor(base, role, type); } for (int i = 0; i < QPalette::NColorRoles; ++i) { DPalette::ColorType role = static_cast(i); generatePaletteColor(base, role, type); } } static inline QColor getActiveColor(const DPlatformTheme *theme, DGuiApplicationHelper::ColorType type) { QColor activeColor; if (type == DGuiApplicationHelper::DarkType) { activeColor = theme->darkActiveColor(); if (!activeColor.isValid()) { activeColor = theme->activeColor(); } } else { activeColor = theme->activeColor(); } return activeColor; } /*! \brief 获å�–调色æ�¿æ•°æ�®. 首先根æ�® DPlatformTheme::themeName 获å�–主题的颜色类型, 如果å��称以 "dark" 结尾则认为其颜色类型为 DarkType, å�¦åˆ™ä¸º LightType. 如果主题å��称为空, 将使用其父主题的å��ç§°( DPlatformTheme::fallbackProperty ). æ ¹æ�®é¢œè‰²ç±»åž‹å°†ä½¿ç”¨ standardPalette 获å�–基础调色æ�¿æ•°æ�®, 在此基础上 从 DPlatformTheme::fetchPalette 获å�–最终的调色æ�¿. \param theme å¹³å�°ä¸»é¢˜å¯¹è±¡ \return 调色æ�¿æ•°æ�® */ DPalette DGuiApplicationHelper::fetchPalette(const DPlatformTheme *theme) { DPalette base_palette; const QByteArray theme_name = theme->themeName(); ColorType type = LightType; // 深色主题 if (theme_name.endsWith("dark")) { type = DarkType; } bool ok = false; base_palette = theme->fetchPalette(standardPalette(type), &ok); const QColor &active_color = getActiveColor(theme, type); if (active_color.isValid()) { base_palette.setColor(QPalette::Normal, QPalette::Highlight, active_color); // ok为true时会整体处ç�†palette的所有颜色 if (!ok) { generatePaletteColor(base_palette, QPalette::Highlight, type); } } if (ok) { generatePalette(base_palette, type); } return base_palette; } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief 设置是å�¦å°†è°ƒè‰²æ�¿çš„颜色改为å�Šé€�明模å¼�. 一般用在主窗å�£èƒŒæ™¯ä¸ºé€�明ã€�模糊的程åº�中 \param on 是å�¦å¼€å�¯ */ void DGuiApplicationHelper::setUseInactiveColorGroup(bool on) { DGuiApplicationHelper::setAttribute(Attribute::UseInactiveColorGroup, on); } /*! \brief 设置是å�¦å¼€å�¯æ··å�ˆé¢œè‰². \param on 是å�¦å¼€å�¯ */ void DGuiApplicationHelper::setColorCompositingEnabled(bool on) { DGuiApplicationHelper::setAttribute(Attribute::ColorCompositing, on); } #endif bool DGuiApplicationHelper::isXWindowPlatform() { return DGuiApplicationHelper::testAttribute(Attribute::IsXWindowPlatform); } /*! \brief 用于判断当å‰�桌é�¢çŽ¯å¢ƒæ˜¯å�¦æ˜¯å¹³æ�¿ç”µè„‘环境. \return true 是平æ�¿ç”µè„‘环境 falseä¸�是平æ�¿ç”µè„‘环境 */ bool DGuiApplicationHelper::isTabletEnvironment() { return DGuiApplicationHelper::testAttribute(Attribute::IsTableEnvironment); } /*! \brief isAnimationEnvironment 用于判断当å‰�桌é�¢çŽ¯å¢ƒæ˜¯å�¦æ˜¯å¼€å�¯äº†åŠ¨ç”»ç­‰ç‰¹æ•ˆçš„çŽ¯å¢ƒ \return trueå¼€å�¯äº† false没有开å�¯ */ bool DGuiApplicationHelper::isSpecialEffectsEnvironment() { return DGuiApplicationHelper::testAttribute(Attribute::IsSpecialEffectsEnvironment); } /*! \brief DGuiApplicationHelper::systemTheme. 返回系统级别的主题, 优先级低于 applicationTheme \return å¹³å�°ä¸»é¢˜å¯¹è±¡ \sa applicationTheme \sa windowTheme */ DPlatformTheme *DGuiApplicationHelper::systemTheme() const { D_DC(DGuiApplicationHelper); return d->systemTheme; } /*! \brief DGuiApplicationHelper::applicationTheme. å�Œ systemTheme \return å¹³å�°ä¸»é¢˜å¯¹è±¡ \sa systemTheme \sa windowTheme */ DPlatformTheme *DGuiApplicationHelper::applicationTheme() const { D_DC(DGuiApplicationHelper); // 如果appTheme还未åˆ�始化,应当先åˆ�始化appTheme if (Q_UNLIKELY(!d->appTheme)) { // åˆ�始程åº�级别的主题对象 const_cast(d)->_q_initApplicationTheme(false); } return d->appTheme; } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief 返回窗å�£çº§åˆ«çš„主题, 优先级高于 windowTheme å’Œ systemTheme. \param window 主题对象对应的窗å�£ \return å¹³å�°ä¸»é¢˜å¯¹è±¡ \sa applicationTheme() \warning 已废弃, ä¸�å†�对外暴露为特定窗å�£è®¾ç½®ä¸»é¢˜çš„æŽ¥å�£ */ DPlatformTheme *DGuiApplicationHelper::windowTheme(QWindow *window) const { DPlatformTheme *theme = qvariant_cast(window->property(WINDOW_THEME_KEY)); if (theme) { return theme; } D_DC(DGuiApplicationHelper); theme = d->initWindow(window); return theme; } #endif /*! \brief 返回应用程åº�调色æ�¿. 如果使用 setApplicationPalette 设置过一个有效的调色æ�¿, 将直接返回ä¿�存的调色æ�¿. å�¦åˆ™ 先计算调色æ�¿çš„ColorType, å†�使用这个颜色类型通过 standardPalette 获å�–标准调色æ�¿. 计算 ColorType的数æ�®æ�¥æº�按优先级从高到低排列有以下几ç§�æ–¹å¼�: 1. 如果使用 setThemeType 设置过一个有效的颜色类型, 将直接使用 themeType 的值. 2. 如果为QGuiApplication设置过调色æ�¿(表现为 QGuiApplication::testAttribute(Qt::AA_SetPalette) 为true), 则将使用 QGuiApplication::palette 通过 toColorType 获å�–颜色类型. 3. 将根æ�® applicationTheme çš„ DPlatformTheme::themeName 计算颜色类型. 如果ColorTypeæ�¥æº�自第2ç§�æ–¹å¼�, 则会直接使用 QGuiApplication::palette 覆盖标准调色æ�¿ä¸­çš„ QPalette 部分, 且程åº�ä¸�会å†�è·Ÿéš�系统的活动色自动更新调色æ�¿. \warning ä¸�应该在DTK程åº�中使用QGuiApplication/QApplication::setPalette \return 应用程åº�调色æ�¿ */ DPalette DGuiApplicationHelper::applicationPalette(ColorType paletteType) const { D_DC(DGuiApplicationHelper); if (d->appPalette) { return *d->appPalette; } ColorType type = paletteType; bool aa_setPalette = qGuiApp && qGuiApp->testAttribute(Qt::AA_SetPalette); // 此时appThemeå�¯èƒ½è¿˜æœªåˆ�始化, 因此先使用systemTheme, å¾…appThemeåˆ�始化之å�Žä¼š // 通知程åº�调色æ�¿å�‘生改å�˜ auto theme = Q_LIKELY(d->appTheme) ? d->appTheme : d->systemTheme; if (type == UnknownType) { if (aa_setPalette) { type = toColorType(qGuiApp->palette()); } else { // 如果程åº�未自定义调色æ�¿, 则直接从平å�°ä¸»é¢˜ä¸­èŽ·å�–调色æ�¿æ•°æ�® return fetchPalette(theme); } } // 如果程åº�自定义了palette的类型,将忽略 appTheme 中设置的调色æ�¿æ•°æ�®. DPalette pa = standardPalette(type); if (aa_setPalette) { // 如果程åº�通过QGuiApplication::setPalette自定义了调色æ�¿, 则应当尊é‡�程åº�的选择 // 覆盖DPalette中的的QPaletteæ•°æ�® pa.QPalette::operator =(qGuiApp->palette()); } else { const QColor &active_color = getActiveColor(theme, type); if (active_color.isValid()) { // 应用Active Color pa.setColor(QPalette::Normal, QPalette::Highlight, active_color); generatePaletteColor(pa, QPalette::Highlight, type); } } return pa; } DPalette DGuiApplicationHelper::applicationPalette() const { D_DC(DGuiApplicationHelper); return applicationPalette(d->paletteType); } /*! \brief DGuiApplicationHelper::setApplicationPalette. 自定义应用程åº�调色æ�¿, 如果没有为 QGuiApplication 设置过 QPalette, 则 将触å�‘ QGuiApplication::palette 的更新. 如果仅需è¦�控制程åº�使用亮色还是暗色的 调色æ�¿, 请使用 setThemeType. \note 主动设置调色æ�¿çš„æ“�作会导致程åº�ä¸�å†�使用 DPlatformTheme 中调色æ�¿ç›¸å…³çš„æ•°æ�®, 也 包括窗å�£çº§åˆ«çš„ windowTheme 所对应的 DPlatformTheme, 届时设置 DPlatformTheme çš„ themeName 和所有与 \a palette 相关的属性都ä¸�å†�生效. \warning 使用此方å¼�设置的调色æ�¿å°†ä¸�会自动跟éš�活动色的å�˜åŒ– \warning 如果使用过QGuiApplication::setPalette, 此方å¼�å�¯èƒ½ä¸�会生效 \param palette è¦�设置的调色æ�¿ */ void DGuiApplicationHelper::setApplicationPalette(const DPalette &palette) { D_D(DGuiApplicationHelper); if (qGuiApp && qGuiApp->testAttribute(Qt::AA_SetPalette)) { qWarning() << "DGuiApplicationHelper: Plase check 'QGuiApplication::setPalette', Don't use it on DTK application."; } auto resolve = [](const DPalette &palette) ->bool { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) return palette.resolveMask(); #else return palette.resolve(); #endif }; if (d->appPalette) { if (resolve(palette)) { *d->appPalette = palette; } else { d->appPalette.reset(); } } else if (resolve(palette)) { d->appPalette.reset(new DPalette(palette)); } else { return; } // 通知QGuiApplication更新自身的paletteå’Œfont d->notifyAppThemeChanged(); } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief DGuiApplicationHelper::windowPalette. 返回窗å�£æ‰€å¯¹åº”的调色æ�¿æ•°æ�®, å�Œ applicationPalette, 如果程åº�中自定义了 调色æ�¿, 则直接使用 applicationPalette. 自定义调色æ�¿çš„三ç§�æ–¹å¼�如下: 1. 通过 setApplicationPalette 固定调色æ�¿ 2. 通过 setThemeType 固定调色æ�¿çš„类型 3. 通过 QGuiApplication::setPalette 固定调色æ�¿, 需è¦�注æ„�此方法ä¸�å�¯é€†. å�¦åˆ™å°†åŸºäºŽçª—å�£æ‰€å¯¹åº”çš„ DPlatformTheme 获å�–调色æ�¿( fetchPalette). \param window \return 调色æ�¿ \sa windowTheme(), fetchPalette(), standardPalette(), generatePalette(), applicationPalette() \warning 使用时è¦�å�Œæ—¶å…³æ³¨ applicationPaletteChanged() , 收到此信å�·å�Žå�¯èƒ½éœ€è¦�é‡�新获å�–窗å�£çš„调色æ�¿ \warning 已废弃, ä¸�å†�对外暴露控制窗å�£çº§åˆ«è°ƒè‰²æ�¿çš„æŽ¥å�£ */ DPalette DGuiApplicationHelper::windowPalette(QWindow *window) const { #if DTK_VERSION >= DTK_VERSION_CHECK(5, 0, 0, 0) Q_UNUSED(window); qCWarning(dgAppHelper) << "DGuiApplicationHelper::windowPalette is deprecated, please use applicationPalette instead."; return applicationPalette(); #else D_DC(DGuiApplicationHelper); // 如果程åº�自定义了调色版, 则ä¸�å†�关心窗å�£å¯¹åº”的平å�°ä¸»é¢˜ä¸Šçš„设置 if (Q_UNLIKELY(d->isCustomPalette())) { return applicationPalette(); } DPlatformTheme *theme = windowTheme(window); if (Q_UNLIKELY(!theme)) { return applicationPalette(); } return fetchPalette(theme); #endif } #endif /*! \brief DGuiApplicationHelper::fontManager. 程åº�中唯一的DFontManager对象, 会根æ�®ç¨‹åº�çš„fontChangedä¿¡å�· æ›´æ–° DFontManager::baseFontPixelSize \warning 请ä¸�è¦�å°�试更改它的 baseFontPixelSize 属性 */ const DFontManager *DGuiApplicationHelper::fontManager() const { // 为对象åˆ�始化信å�·é“¾æŽ¥ if (!_globalFM.exists()) { // fontManager's base font is update from qGuiApp. _globalFM->setBaseFont(qGuiApp->font()); connect(this, &DGuiApplicationHelper::fontChanged, _globalFM, &DFontManager::setBaseFont); } return _globalFM; } /*! \brief 获å�–颜色的明亮度,将其转æ�¢ä¸ºä¸»é¢˜ç±»åž‹çš„æžšä¸¾å€¼. 转æ�¢çš„策略为:先将颜色转æ�¢ä¸ºrgbæ ¼å¼�,å†�æ ¹æ�® Y = 0.299R + 0.587G + 0.114B 的公å¼� 计算出颜色的亮度,亮度大于 191 时认为其为浅色,å�¦åˆ™è®¤ä¸ºå…¶ä¸ºæ·±è‰²ã€‚ \param color 需è¦�转æ�¢ä¸ºä¸»é¢˜çš„类型的颜色 \return 颜色类型的枚举值 */ DGuiApplicationHelper::ColorType DGuiApplicationHelper::toColorType(const QColor &color) { if (!color.isValid()) return UnknownType; QColor rgb_color = color.toRgb(); // 获å�–rgb颜色的亮度(转æ�¢ä¸ºYUVæ ¼å¼�) float luminance = 0.299 * rgb_color.redF() + 0.587 * rgb_color.greenF() + 0.114 * rgb_color.blueF(); if (qRound(luminance * 255) > 191) { return LightType; } return DarkType; } /*! \brief 将调色æ�¿ \a palette 转æ�¢ä¸ºä¸»é¢˜ç±»åž‹çš„æžšä¸¾. \overload 使用 QPalette::background 获å�–颜色的明亮度,将其转æ�¢ä¸ºä¸»é¢˜ç±»åž‹çš„æžšä¸¾å€¼ã€‚ 返回调色æ�¿çš„颜色类型 \param palette 调色æ�¿ \return 颜色类型的枚举值 */ DGuiApplicationHelper::ColorType DGuiApplicationHelper::toColorType(const QPalette &palette) { return toColorType(palette.window().color()); } /*! \brief 返回程åº�的主题类型. 当themeType为UnknownTypeæ—¶, 将自动根æ�® GuiApplication::paletteçš„QPalette::background颜色计算主题 类型, å�¦åˆ™ä¸Ž paletteType 的值一致. 程åº�中应当使用此值作为 暗色/亮色主题类型的判断. \return 主题的颜色类型. \sa toColorType */ DGuiApplicationHelper::ColorType DGuiApplicationHelper::themeType() const { D_DC(DGuiApplicationHelper); d->initPaletteType(); if (d->paletteType != UnknownType) { return d->paletteType; } return toColorType(qGuiApp->palette()); } /*! \brief 返回当å‰�已设置的调色æ�¿ç±»åž‹. 如果未调用过 setPaletteType, 默认为 UnknownType. \return 返回当å‰�已设置的调色æ�¿ç±»åž‹. \warning 与 themetype ä¸�å�Œï¼Œæ­¤å€¼ä¸Žç¨‹åº�当å‰�çš„ QPalette 没有关系。 \sa DGuiApplicationHelper::themeType */ DGuiApplicationHelper::ColorType DGuiApplicationHelper::paletteType() const { D_DC(DGuiApplicationHelper); d->initPaletteType(); return d->paletteType; } /*! \brief 设置DGuiApplicationHelper实例. \param key 实例关键字 \param singleScope 实例使用范围 \return 设置是å�¦æˆ�功 \note 此处所用到DGuiApplicationHelperPrivate::waitTime默认值为3000ms,å�¯é€šè¿‡ \note DGuiApplicationHelper::setSingleInstanceInterval设置 */ bool DGuiApplicationHelper::setSingleInstance(const QString &key, DGuiApplicationHelper::SingleScope singleScope) { bool new_server = !_d_singleServer.exists(); if (_d_singleServer->isListening()) { _d_singleServer->close(); } QString socket_key = "_d_dtk_single_instance_"; switch (singleScope) { case GroupScope: _d_singleServer->setSocketOptions(QLocalServer::GroupAccessOption); #ifdef Q_OS_LINUX socket_key += QString("%1_").arg(getgid()); #endif break; case WorldScope: _d_singleServer->setSocketOptions(QLocalServer::WorldAccessOption); break; default: _d_singleServer->setSocketOptions(QLocalServer::UserAccessOption); #ifdef Q_OS_LINUX socket_key += QString("%1_").arg(getuid()); #endif break; } socket_key += key; #ifdef Q_OS_LINUX auto info = QFileInfo{"/proc/self/ns/pid"}; // maybe kernel doesn't support namespace while (info.exists()) { auto pidns = QFileInfo{info.symLinkTarget()}.fileName(); if (pidns.isEmpty()) { break; } // maybe format has been changed auto start = pidns.indexOf('['); auto end = pidns.indexOf(']'); if (start == -1 || end == -1) { break; } auto num = pidns.mid(start + 1, end - start - 1); // append pid namespace socket_key += QStringLiteral("_%1").arg(num); break; } #endif QString lockfile = socket_key; if (!lockfile.startsWith(QLatin1Char('/'))) { lockfile = QDir::cleanPath(QDir::tempPath()); lockfile += QLatin1Char('/') + socket_key; } lockfile += QStringLiteral(".lock"); static QScopedPointer lock(new QLockFile(lockfile)); // å�Œä¸€ä¸ªè¿›ç¨‹å¤šæ¬¡è°ƒç”¨æœ¬æŽ¥å�£ä½¿ç”¨æœ€å�Žä¸€æ¬¡è®¾ç½®çš„ key // FIX dcc 使用ä¸�å�Œçš„ key 两次调用 setSingleInstance å�Žæ— æ³•å�¯åŠ¨çš„é—®é¢˜ qint64 pid = -1; QString hostname, appname; if (lock->isLocked() && lock->getLockInfo(&pid, &hostname, &appname) && pid == getpid()) { qCWarning(dgAppHelper) << "call setSingleInstance again within the same process"; lock->unlock(); lock.reset(new QLockFile(lockfile)); } if (!lock->tryLock()) { qCDebug(dgAppHelper) << "===> new client <===" << getpid(); // 通知别的实例 QLocalSocket socket; socket.connectToServer(socket_key); // 等待到有效数æ�®æ—¶è®¤ä¸ºserver实例有效 if (socket.waitForConnected(DGuiApplicationHelperPrivate::waitTime) && socket.waitForReadyRead(DGuiApplicationHelperPrivate::waitTime)) { // 读å�–æ•°æ�® quint8 version; qint64 pid; QStringList arguments; QStringList envs; QDataStream ds(&socket); ds >> version >> pid >> arguments; // Only read envs field when server supports v2+ protocol if (version >= 2) ds >> envs; qCInfo(dgAppHelper) << "Process is started: pid=" << pid << "arguments=" << arguments; if (ds.status() != QDataStream::Ok) { qCWarning(dgAppHelper) << "Invalid data received from primary instance, aborting."; return false; } // 把自己的信æ�¯å‘Šè¯‰ç¬¬ä¸€ä¸ªå®žä¾‹ ds << _d_singleServerVersion << qApp->applicationPid() << qApp->arguments() << filteredSingleInstanceEnvs(); socket.flush(); } return false; } if (!_d_singleServer->listen(socket_key)) { qCWarning(dgAppHelper) << "listen failed:" << _d_singleServer->errorString(); return false; } else { qCDebug(dgAppHelper) << "===> listen <===" << _d_singleServer->serverName() << getpid(); } if (new_server) { qCDebug(dgAppHelper) << "===> new server <===" << _d_singleServer->serverName() << getpid(); QObject::connect(_d_singleServer, &QLocalServer::newConnection, qApp, [] { QLocalSocket *instance = _d_singleServer->nextPendingConnection(); // å…ˆå�‘é€�æ•°æ�®å‘Šè¯‰æ–°çš„实例自己收到了它的请求 QDataStream ds(instance); ds << _d_singleServerVersion // å��议版本 << qApp->applicationPid() // 进程id << qApp->arguments() // å�¯åŠ¨æ—¶çš„å�‚æ•° << filteredSingleInstanceEnvs(); // 环境å�˜é‡�(仅转å�‘许å�¯åˆ—表中的 key) QObject::connect(instance, &QLocalSocket::readyRead, qApp, [instance] { // 读å�–æ•°æ�® QDataStream ds(instance); quint8 version; qint64 pid; QStringList arguments; QStringList envs; ds >> version >> pid >> arguments; // Only read envs field when client supports v2+ protocol if (version >= 2) ds >> envs; instance->close(); qCInfo(dgAppHelper) << "New instance: pid=" << pid << "arguments=" << arguments; if (ds.status() != QDataStream::Ok) { qCWarning(dgAppHelper) << "Invalid data received from new instance, aborting."; return; } // Apply environment variables forwarded from the new client instance. // Only process KEY=VALUE pairs sent by v2+ clients; re-validate each key // against the whitelist to prevent env injection via malformed socket data. if (version >= 2) { for (const QString &envItem : std::as_const(envs)) { const int eqPos = envItem.indexOf(QLatin1Char('=')); if (eqPos < 1) // skip entries with no '=' or an empty key continue; const QString keyStr = envItem.left(eqPos); if (!s_singleInstanceForwardEnvKeys.contains(keyStr)) continue; // reject keys not in the whitelist const QByteArray keyBa = keyStr.toLocal8Bit(); const QByteArray valueBa = envItem.mid(eqPos + 1).toLocal8Bit(); qputenv(keyBa.constData(), valueBa); qCInfo(dgAppHelper) << "Applied env from new instance:" << keyBa; } } // 通知新进程的信æ�¯ if (_globalHelper.exists() && _globalHelper->helper()) Q_EMIT _globalHelper->helper()->newProcessInstance(pid, arguments); }); instance->flush(); //å�‘é€�æ•°æ�®ç»™æ–°çš„实例 }); } return true; } /*! \brief 设置从QLocalServer获å�–消æ�¯çš„等待时间. 用于在é‡�新创建DGuiApplicationHelperå�•例时,检测DGuiApplicationHelperå�•例是å�¦å­˜åœ¨ä¸”有å“�应 \param interval 等待时间,如 \a interval 为 -1 则没有超时一直等待,默认和 QLocalSocket 一致 3000ms \note 需è¦�在 DGuiApplicationHelper::setSingleInstance 之å‰�调用å�¦åˆ™æ— æ•ˆã€‚ */ void DGuiApplicationHelper::setSingleInstanceInterval(int interval) { Q_ASSERT_X(!_d_singleServer->isListening(), "DGuiApplicationHelper::setSingleInstanceInterval","Must call before setSingleInstance"); DGuiApplicationHelperPrivate::waitTime = interval; } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief 设置从QLocalServer获å�–消æ�¯çš„等待时间. \param interval 等待时间,typo 请使用 DGuiApplicationHelper::setSingleInstanceInterval */ void DGuiApplicationHelper::setSingelInstanceInterval(int interval) { DGuiApplicationHelperPrivate::waitTime = interval; } #endif /*! \brief 获å�–帮助手册目录 \return 帮助手册目录 */ QStringList DGuiApplicationHelper::userManualPaths(const QString &appName) { Q_ASSERT(!appName.isEmpty()); // 获å�–主目录 DCORE_USE_NAMESPACE QStringList manualPaths; const auto &pathlist = DStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); // 获å�–所有已存在的帮助手册目录 for (int i = 0; i < pathlist.size(); ++i) { QString strAssetPath = QStringList{pathlist[i], "deepin-manual/manual-assets"}.join(QDir::separator()); for (const QString &type : QDir(strAssetPath).entryList(QDir::NoDotAndDotDot | QDir::Dirs)) { QString appDirPath = QStringList{strAssetPath, type, appName}.join(QDir::separator()); if (QDir(appDirPath).exists()) manualPaths.push_back(appDirPath); } } return manualPaths; } /*! * \brief Determine whether it's a user manual for this application. * \return */ bool DGuiApplicationHelper::hasUserManual() const { return userManualPaths(qApp->applicationName()).size() > 0; } static inline QStringList translateDirs(const QString &appName) { Q_ASSERT(!appName.isEmpty()); QStringList dirs; DCORE_USE_NAMESPACE //("/home/user/.local/share", "/usr/local/share", "/usr/share") auto dataDirs = DStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); for (const auto &path : dataDirs) { DPathBuf pathBuf(path); dirs << (pathBuf / appName / "translations").toString(); } return dirs; } bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QString &appName, const QList &localeFallback) { return loadTranslator(fileName, translateDirs(appName), localeFallback); } bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QList &translateDirs, const QList &localeFallback) { DCORE_USE_NAMESPACE; QList dirs = translateDirs; const QList defaultDirPrefix { qApp->applicationDirPath(), QDir::currentPath() }; for (auto item : defaultDirPrefix) dirs << item.join("translations").toString(); for (const auto &locale : localeFallback) { for (const auto &dir : dirs) { auto translator = new QTranslator(qApp); // QTranslator::load(locale, filename, prefix, directory, suffix) automatically handles // locale fallback (e.g., zh_CN -> zh -> C) and file existence checking if (translator->load(locale, fileName, QString('_'), dir)) { qCDebug(dgAppHelper) << "load translate" << fileName << "for locale" << locale.name() << "from" << dir; qApp->installTranslator(translator); qApp->setProperty("dapp_locale", locale.name()); return true; } delete translator; // Clean up if loading failed } } // Collect locale names for warning message QStringList localeNames; for (const auto &locale : localeFallback) { if (locale.language() != QLocale::English) // English does not need translation localeNames << locale.name(); } if (!localeNames.isEmpty()) { qWarning() << fileName << "can not find qm files for locales" << localeNames; } return false; } bool DGuiApplicationHelper::loadTranslator(const QList &localeFallback) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) auto qTranslationsPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); #else auto qTranslationsPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); #endif DCORE_USE_NAMESPACE //("/home/user/.local/share", "/usr/local/share", "/usr/share") auto qtranslateDirs = translateDirs("qt" QT_STRINGIFY(QT_VERSION_MAJOR)); qtranslateDirs.prepend(qTranslationsPath); loadTranslator("qt", qtranslateDirs, localeFallback); loadTranslator("qtbase", qtranslateDirs, localeFallback); auto appName = qApp->applicationName(); return loadTranslator(appName, appName, localeFallback); } DGuiApplicationHelper::SizeMode DGuiApplicationHelper::sizeMode() const { D_DC(DGuiApplicationHelper); return d->fetchSizeMode(); } void DGuiApplicationHelper::setSizeMode(const DGuiApplicationHelper::SizeMode mode) { D_D(DGuiApplicationHelper); const auto old = d->fetchSizeMode(); d->explicitSizeMode = mode; const auto current = d->fetchSizeMode(); if (old != current) Q_EMIT sizeModeChanged(current); } void DGuiApplicationHelper::resetSizeMode() { D_D(DGuiApplicationHelper); const auto old = d->fetchSizeMode(); d->explicitSizeMode = InvalidSizeMode; const auto current = d->fetchSizeMode(); if (current != old) Q_EMIT sizeModeChanged(current); } void DGuiApplicationHelper::setAttribute(DGuiApplicationHelper::Attribute attribute, bool enable) { if (attribute < Attribute::ReadOnlyLimit) { DGuiApplicationHelperPrivate::attributes.setFlag(attribute, enable); } else { qWarning() << "You are setting for the read-only option."; return; } } bool DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::Attribute attribute) { switch (attribute) { case IsXWindowPlatform: return qGuiApp->platformName() == QByteArrayLiteral("xcb") || qGuiApp->platformName() == QByteArrayLiteral("dxcb"); case IsDXcbPlatform: return DPlatformHandle::isDXcbPlatform(); case IsTableEnvironment: return QGuiApplicationPrivate::instance()->platformIntegration()->services()->desktopEnvironment().toLower().endsWith("tablet"); case IsDeepinPlatformTheme: if (!QGuiApplicationPrivate::platform_name) { return false; } return QString(typeid(*QGuiApplicationPrivate::platform_theme).name()).contains("QDeepinTheme"); case IsDeepinEnvironment: { const auto &de = QGuiApplicationPrivate::instance()->platformIntegration()->services()->desktopEnvironment(); return de.toLower().contains("deepin") || de == "DDE"; } case IsSpecialEffectsEnvironment: { return qgetenv("DTK_DISABLED_SPECIAL_EFFECTS").toInt() != 1; } case IsWaylandPlatform: { static bool isTreeland = qApp->platformName() == QByteArrayLiteral("wayland"); return isTreeland; } case HasAnimations: { static bool isDisable = qEnvironmentVariableIsSet(DTK_ANIMATIONS_ENV); if (isDisable) return false; return _d_dconfig->enableDtkAnimations(); } case HasInWindowBlur: { static bool isDisable = qEnvironmentVariableIsSet(DTK_DISABLE_INWINDOWBLUR_ENV); if (isDisable) return false; return !_d_dconfig->disableInWindowBlur(); } default: return DGuiApplicationHelperPrivate::attributes.testFlag(attribute); } } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) /*! \brief DGuiApplicationHelper::setThemeType. \deprecated å�Œ setPaletteType, 已废弃,请ä¸�è¦�å†�使用。 \param themeType 主题类型. */ void DGuiApplicationHelper::setThemeType(DGuiApplicationHelper::ColorType themeType) { setPaletteType(themeType); } #endif /*! \brief 设置程åº�所应用的调色æ�¿ç±»åž‹. 将固定程åº�的调色æ�¿ç±»åž‹, 此行为å�¯èƒ½å¯¼è‡´ applicationPalette å�˜åŒ–, å‰�æ��是未使用 setApplicationPalette 固定过程åº�的调色æ�¿, 此方法ä¸�å½±å“�程åº�的调色æ�¿è·Ÿéš� 活动色改å�˜, å�¯ç”¨äºŽæŽ§åˆ¶ç¨‹åº�使用亮色还是暗色调色æ�¿. \note 主动设置调色æ�¿é¢œè‰²ç±»åž‹çš„æ“�作会导致程åº�ä¸�å†�使用 DPlatformTheme 中调色æ�¿ç›¸å…³çš„æ•°æ�®, 也 包括窗å�£çº§åˆ«çš„ windowTheme 所对应的 DPlatformTheme, 届时设置 DPlatformTheme çš„ themeName 和所有与 palette 相关的属性都ä¸�å†�生效. \param paletteType 主题类型的枚举值 */ void DGuiApplicationHelper::setPaletteType(DGuiApplicationHelper::ColorType paletteType) { if (!qApp) { qWarning() << "Can't call `DGuiApplicationHelper::setPaletteType` before QCoreApplication constructed."; return; } D_D(DGuiApplicationHelper); d->initPaletteType(); d->setPaletteType(paletteType, true); if (!DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::DontSaveApplicationTheme)) _d_dconfig->setThemeType(static_cast(paletteType)); } /*! * \brief Open manual for this application. */ void DGuiApplicationHelper::handleHelpAction() { if (!hasUserManual()) { return; } #ifdef Q_OS_LINUX QString appid = qApp->applicationName(); // new interface use applicationName as id QDBusInterface manual("com.deepin.Manual.Open", "/com/deepin/Manual/Open", "com.deepin.Manual.Open"); QDBusPendingCall call = manual.asyncCall("ShowManual", appid); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [appid](QDBusPendingCallWatcher *pWatcher) { QDBusPendingReply reply = *pWatcher; if (reply.isError()) { // fallback to old interface qWarning() << reply.error() << "fallback to dman appid"; QProcess::startDetached("dman", QStringList() << appid); } pWatcher->deleteLater(); }); #else qWarning() << "not support dman now"; #endif } void DGuiApplicationHelper::openUrl(const QString &url) { #ifdef Q_OS_UNIX // workaround for pkexec apps bool ok = false; const int pkexecUid = qEnvironmentVariableIntValue("PKEXEC_UID", &ok); if (ok) { EnvReplaceGuard _env_guard(pkexecUid); Q_UNUSED(_env_guard); QDesktopServices::openUrl(url); } else #endif { QDesktopServices::openUrl(url); } } DGUI_END_NAMESPACE #include "moc_dguiapplicationhelper.cpp" dtkgui-6.7.46/src/kernel/dnativesettings.cpp000066400000000000000000000060461522615413000211000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dnativesettings.h" #include "private/dnativesettings_p.h" #include #include #include #include DGUI_BEGIN_NAMESPACE DNativeSettingsPrivate::DNativeSettingsPrivate(DNativeSettings *qq, const QByteArray &domain) : DObjectPrivate(qq) , domain(domain) { } DNativeSettingsPrivate::~DNativeSettingsPrivate() { } bool DNativeSettingsPrivate::init(const QMetaObject *mo, quint32 window) { QFunctionPointer native_build_setting_fun = qGuiApp->platformFunction("_d_buildNativeSettings"); if (!native_build_setting_fun) return false; D_Q(DNativeSettings); if (!domain.isEmpty()) { q->setProperty("_d_domain", domain); } q->setProperty("_d_metaObject", reinterpret_cast(mo)); return reinterpret_cast(native_build_setting_fun)(q, window); } /*! \class Dtk::Gui::DNativeSettings \inmodule dtkgui \brief 一个用于本地设置的类. */ DNativeSettings::DNativeSettings(quint32 window, const QByteArray &domain, QObject *parent) : DNativeSettings(&DNativeSettings::staticMetaObject, window, domain, parent) { } bool DNativeSettings::isValid() const { D_DC(DNativeSettings); return d->valid; } QByteArrayList DNativeSettings::allKeys() const { D_DC(DNativeSettings); return d->allKeys; } QVariant DNativeSettings::getSetting(const QByteArray &name) const { D_DC(DNativeSettings); // é�¿å…�进入死循环 if (!d->valid) return QVariant(); return property(name.constData()); } void DNativeSettings::setSetting(const QByteArray &name, const QVariant &value) { D_D(DNativeSettings); // é�¿å…�进入死循环 if (!d->valid) return; setProperty(name.constData(), value); } DNativeSettings::DNativeSettings(DNativeSettingsPrivate &dd, const QMetaObject *metaObject, quint32 window, QObject *parent) : QObject(parent) , DObject(dd) { d_func()->valid = init(metaObject, window); } DNativeSettings::DNativeSettings(const QMetaObject *metaObject, quint32 window, const QByteArray &domain, QObject *parent) : DNativeSettings(*new DNativeSettingsPrivate(this, domain), metaObject, window, parent) { } bool DNativeSettings::init(const QMetaObject *metaObject, quint32 window) { D_D(DNativeSettings); return d->init(metaObject, window); } void DNativeSettings::__setAllKeys(const QByteArrayList &keys) { D_D(DNativeSettings); d->allKeys = keys; Q_EMIT allKeysChanged(); } DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE QDebug operator<<(QDebug debug, const DTK_GUI_NAMESPACE::DNativeSettings &settings) { const QByteArrayList &keys = settings.allKeys(); for (const QByteArray &key : keys) { debug << key << settings.getSetting(key) << #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) Qt::endl; #else endl; #endif } return debug; } QT_END_NAMESPACE dtkgui-6.7.46/src/kernel/dpalette.cpp000066400000000000000000000114011522615413000174560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dpalette.h" DGUI_BEGIN_NAMESPACE struct DPaletteData : public QSharedData { QBrush br[DPalette::NColorGroups][DPalette::NColorTypes]; }; class DPalettePrivate { public: explicit DPalettePrivate(const QSharedDataPointer &d) : data(d) { } QSharedDataPointer data; }; /*! @~english \class Dtk::Gui::DPalette \ingroup guikernal \brief DPalette inherits and extends the QPalette class, providing the unique features of DTK DPalette add new color type */ /*! @~english \brief DPalette::Dpalette constructor function */ DPalette::DPalette() : d(new DPalettePrivate(QSharedDataPointer(new DPaletteData()))) { } /*! @~english \brief DPalette::Dpalette constructor function \a palette parameter is sent to the QPalette constructor function */ DPalette::DPalette(const QPalette &palette) : QPalette(palette) , d(new DPalettePrivate(QSharedDataPointer(new DPaletteData()))) { } /*! @~english \brief DPalette::Dpalette constructor functio \a palette parameter is sent to the QPalette constructor function */ DPalette::DPalette(const DPalette &palette) : QPalette(palette) , d(new DPalettePrivate(palette.d->data)) { } DPalette::~DPalette() {} DPalette &DPalette::operator=(const DPalette &palette) { QPalette::operator=(palette); d->data = palette.d->data; return *this; } /*! @~english \brief DPalette::brush \a cg \a cr \sa QPalette::brush() */ const QBrush &DPalette::brush(QPalette::ColorGroup cg, DPalette::ColorType cr) const { if (cr >= NColorTypes) { return QPalette::brush(cg, QPalette::NoRole); } if (cg == Current) { cg = currentColorGroup(); } else if (cg >= NColorGroups) { cg = Active; } return d->data->br[cg][cr]; } /*! @~english \brief DPalette::setBrush set drawing brush \a cg \a cr \a brush \sa QPalette::setBrush() */ void DPalette::setBrush(QPalette::ColorGroup cg, DPalette::ColorType cr, const QBrush &brush) { if (cg == All) { for (uint i = 0; i < NColorGroups; i++) setBrush(ColorGroup(i), cr, brush); return; } if (cr >= NColorTypes) { return QPalette::setBrush(cg, QPalette::NoRole, brush); } if (cg == Current) { cg = currentColorGroup(); } else if (cg >= NColorGroups) { cg = Active; } d->data->br[cg][cr] = brush; } DGUI_END_NAMESPACE DGUI_USE_NAMESPACE QT_BEGIN_NAMESPACE QDataStream &operator<<(QDataStream &ds, const DPalette &p) { ds << static_cast(p); for (int i = 0; i < DPalette::NColorGroups; ++i) { for (int j = 0; j < DPalette::NColorTypes; ++j) { ds << p.brush(DPalette::ColorGroup(i), DPalette::ColorType(j)); } } return ds; } QDataStream &operator>>(QDataStream &ds, DPalette &p) { ds >> static_cast(p); for (int i = 0; i < DPalette::NColorGroups; ++i) { for (int j = 0; j < DPalette::NColorTypes; ++j) { QBrush brush; ds >> brush; p.setBrush(DPalette::ColorGroup(i), DPalette::ColorType(j), brush); } } return ds; } QDebug operator<<(QDebug dbg, const DPalette &p) { const char *colorGroupNames[] = {"Active", "Disabled", "Inactive", "NColorGroups", "Current", "All", "Normal"}; const char *colorTypeNames[] = { "NoType", "ItemBackground", // 列表项的背景色 "TextTitle", // 标题型文本的颜色 "TextTips", // æ��示性文本的颜色 "TextWarning", // 警告类型的文本颜色 "TextLively", // 活跃å¼�文本颜色(ä¸�å�—活动色影å“�) "LightLively", // 活跃å¼�按钮(recommend button)背景色中的亮色(ä¸�å�—活跃色影å“�) "DarkLively", // 活跃å¼�按钮(recommend button)背景色中的暗色,会从亮色æ¸�å�˜åˆ°æš—色(ä¸�å�—活跃色影å“�) "FrameBorder", // 控件边框颜色 "PlaceholderText", // å� ä½�类型的文本颜色,å�¯ç”¨äºŽè¾“入框å� ä½�内容等æ��示性文字 "FrameShadowBorder", // 用于跟阴影å� åŠ çš„è¾¹æ¡†é¢œè‰² "ObviousBackground", // 明显的背景色 "NColorTypes"}; QDebugStateSaver saver(dbg); dbg << "\r\nDPalette: \r\n"; for (int i = 0; i < DPalette::NColorGroups; ++i) { for (int j = DPalette::NoType + 1; j < DPalette::NColorTypes; ++j) { dbg << colorGroupNames[DPalette::ColorGroup(i)] << colorTypeNames[DPalette::ColorType(j)]; dbg << p.brush(DPalette::ColorGroup(i), DPalette::ColorType(j)) << "\r\n"; } } return dbg; } QT_END_NAMESPACE dtkgui-6.7.46/src/kernel/dplatformhandle.cpp000066400000000000000000001022601522615413000210240ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022-2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dplatformhandle.h" #include "dplatformwindowinterface_p.h" #include "dguiapplicationhelper.h" #ifndef DTK_DISABLE_XCB #include "plugins/platform/xcb/dxcbplatformwindowinterface.h" #endif #ifndef DTK_DISABLE_TREELAND #include "plugins/platform/treeland/dtreelandplatformwindowinterface.h" #endif DGUI_BEGIN_NAMESPACE static QHash g_platformWindowImpls; static DPlatformWindowInterface *platformWindowImpl(const DPlatformHandle *platformHandle) { return g_platformWindowImpls.value(platformHandle); } /*! \class Dtk::Gui::DPlatformHandle \inmodule dtkgui \brief 一个和Qt dxcbå¹³å�°æ�’件交互的工具类. 实质性的功能皆在dxcbæ�’件中实现,此æ�’ä»¶ç›®å‰�å�ª 支æŒ�X11å¹³å�°ï¼Œåœ¨å…¶å®ƒå¹³å�°ä¸Šä½¿ç”¨è¿™ä¸ªç±»ä¸�会有任何效果。关于dxcb:它介于Qt应用和Qt xcbå¹³å�° æ�’件之间,通过覆写xcbæ�’件中æŸ�些对象的虚函数æ�¥æ”¹å�˜å®ƒçš„一些行为,本质上æ�¥è®²æ˜¯Qt xcbæ�’ä»¶çš„ 扩展,在X11å¹³å�°ä¸Šä¸ºDTK应用æ��供了一些改å�˜çª—å�£æ•ˆæžœçš„功能(比如自定义窗å�£çš„边框)ã€�其它和平 å�°å¯†åˆ‡ç›¸å…³çš„实现(比如修å¤�Qt应用在X11å¹³å�°çš„一些bug),ä¸�能脱离Qt xcbæ�’件独立è¿�行。dxcb 通过é‡�è½½ QPlatformNativeInterface æ��供接å�£ï¼ŒDPlatformHandle 中使用 QGuiApplication::platformFunction 调用这些接å�£ã€‚Applicationã€�dxcbã€�qt xcb 之间 的关系: \raw HTML
        �����������������┓
        ┃   Application  ┃
        ┗����������������┛
                ⇅
      ���������������������┓
      ┃     dxcb plugin    ┃
      ┗��������������������┛
                ⇅
   ����������������������������┓
   ┃      qt xcb platform      ┃
   ┗���������������������������┛
  
\endraw \ref {http://doc.qt.io/qt-5/qpa.html}{QPA} \ref {https://github.com/linuxdeepin/qt5dxcb-plugin/}{dxcb�件} \sa Dtk::Gui::DPlatformHandle::isDXcbPlatform \sa QGuiApplication::platformNativeInterface \sa Dtk::Widget::DMainWindow \sa DWindowManagerHelper \warning 使用此工具��确�应用加载了dxcb�件 \warning 因为 QGuiApplication::platformFunction 是在 Qt 5.4.0 版本引入的新接�, 所以 DPlatformHandle �支� Qt 5.4.0 以下版本。 */ /*! \property DPlatformHandle::windowRadius \brief 窗�的圆角�径。默认情况下,窗�管�器支�混�时,圆角�径为4,�则为0,并且 会��窗�管�器开�/关闭混�效果而�化 \note �读�写 \note 窗�为���全�或最大化状�时此值�生效 \warning 手动设置值�将无法���窗�管�器是�支�混�而自动更新边框宽度 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::borderWidth \brief 窗�的外边框宽度。默认情况下,窗�管�器支�混�时,边框宽度为1,�则对于�以 改�大�的窗�其值为2,�则为1,并且会��窗�管�器开�/关闭混�效果而�化 \note �读�写 \warning 手动设置值�将无法���窗�管�器是�支�混�而自动更新边框宽度 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::borderColor \brief 窗�外边框的颜色。默认情况下,窗�管�器支�混�时,颜色为 QColor(0, 0, 0, 255 * 0.15), �则为边框颜色和 #e0e0e0 的混�,并且会��窗�管�器开�/关闭混�效果而�化 \note �读�写 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::shadowRadius \brief 窗�的阴影�径。默认为 60 \note �读�写 \note 窗�管�器�支�混�时此值无效 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::shadowOffset \brief 窗�阴影的�移�。默认为 QPoint(0,16) \note �读�写 \note 窗�管�器�支�混�时此值无效 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::shadowColor \brief 窗�阴影的颜色。默认为 QColor(0, 0, 0, 255 * 0.6) \note �读�写 \note 窗�管�器�支�混�时此值无效 \sa DWindowManagerHelper::hasComposite */ /*! \property DPlatformHandle::clipPath \brief 窗�的�剪区域。处于路径内部的区域为窗�有效区域,�有效区域内的窗�内容 将无法显示,并且无法收到鼠标和触摸事件。示例: \code QWidget w; QPainterPath path; QFont font; font.setPixelSize(100); path.addText(0, 150, font, "deepin"); DPlatformHandle handle(&w); handle.setClipPath(path); w.resize(400, 200); w.show(); \endcode \image clip_window_demo.gif \note �读�写 \note 窗�的阴影和外边框绘制和其有效区域密切相关 \warning 设置此属性�将导致 DPlatformHandle::windowRadius 失效 */ /*! \property DPlatformHandle::frameMask \brief 设置 Frame Window 的�罩,和 \a clipPath ��的是,它的�剪包括阴影 部分。示例: \code QWidget w; DPlatformHandle handle(&w); // 为何更好的观察效果,此处将阴影改为�色 handle.setShadowColor(Qt::blue); w.resize(400, 200); w.show(); QRect frame_rect = w.rect() + handle.frameMargins(); frame_rect.moveTopLeft(QPoint(0, 0)); handle.setFrameMask(QRegion(frame_rect, QRegion::Ellipse)); \endcode \image frame_mask_demo.png \note �读�写 \note 由于实现机制�制,使用此属性�剪 Frame Window 时,无法去除边缘产生的锯齿 */ /*! \property DPlatformHandle::frameMargins \brief Sub Window 相对于 Frame Window 的边� \image frame_margins.png \note �读 \warning 在窗���时���此值的正确性 */ /*! \property DPlatformHandle::translucentBackground \brief 如果此属性值为 true,则在更新窗�绘制内容之�会先清空�更新区域内的图�, �则�清空,默认为 false \note �读�写 */ /*! \property DPlatformHandle::enableSystemResize \brief 如果此属性值为 true,则�许外界改�窗�的大�(如使用鼠标拖拽窗�边框), �则��许。默认为 true \note 无论属性值是多少,Qt::Popup 和 Qt::BypassWindowManagerHint 类型的 窗�都��许改�大� \note �读�写 \note 此属性仅仅控制 dxcb 中的行为,�会影�窗�管�器的行为 \sa QWidget::setFixedSize \sa QWindow::setMinimumSize \sa QWindow::setMaximumSize \sa DWindowManagerHelper::FUNC_RESIZE */ /*! \property DPlatformHandle::enableSystemMove \brief 如果此属性值为 ture,则�许外界移动窗�的�置(如使用鼠标拖拽移动窗�), �则��许。默认为 true \note 无论属性值是多少,Qt::Popup 和 Qt::BypassWindowManagerHint 类型的 窗�都��许改�大� \note �读�写 \note 此属性仅仅控制 dxcb 中的行为,�会影�窗�管�器的行为 \sa DWindowManagerHelper::FUNC_MOVE */ /*! \property DPlatformHandle::enableBlurWindow \brief 如果此属性为 true,则窗�有效区域内的背景将呈现出模糊效果,�则无特效。 默认为 false \note �读�写 \sa DPlatformHandle::setWindowBlurAreaByWM */ /*! \property DPlatformHandle::autoInputMaskByClipPath \brief 如果此属性值为 true,则窗��输入区域跟�其 \a clipPath 属性,�则� 跟�。默认为 true \note �输入区域指�接收鼠标或触摸事件的区域 \note �读�写 */ /*! \property DPlatformHandle::realWindowId \brief Sub Window 的窗� id,直接使用 QWindow::winId 或 QWidget::winId 获�到的是 Frame Window 的窗� id \note �读 */ /*! \fn void DPlatformHandle::frameMarginsChanged() \brief 信�会在 frameMargins 属性的值改�时被��. */ /*! \fn void DPlatformHandle::windowRadiusChanged() \brief 信�会在 windowRadius 属性的值改�时被�� */ /*! \fn void DPlatformHandle::borderWidthChanged() \brief 信�会在 borderWidth 属性的值改�时被�� */ /*! \fn void DPlatformHandle::borderColorChanged() \brief 信�会在 borderColor 属性的值改�时被�� */ /*! \fn void DPlatformHandle::shadowRadiusChanged() \brief 信�会在 shadowRadius 属性的值改�时被�� */ /*! \fn void DPlatformHandle::shadowOffsetChanged() \brief 信�会在 shadowOffset 属性的值改�时被�� */ /*! \fn void DPlatformHandle::shadowColorChanged() \brief 信�会在 shadowColor 属性的值改�时被�� */ /*! \fn void DPlatformHandle::clipPathChanged() \brief 信�会在 clipPath 属性的值改�时被�� */ /*! \fn void DPlatformHandle::frameMaskChanged() \brief 信�会在 frameMask 属性的值改�时被�� */ /*! \fn void DPlatformHandle::translucentBackgroundChanged() \brief 信�会在 translucentBackground 属性的值改�时被�� */ /*! \fn void DPlatformHandle::enableSystemResizeChanged() \brief 信�会在 enableSystemResize 属性的值改�时被�� */ /*! \fn void DPlatformHandle::enableSystemMoveChanged() \brief 信�会在 enableSystemMove 属性的值改�时被�� */ /*! \fn void DPlatformHandle::enableBlurWindowChanged() \brief 信�会在 enableBlurWindow 属性的值改�时被�� */ /*! \fn void DPlatformHandle::autoInputMaskByClipPathChanged() \brief 信�会在 autoInputMaskByClipPath 属性的值改�时被�� */ /*! \class Dtk::Gui::DPlatformHandle::WMBlurArea \inmodule dtkgui \brief �述窗�背景模糊区域的数�结构,包��置�大��圆角�径等信�. \var x 水平方�的�标 \var y 竖直方�的�标 \var width 区域的宽度 \var height 区域的高度 \var xRadius 水平方�的圆角�径 \var yRaduis 竖直方�的圆角�径 */ static DPlatformWindowInterfaceFactory::Creator OutsideWindowInterfaceCreator = nullptr; void DPlatformWindowInterfaceFactory::registerInterface(Creator creator) { OutsideWindowInterfaceCreator = creator; } static DPlatformWindowInterface *createWindowInterface(QWindow *window, DPlatformHandle *platformHandle) { DPlatformWindowInterface *impl = nullptr; if (OutsideWindowInterfaceCreator) { impl = OutsideWindowInterfaceCreator(window, platformHandle); } if (!impl) { #ifndef DTK_DISABLE_XCB if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsXWindowPlatform)) { impl = new DXCBPlatformWindowInterface(window, platformHandle); } #endif #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { impl = new DTreeLandPlatformWindowInterface(window, platformHandle); } #endif } return impl; } /*! \brief DPlatformHandle::DPlatformHandle 将 \a window 对象传递给 enableDXcbForWindow \a window �开�DTK风格的主窗� \a parent DPlatformHandle 对象的父对象 \sa DPlatformHandle::enableDXcbForWindow(QWindow *) */ DPlatformHandle::DPlatformHandle(QWindow *window, QObject *parent) : QObject(parent) , m_window(window) { auto impl = createWindowInterface(window, this); if (!impl) { qDebug() << "Use default DPlatformWindowInterface for the window" << window->winId(); impl = new DPlatformWindowInterface(window, this); } g_platformWindowImpls.insert(this, impl); impl->setEnabled(true); } DPlatformHandle::~DPlatformHandle() { if (auto item = g_platformWindowImpls.take(this)) { delete item; } } /*! \brief DPlatformHandle::pluginVersion \return 返回dxcb�件的版本 \note 在旧版dxcb�件中未实现获�版本的接�,将会返回一个空的 QString 对象 */ QString DPlatformHandle::pluginVersion() { #ifndef DTK_DISABLE_XCB return DXCBPlatformWindowInterface::pluginVersion(); #else return {}; #endif } /*! \brief DPlatformHandle::isDXcbPlatform 检查当�程�是�使用了dxcb平��件。 \return 正在使用返回 true,�则返回 false。 */ bool DPlatformHandle::isDXcbPlatform() { #ifndef DTK_DISABLE_XCB return DXCBPlatformWindowInterface::isDXcbPlatform(); #else return false; #endif } /*! \brief DPlatformHandle::enableDXcbForWindow 将 QWindow 的窗�装饰设置为 DTK 风格,这将使用 Qt::FramelessWindowHint 去除本地窗�管�器 给窗�附加的边框修饰以�窗�阴影效果,并且,会创建一个对应的本地窗�(在X11平�就是指X Window) 作为此窗�的父窗�,父窗�(Frame Window)中将根��窗�(Sub Window)的有效区域绘制阴影和边 框等效果,默认情况下,�窗�的有效区域为一个圆角矩形,结构如下: \raw HTML
  ������������������������������┓
  ┃    Frame Window             ┃
  ┃                             ┃
  ┃                             ┃
  ┃     ╭┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅╮     ┃
  ┃     ┋    Sub Window   ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ┋                 ┋     ┃
  ┃     ╰┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅╯     ┃
  ┃                             ┃
  ┃                             ┃
  ┃                             ┃
  ┗�����������������������������┛
  
\endraw 但是,如果窗å�£ç®¡ç�†å™¨è‡ªèº«æ”¯æŒ�éš�è—�窗å�£æ ‡é¢˜æ �,则此方法将优先调用 enableNoTitlebarForWindow 实现å�Œæ ·çš„æ•ˆæžœã€‚ 例å­�: \code QWidget w1; w1.setWindowTitle("使用系统边框的窗å�£"); w1.show(); DMainWindow w2; QWidget w3; w2.titlebar()->setTitle("使用DTK风格边框带标题æ �的窗å�£"); w3.setWindowTitle("使用DTK风格边框没有标题æ �的窗å�£"); w2.show(); DPlatformHandle::enableDXcbForWindow(&w3); w3.show(); // 因为这个窗å�£æ²¡æœ‰æ ‡é¢˜æ �,所以ä¸�会显示窗å�£æ ‡é¢˜ \endcode \image dtk_and_system_window.jpeg å¼€å�¯äº†dxcb的窗å�£ï¼Œåœ¨çª—å�£å¤–边缘10åƒ�素的范围按下鼠标左键å�¯ä»¥è§¦å�‘改å�˜çª—å�£å¤§å°�的行为, 而且会自动将鼠标å�¸é™„到对应的窗å�£è¾¹ç¼˜ï¼Œå¢žå¼ºäº†æ‹–拽改å�˜çª—å�£å¤§å°�的体验。效果: \image dtk_window_cursor_effect.gif å�¦å¤–,所有到达主窗å�£çš„鼠标移动事件如果没有调用 QEvent::accepted ,则会触å�‘主窗 å�£çš„移动效果,默认情况下,一个没有å­�控件的DTK窗å�£ï¼Œå¦‚果没有é‡�写 QWidget::mouseMoveEvent , 则使用鼠标左键在窗å�£çš„ä»»æ„�地方按ä½�并移动都会触å�‘移动窗å�£çš„动作。如: \code class Window : public QWidget { public: explicit Window() { } protected: void mouseMoveEvent(QMouseEvent *event) override { event->accept(); } }; \endcode \code Window w; DPlatformHandle::enableDXcbForWindow(&w); w.show(); \endcode 将无法使用鼠标移动窗å�£w 窗å�£ç®¡ç�†å™¨ï¼ˆå¦‚X11å¹³å�°ä¸Šçš„Window Manager)是å�¦æ”¯æŒ�æ··æˆ�会影å“�dxcbæ�’件对窗å�£æ·»åŠ çš„é»˜è®¤è£…é¥°ã€‚ \note 在 Deepin 桌é�¢çŽ¯å¢ƒä¸­ï¼Œæ‰“å¼€çª—å�£ç‰¹æ•ˆåˆ™æ”¯æŒ�æ··æˆ�,关闭窗å�£ç‰¹æ•ˆåˆ™ä¸�支æŒ�æ··æˆ� 支æŒ�æ··æˆ�: \image enable_composite.png ä¸�支æŒ�æ··æˆ�: \image disable_composite.png 并且,在ä¸�支æŒ�æ··æˆ�的窗å�£ç®¡ç�†å™¨ä¸­ï¼Œä¸Šè¿°â€œçª—å�£è¾¹ç¼˜çš„é¼ æ ‡å�¸é™„â€�效果也会被ç¦�用。å�¯ä»¥ä½¿ç”¨ DWindowManagerHelper::hasComposite 或 QX11Info::isCompositingManagerRunning 判断当å‰�è¿�行的窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�æ··æˆ�。 \a window \sa Dtk::Gui::DPlatformHandle::setEnabledNoTitlebarForWindow() */ void DPlatformHandle::enableDXcbForWindow(QWindow *window) { DPlatformHandle handle(window); auto impl = platformWindowImpl(&handle); impl->setEnabled(true); } /*! \brief DPlatformHandle::enableDXcbForWindow 功能上和 DPlatformHandle::enableDXcbForWindow(QWindow *) 一致. \a window \a redirectContent 如果值为 true,Sub Window å°†ä¸�å�¯è§�,且它的绘制内容会 被å�ˆæˆ�到外层的 Frame Window(它的父窗å�£ï¼‰ï¼Œå�¦åˆ™ Sub Window å’Œ Frame Window 会分开绘制和显示。默认情况下å�ªéœ€è¦�使用 DPlatformHandle::enableDXcbForWindow(QWindow *), dxcbæ�’件中会自动根æ�®çª—å�£æ¸²æŸ“类型选择使用更å�ˆé€‚的实现方å¼�,使用 OpenGL 渲染的窗å�£å°†å¼€å�¯ redirectContent 模å¼�。 \note 如果窗å�£å†…嵌入了其它的本地窗å�£ï¼ˆå¦‚X11å¹³å�°çš„X Window),默认情况下,这个窗å�£ 绘制的内容ä¸�å�—dxcbæ�’件的控制,它的绘制内容å�¯èƒ½ä¼šè¶…过 Sub Window 的有效区域,这ç§� 情况下,应该使用此接å�£ï¼Œå¹¶å°† redirectContent 指定为 true。 \ref {https://www.x.org/releases/X11R7.5/doc/damageproto/damageproto.txt}{X11 Damage} */ void DPlatformHandle::enableDXcbForWindow(QWindow *window, bool redirectContent) { DPlatformHandle handle(window); #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { impl->enableDXcb(redirectContent); } #endif } /*! \brief DPlatformHandle::isEnabledDXcb. \return 如果窗å�£ \a window å¼€å�¯äº†DTK风格的窗å�£ä¿®é¥°åˆ™è¿”回 true,å�¦åˆ™è¿”回 false \sa DPlatformHandle::isEnabledNoTitlebar() */ bool DPlatformHandle::isEnabledDXcb(const QWindow *window) { DPlatformHandle handle(const_cast(window)); auto impl = platformWindowImpl(&handle); return impl->isEnabled(); } /*! \brief DPlatformHandle::setEnabledNoTitlebarForWindow. 使用窗å�£ç®¡ç�†å™¨æ��供的方å¼�éš�è—�窗å�£çš„æ ‡é¢˜æ �,目å‰�已适é…� DDE KWin 窗管,在窗å�£ç®¡ç�†å™¨æ”¯æŒ�çš„å‰�æ��下, 此方法将通过设置窗å�£å±žæ€§ _DEEPIN_SCISSOR_WINDOW 的值为 1 æ�¥å¼€å�¯æ— æ ‡é¢˜æ �效果。 \a window 被设置的 QWindow 实例. \a enable 是å�¦å¼€å�¯æ— æ ‡é¢˜å±žæ€§. \return 设置æˆ�功返回 true,å�¦åˆ™è¿”回false. \sa DPlatformHandle::enableDXcbForWindow() \sa DWindowManagerHelper::hasNoTitlebar() */ bool DPlatformHandle::setEnabledNoTitlebarForWindow(QWindow *window, bool enable) { DPlatformHandle handle(window); auto impl = platformWindowImpl(&handle); return impl->setEnabledNoTitlebar(enable); } /*! \brief DPlatformHandle::isEnableNoTitlebar \a window \return 如果窗å�£ä½¿ç”¨çª—管æ��供的方å¼�éš�è—�了标题æ �则返回 true,å�¦åˆ™è¿”回 false \sa DPlatformHandle::isEnabledDXcb */ bool DPlatformHandle::isEnabledNoTitlebar(const QWindow *window) { DPlatformHandle handle(const_cast(window)); auto impl = platformWindowImpl(&handle); return impl->isEnabledNoTitlebar(); } /*! \brief DPlatformHandle::setWindowBlurAreaByWM 设置窗å�£èƒŒæ™¯çš„æ¨¡ç³ŠåŒºåŸŸï¼Œç¤ºä¾‹ï¼š \code QWindow w; QVector area_list; DPlatformHandle::WMBlurArea area; area.x = 50; area.y = 50; area.width = 200; area.height = 200; area.xRadius = 10; area.yRaduis = 10; area_list.append(area); DPlatformHandle::setWindowBlurAreaByWM(&w, area_list); QSurfaceFormat format = w.format(); format.setAlphaBufferSize(8); w.setFormat(format); w.resize(300, 300); w.show(); \endcode \image blur_window_demo1.png \a window 目标窗å�£å¯¹è±¡ \a area 模糊区域,此区域范围内的窗å�£èƒŒæ™¯å°†å¡«å……为窗å�£å�Žé�¢å†…容模糊之å�Žçš„图åƒ� \return 如果设置æˆ�功则返回 true,å�¦åˆ™è¿”回 false \note 对于需è¦�显示模糊背景的窗å�£ï¼Œéœ€è¦�将其 QSurfaceFormat çš„ alpha 通é�“设置为8 \note 调用此接å�£è®¾ç½®çª—å�£èƒŒæ™¯æ¨¡ç³ŠåŒºåŸŸå�Žå°†è¦†ç›–之å‰�所设置的区域,包括调用 setWindowBlurAreaByWM(QWindow *, const QList &) 所设置的区域 \note 建议使用 DBlurEffectWidget 实现窗å�£èƒŒæ™¯æ¨¡ç³Šæ•ˆæžœ \note 此功能ä¾�赖于窗å�£ç®¡ç�†å™¨çš„实现,目å‰�仅支æŒ� deepin-wm å’Œ kwin 这两个窗å�£ç®¡ç�†å™¨ \sa Dtk::Widget::DBlurEffectWidget \sa QSurfaceFormat::setAlphaBufferSize \sa QWindow::setFormat \sa DWindowManagerHelper::hasBlurWindow \sa DPlatformHandle::setWindowBlurAreaByWM(QWindow *, const QList &) */ bool DPlatformHandle::setWindowBlurAreaByWM(QWindow *window, const QVector &area) { DPlatformHandle handle(const_cast(window)); #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { return impl->setWindowBlurArea(area); } #endif handle.setEnableBlurWindow(true); return true; } /*! \brief DPlatformHandle::setWindowBlurAreaByWM 设置窗å�£èƒŒæ™¯çš„æ¨¡ç³ŠåŒºåŸŸï¼Œä½¿ç”¨ QPainterPath æ��述模糊区域,使用起æ�¥æ›´åŠ çš„ç�µæ´»ï¼Œå�¯ä»¥ 实现任何形状,但是性能è¦�低于使用 QVector æ��述模糊区域。示例: \code QWindow w; QList path_list; QPainterPath path; QFont font; font.setPixelSize(100); font.setBold(true); path.addText(0, 150, font, "deepin"); path_list.append(path); DPlatformHandle::setWindowBlurAreaByWM(&w, path_list); QSurfaceFormat format = w.format(); format.setAlphaBufferSize(8); w.setFormat(format); w.resize(300, 300); w.show(); \endcode \image blur_window_demo2.png \a window 目标窗å�£å¯¹è±¡ \a paths 模糊区域,此区域范围内的窗å�£èƒŒæ™¯å°†å¡«å……为窗å�£å�Žé�¢å†…容模糊之å�Žçš„图åƒ� \return 如果设置æˆ�功则返回 true,å�¦åˆ™è¿”回 false \note 调用此接å�£è®¾ç½®çª—å�£èƒŒæ™¯æ¨¡ç³ŠåŒºåŸŸå�Žå°†è¦†ç›–之å‰�所设置的区域,包括调用 setWindowBlurAreaByWM(QWindow *, QVector &) 设置的窗å�£èƒŒæ™¯æ¨¡ç³Šè·¯å¾„ \note 对于需è¦�显示模糊背景的窗å�£ï¼Œéœ€è¦�将其 QSurfaceFormat çš„ alpha 通é�“设置为8 \note 建议使用 DBlurEffectWidget 实现窗å�£èƒŒæ™¯æ¨¡ç³Šæ•ˆæžœ \note 此功能ä¾�赖于窗å�£ç®¡ç�†å™¨çš„实现,目å‰�仅支æŒ� deepin-wm å’Œ kwin 这两个窗å�£ç®¡ç�†å™¨ \warning setWindowBlurAreaByWM(QWindow *, QVector &) 能满足需求请ä¸�è¦�使用此接å�£ \sa Dtk::Widget::DBlurEffectWidget \sa QSurfaceFormat::setAlphaBufferSize \sa QWindow::setFormat \sa DWindowManagerHelper::hasBlurWindow \sa DPlatformHandle::setWindowBlurAreaByWM() */ bool DPlatformHandle::setWindowBlurAreaByWM(QWindow *window, const QList &paths) { DPlatformHandle handle(const_cast(window)); #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { return impl->setWindowBlurArea(paths); } #endif handle.setEnableBlurWindow(true); return true; } /*! \brief DPlatformHandle::setWindowWallpaperParaByWM 设置窗å�£èƒŒæ™¯å£�纸,示例: \code QWindow w; QRect area; WallpaperScaleMode sMode WallpaperFillMode fMode area.setRect(50, 50, 200, 200); bMode = WallpaperScaleFlag::FollowWindow | WallpaperFillFlag::PreserveAspectCrop; DPlatformHandle::setWindowWallpaperParaByWM(&w, area, bMode); QSurfaceFormat format = w.format(); format.setAlphaBufferSize(8); w.setFormat(format); w.resize(300, 300); w.show(); \endcode \a window 目标窗å�£å¯¹è±¡ \a area å£�纸区域,此区域范围内的窗å�£èƒŒæ™¯å°†å¡«å……为用户设置的当å‰�工作区窗å�£å£�纸 \~Chinese \a sMode 控制å£�纸缩放是éš�å±�幕还是éš�窗å�£ \~Chinese \a fMode 控制å£�纸是缩放还是è£�剪 \return 如果设置æˆ�功则返回 true,å�¦åˆ™è¿”回 false \note 对于需è¦�显示openglå£�纸特效的窗å�£ï¼Œéœ€è¦�将其 QSurfaceFormat çš„ alpha 通é�“设置为8 \note 需è¦�在window handle有效之å�Žè°ƒç”¨å�¦åˆ™3d下失效 \note 调用此接å�£è®¾ç½®çª—å�£èƒŒæ™¯å£�纸区域å�Žå°†è¦†ç›–之å‰�所设置的区域 \note 此功能ä¾�赖于窗å�£ç®¡ç�†å™¨çš„实现,目å‰�仅支æŒ� kwin 窗å�£ç®¡ç�†å™¨ \sa Dtk::Widget::DBlurEffectWidget \sa QSurfaceFormat::setAlphaBufferSize \sa QWindow::setFormat \sa DWindowManagerHelper::hasBlurWindow \sa DPlatformHandle::setWindowBlurAreaByWM(QWindow *, const QList &) */ bool DPlatformHandle::setWindowWallpaperParaByWM(QWindow *window, const QRect &area, WallpaperScaleMode sMode, WallpaperFillMode fMode) { DPlatformHandle handle(window); #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { return impl->setWindowWallpaperPara(area, sMode, fMode); } #endif return false; } /*! \brief DPlatformHandle::connectWindowManagerChangedSignal 将窗å�£ç®¡ç�†å™¨å�˜åŒ–的信å�·é“¾æŽ¥åˆ° \a object 对象的 \a slot 槽,建议使用 DWindowManager::windowManagerChanged \a object \a slot \return 如果链接æˆ�功则返回 true,å�¦åˆ™è¿”回 false \sa DWindowManagerHelper::windowManagerChanged() */ bool DPlatformHandle::connectWindowManagerChangedSignal(QObject *object, std::function slot) { #ifndef DTK_DISABLE_XCB return DXCBPlatformWindowInterface::connectWindowManagerChangedSignal(object, slot); #endif return false; } /*! \brief DPlatformHandle::connectHasBlurWindowChanged 将窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�背景模糊的信å�·é“¾æŽ¥åˆ° object 对象的 slot 槽,建议使用 DWindowManager::hasBlurWindowChanged \a object \a slot \return 如果链接æˆ�功则返回 true,å�¦åˆ™è¿”回 false \sa DWindowManagerHelper::hasBlurWindowChanged */ bool DPlatformHandle::connectHasBlurWindowChanged(QObject *object, std::function slot) { #ifndef DTK_DISABLE_XCB return DXCBPlatformWindowInterface::connectHasBlurWindowChanged(object, slot); #endif return false; } /*! \brief DPlatformHandle::setWindowBlurAreaByWM è¿™å�ªæ˜¯ä¸€ä¸ªé‡�载的函数,将调用 setWindowBlurAreaByWM(const QList &paths) 并将构造对象时传递的主窗å�£å½“å�šç¬¬ä¸€ä¸ªå�‚æ•° \a area \return \sa DPlatformHandle::setWindowBlurAreaByWM(const QList &paths) */ bool DPlatformHandle::setWindowBlurAreaByWM(const QVector &area) { return setWindowBlurAreaByWM(m_window, area); } /*! \brief DPlatformHandle::setWindowBlurAreaByWM è¿™å�ªæ˜¯ä¸€ä¸ªé‡�载的函数,将调用 setWindowBlurAreaByWM(const QVector &area) 并将构造对象时传递的主窗å�£å½“å�šç¬¬ä¸€ä¸ªå�‚æ•° \a paths \return \sa DPlatformHandle::setWindowBlurAreaByWM() */ bool DPlatformHandle::setWindowBlurAreaByWM(const QList &paths) { return setWindowBlurAreaByWM(m_window, paths); } /*! \brief DPlatformHandle::setDisableWindowOverrideCursor 如果 \a disable 为 true,则ç¦�止窗å�£ \a window 改å�˜å…‰æ ‡æ ·å¼�,å�¦åˆ™å…�许改å�˜å…‰æ ‡æ ·å¼�。 窗å�£è¢«ç¦�止改å�˜å…‰æ ‡æ ·å¼�å�Žï¼Œä½¿ç”¨ QWindow::setCursor å°†ä¸�会产生任何效果。 \a window \a disable */ void DPlatformHandle::setDisableWindowOverrideCursor(QWindow *window, bool disable) { DPlatformHandle handler(window); #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(&handler))) { impl->setDisableWindowOverrideCursor(disable); } #endif } int DPlatformHandle::windowRadius() const { auto impl = platformWindowImpl(this); return impl->windowRadius(); } int DPlatformHandle::borderWidth() const { auto impl = platformWindowImpl(this); return impl->borderWidth(); } QColor DPlatformHandle::borderColor() const { auto impl = platformWindowImpl(this); return impl->borderColor(); } int DPlatformHandle::shadowRadius() const { auto impl = platformWindowImpl(this); return impl->shadowRadius(); } QPoint DPlatformHandle::shadowOffset() const { auto impl = platformWindowImpl(this); return impl->shadowOffset(); } QColor DPlatformHandle::shadowColor() const { auto impl = platformWindowImpl(this); return impl->shadowColor(); } DPlatformHandle::EffectScene DPlatformHandle::windowEffect() { auto impl = platformWindowImpl(this); return impl->windowEffect(); } DPlatformHandle::EffectType DPlatformHandle::windowStartUpEffect() { auto impl = platformWindowImpl(this); return impl->windowStartUpEffect(); } QPainterPath DPlatformHandle::clipPath() const { auto impl = platformWindowImpl(this); return impl->clipPath(); } QRegion DPlatformHandle::frameMask() const { auto impl = platformWindowImpl(this); return impl->frameMask(); } QMargins DPlatformHandle::frameMargins() const { auto impl = platformWindowImpl(this); return impl->frameMargins(); } bool DPlatformHandle::translucentBackground() const { auto impl = platformWindowImpl(this); return impl->translucentBackground(); } bool DPlatformHandle::enableSystemResize() const { auto impl = platformWindowImpl(this); return impl->enableSystemResize(); } bool DPlatformHandle::enableSystemMove() const { auto impl = platformWindowImpl(this); return impl->enableSystemMove(); } bool DPlatformHandle::enableBlurWindow() const { auto impl = platformWindowImpl(this); return impl->enableBlurWindow(); } bool DPlatformHandle::autoInputMaskByClipPath() const { #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(this))) { return impl->autoInputMaskByClipPath(); } #endif return false; } WId DPlatformHandle::realWindowId() const { #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(this))) { return impl->realWindowId(); } #endif return 0; } WId DPlatformHandle::windowLeader() { #ifndef DTK_DISABLE_XCB return DXCBPlatformWindowInterface::windowLeader(); #endif return 0; } void DPlatformHandle::setWindowRadius(int windowRadius) { auto impl = platformWindowImpl(this); impl->setWindowRadius(windowRadius); } void DPlatformHandle::setBorderWidth(int borderWidth) { auto impl = platformWindowImpl(this); impl->setBorderWidth(borderWidth); } void DPlatformHandle::setBorderColor(const QColor &borderColor) { auto impl = platformWindowImpl(this); impl->setBorderColor(borderColor); } void DPlatformHandle::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { auto impl = platformWindowImpl(this); impl->setWindowEffect(effectScene); } void DPlatformHandle::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) { auto impl = platformWindowImpl(this); impl->setWindowStartUpEffect(effectType); } void DPlatformHandle::setShadowRadius(int shadowRadius) { auto impl = platformWindowImpl(this); impl->setShadowRadius(shadowRadius); } void DPlatformHandle::setShadowOffset(const QPoint &shadowOffset) { auto impl = platformWindowImpl(this); impl->setShadowOffset(shadowOffset); } void DPlatformHandle::setShadowColor(const QColor &shadowColor) { auto impl = platformWindowImpl(this); impl->setShadowColor(shadowColor); } void DPlatformHandle::setClipPath(const QPainterPath &clipPath) { auto impl = platformWindowImpl(this); impl->setClipPath(clipPath); } void DPlatformHandle::setFrameMask(const QRegion &frameMask) { auto impl = platformWindowImpl(this); impl->setFrameMask(frameMask); } void DPlatformHandle::setTranslucentBackground(bool translucentBackground) { auto impl = platformWindowImpl(this); impl->setTranslucentBackground(translucentBackground); } void DPlatformHandle::setEnableSystemResize(bool enableSystemResize) { auto impl = platformWindowImpl(this); impl->setEnableSystemResize(enableSystemResize); } void DPlatformHandle::setEnableSystemMove(bool enableSystemMove) { auto impl = platformWindowImpl(this); impl->setEnableSystemMove(enableSystemMove); } void DPlatformHandle::setEnableBlurWindow(bool enableBlurWindow) { auto impl = platformWindowImpl(this); impl->setEnableBlurWindow(enableBlurWindow); } void DPlatformHandle::setAutoInputMaskByClipPath(bool autoInputMaskByClipPath) { #ifndef DTK_DISABLE_XCB if (auto impl = dynamic_cast(platformWindowImpl(this))) { impl->setAutoInputMaskByClipPath(autoInputMaskByClipPath); } #endif } bool DPlatformHandle::eventFilter(QObject *obj, QEvent *event) { return QObject::eventFilter(obj, event); } DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE QDebug operator<<(QDebug deg, const DPlatformHandle::WMBlurArea &area) { QDebugStateSaver saver(deg); Q_UNUSED(saver) deg.setAutoInsertSpaces(true); deg << "x:" << area.x << "y:" << area.y << "width:" << area.width << "height:" << area.height << "xRadius:" << area.xRadius << "yRadius:" << area.yRaduis; return deg; } QT_END_NAMESPACE dtkgui-6.7.46/src/kernel/dplatformtheme.cpp000066400000000000000000000624311522615413000207000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dplatformtheme.h" #include "dguiapplicationhelper.h" #include "private/dplatformtheme_p.h" #ifndef DTK_DISABLE_XCB #include "plugins/platform/xcb/dxcbplatforminterface.h" #endif #ifndef DTK_DISABLE_TREELAND #include "plugins/platform/treeland/dtreelandplatforminterface.h" #endif #include "private/dplatforminterface_p.h" #include "orgdeepindtkpreference.hpp" #include #include #include #include #include DGUI_BEGIN_NAMESPACE static DPlatformInterfaceFactory::HelperCreator OutsideInterfaceCreator = nullptr; void DPlatformInterfaceFactory::registerInterface(HelperCreator creator) { OutsideInterfaceCreator = creator; } // "/deepin/palette" 为调色æ�¿å±žæ€§çš„存储ä½�ç½® // 在x11å¹³å�°ä¸‹ï¼Œå°†ä½¿ç”¨_DEEPIN_PALETTE作为存储调色æ�¿æ•°æ�®çš„窗å�£å±žæ€§ DPlatformThemePrivate::DPlatformThemePrivate(Dtk::Gui::DPlatformTheme *qq) : DNativeSettingsPrivate(qq, QByteArrayLiteral("/deepin/palette")) { } void DPlatformThemePrivate::onQtColorChanged(QPalette::ColorRole role, const QColor &color) { if (!palette) { palette = new DPalette(); } palette->setColor(QPalette::Normal, role, color); notifyPaletteChanged(); } void DPlatformThemePrivate::onDtkColorChanged(DPalette::ColorType type, const QColor &color) { if (!palette) { palette = new DPalette(); } palette->setColor(QPalette::Normal, type, color); notifyPaletteChanged(); } void DPlatformThemePrivate::notifyPaletteChanged() { if (notifyPaletteChangeTimer && notifyPaletteChangeTimer->isActive()) return; D_Q(DPlatformTheme); if (!notifyPaletteChangeTimer) { notifyPaletteChangeTimer = new QTimer(q); q->connect(notifyPaletteChangeTimer, &QTimer::timeout, q, [q, this] { Q_EMIT q->paletteChanged(*palette); }); } notifyPaletteChangeTimer->start(300); } /*! \class Dtk::Gui::DPlatformTheme \inmodule dtkgui \brief 一个æ��供窗å�£ä¸»é¢˜çš„ç±». */ DPlatformTheme::DPlatformTheme(quint32 window, QObject *parent) : DNativeSettings(*new DPlatformThemePrivate(this), &DPlatformTheme::staticMetaObject, window, parent) { D_D(DPlatformTheme); if (OutsideInterfaceCreator) { d->platformInterface = OutsideInterfaceCreator(this); } else { #ifndef DTK_DISABLE_XCB if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsXWindowPlatform)) { d->platformInterface = new DXCBPlatformInterface(0, this); } #endif #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { d->platformInterface = new DTreelandPlatformInterface(this); } #endif } if (!d->platformInterface) { d->platformInterface = new DPlatformInterface(this); } d->theme = new DNativeSettings(window, QByteArray(), this); d->dtkPreferenceConfig = OrgDeepinDTKPreference::createGeneric("", this); d->sizeMode = static_cast(d->dtkPreferenceConfig->sizeMode()); d->scrollBarPolicy = static_cast(d->dtkPreferenceConfig->scrollBarPolicy()); connect(d->dtkPreferenceConfig, &OrgDeepinDTKPreference::sizeModeChanged, this, [this] { D_D(DPlatformTheme); d->sizeMode = static_cast(d->dtkPreferenceConfig->sizeMode()); Q_EMIT sizeModeChanged(d->sizeMode); }); connect(d->dtkPreferenceConfig, &OrgDeepinDTKPreference::scrollBarPolicyChanged, this, [this] { D_D(DPlatformTheme); d->scrollBarPolicy = static_cast(d->dtkPreferenceConfig->scrollBarPolicy()); Q_EMIT scrollBarPolicyChanged(d->scrollBarPolicy); }); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) connect(this, &DPlatformTheme::windowChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Window, std::placeholders::_1)); connect(this, &DPlatformTheme::windowTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::WindowText, std::placeholders::_1)); connect(this, &DPlatformTheme::baseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Base, std::placeholders::_1)); connect(this, &DPlatformTheme::alternateBaseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::AlternateBase, std::placeholders::_1)); connect(this, &DPlatformTheme::toolTipBaseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ToolTipBase, std::placeholders::_1)); connect(this, &DPlatformTheme::toolTipTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ToolTipText, std::placeholders::_1)); connect(this, &DPlatformTheme::textChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Text, std::placeholders::_1)); connect(this, &DPlatformTheme::buttonChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Button, std::placeholders::_1)); connect(this, &DPlatformTheme::buttonTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ButtonText, std::placeholders::_1)); connect(this, &DPlatformTheme::brightTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::BrightText, std::placeholders::_1)); connect(this, &DPlatformTheme::lightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Light, std::placeholders::_1)); connect(this, &DPlatformTheme::midlightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Midlight, std::placeholders::_1)); connect(this, &DPlatformTheme::darkChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Dark, std::placeholders::_1)); connect(this, &DPlatformTheme::midChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Mid, std::placeholders::_1)); connect(this, &DPlatformTheme::shadowChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Shadow, std::placeholders::_1)); connect(this, &DPlatformTheme::highlightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Highlight, std::placeholders::_1)); connect(this, &DPlatformTheme::highlightedTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::HighlightedText, std::placeholders::_1)); connect(this, &DPlatformTheme::linkChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Link, std::placeholders::_1)); connect(this, &DPlatformTheme::linkVisitedChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::LinkVisited, std::placeholders::_1)); connect(this, &DPlatformTheme::itemBackgroundChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::ItemBackground, std::placeholders::_1)); connect(this, &DPlatformTheme::textTitleChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextTitle, std::placeholders::_1)); connect(this, &DPlatformTheme::textTipsChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextTips, std::placeholders::_1)); connect(this, &DPlatformTheme::textWarningChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextWarning, std::placeholders::_1)); connect(this, &DPlatformTheme::textLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextLively, std::placeholders::_1)); connect(this, &DPlatformTheme::lightLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::LightLively, std::placeholders::_1)); connect(this, &DPlatformTheme::darkLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::DarkLively, std::placeholders::_1)); connect(this, &DPlatformTheme::frameBorderChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::FrameBorder, std::placeholders::_1)); #endif } DPlatformTheme::DPlatformTheme(quint32 window, DPlatformTheme *parent) : DPlatformTheme(window, static_cast(parent)) { d_func()->parent = parent; // 将主题相关的属性改å�˜ä¿¡å�·ä»Žçˆ¶ä¸»é¢˜ä¸­ç»§æ‰¿ // å�‡è®¾ A 被 B 继承,B 被 C 继承,当 A 中出å�‘属性å�˜åŒ–时,ä¸�ä»…è¦�能通知到B,还è¦�能通知到C connect(parent->d_func()->theme, SIGNAL(propertyChanged(const QByteArray &, const QVariant &)), d_func()->theme, SIGNAL(propertyChanged(const QByteArray &, const QVariant &))); } DPlatformTheme::~DPlatformTheme() { D_D(DPlatformTheme); if (d->palette) { delete d->palette; } if (d->platformInterface) { delete d->platformInterface; } } bool DPlatformTheme::isValid() const { return !themeName().isEmpty() || isValidPalette() || activeColor().isValid(); } DPlatformTheme *DPlatformTheme::parentTheme() const { D_DC(DPlatformTheme); return d->parent; } void DPlatformTheme::setFallbackProperty(bool fallback) { D_D(DPlatformTheme); d->fallbackProperty = fallback; } DPalette DPlatformTheme::palette() const { D_DC(DPlatformTheme); if (!d->palette) { if (!isValid()) return DPalette(); DPalette *pa = new DPalette(); const_cast(d)->palette = pa; #define SET_PALETTE_COLOR(Role) \ pa->setColor(DPalette::Role, qvariant_cast(getSetting(QByteArrayLiteral(#Role)))) SET_PALETTE_COLOR(Window); SET_PALETTE_COLOR(WindowText); SET_PALETTE_COLOR(Base); SET_PALETTE_COLOR(AlternateBase); SET_PALETTE_COLOR(ToolTipBase); SET_PALETTE_COLOR(ToolTipText); SET_PALETTE_COLOR(Text); SET_PALETTE_COLOR(Button); SET_PALETTE_COLOR(ButtonText); SET_PALETTE_COLOR(BrightText); SET_PALETTE_COLOR(Light); SET_PALETTE_COLOR(Midlight); SET_PALETTE_COLOR(Dark); SET_PALETTE_COLOR(Mid); SET_PALETTE_COLOR(Shadow); SET_PALETTE_COLOR(Highlight); SET_PALETTE_COLOR(HighlightedText); SET_PALETTE_COLOR(Link); SET_PALETTE_COLOR(LinkVisited); SET_PALETTE_COLOR(ItemBackground); SET_PALETTE_COLOR(TextTitle); SET_PALETTE_COLOR(TextTips); SET_PALETTE_COLOR(TextWarning); SET_PALETTE_COLOR(TextLively); SET_PALETTE_COLOR(LightLively); SET_PALETTE_COLOR(DarkLively); SET_PALETTE_COLOR(FrameBorder); } return *d->palette; } DPalette DPlatformTheme::fetchPalette(const DPalette &base, bool *ok) const { D_DC(DPlatformTheme); DPalette palette = base; if (isValidPalette() && d->palette) { if (ok) { *ok = true; } const DPalette *pa = d->palette; for (int i = 0; i < QPalette::NColorRoles; ++i) { const QColor &color = pa->color(QPalette::Normal, static_cast(i)); if (color.isValid()) { palette.setColor(QPalette::Normal, static_cast(i), color); } } for (int i = 0; i < DPalette::NColorTypes; ++i) { const QColor &color = pa->color(QPalette::Normal, static_cast(i)); if (color.isValid()) { palette.setColor(QPalette::Normal, static_cast(i), color); } } return d->parent ? d->parent->fetchPalette(palette, nullptr) : palette; } return d->parent ? d->parent->fetchPalette(palette, ok) : palette; } void DPlatformTheme::setPalette(const DPalette &palette) { Q_UNUSED(palette); #define SET_PALETTE(Role) \ set##Role(palette.color(QPalette::Normal, DPalette::Role)) #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) SET_PALETTE(Window); SET_PALETTE(WindowText); SET_PALETTE(Base); SET_PALETTE(AlternateBase); SET_PALETTE(ToolTipBase); SET_PALETTE(ToolTipText); SET_PALETTE(Text); SET_PALETTE(Button); SET_PALETTE(ButtonText); SET_PALETTE(BrightText); SET_PALETTE(Light); SET_PALETTE(Midlight); SET_PALETTE(Dark); SET_PALETTE(Mid); SET_PALETTE(Shadow); SET_PALETTE(Highlight); SET_PALETTE(HighlightedText); SET_PALETTE(Link); SET_PALETTE(LinkVisited); SET_PALETTE(ItemBackground); SET_PALETTE(TextTitle); SET_PALETTE(TextTips); SET_PALETTE(TextWarning); SET_PALETTE(TextLively); SET_PALETTE(LightLively); SET_PALETTE(DarkLively); SET_PALETTE(FrameBorder); #endif } int DPlatformTheme::cursorBlinkTime() const { D_DC(DPlatformTheme); return d->platformInterface->cursorBlinkTime(); } int DPlatformTheme::cursorBlinkTimeout() const { D_DC(DPlatformTheme); return d->platformInterface->cursorBlinkTimeout(); } bool DPlatformTheme::cursorBlink() const { D_DC(DPlatformTheme); return d->platformInterface->cursorBlink(); } int DPlatformTheme::doubleClickDistance() const { D_DC(DPlatformTheme); return d->platformInterface->doubleClickDistance(); } int DPlatformTheme::doubleClickTime() const { D_DC(DPlatformTheme); return d->platformInterface->doubleClickTime(); } int DPlatformTheme::dndDragThreshold() const { D_DC(DPlatformTheme); return d->platformInterface->dndDragThreshold(); } int DPlatformTheme::windowRadius() const { D_DC(DPlatformTheme); return d->platformInterface->windowRadius(); } int DPlatformTheme::windowRadius(int defaultValue) const { D_DC(DPlatformTheme); return d->platformInterface->windowRadius(defaultValue); } QByteArray DPlatformTheme::themeName() const { D_DC(DPlatformTheme); return d->platformInterface->themeName(); } QByteArray DPlatformTheme::iconThemeName() const { D_DC(DPlatformTheme); return d->platformInterface->iconThemeName(); } QByteArray DPlatformTheme::soundThemeName() const { D_DC(DPlatformTheme); return d->platformInterface->soundThemeName(); } QByteArray DPlatformTheme::fontName() const { D_DC(DPlatformTheme); return d->platformInterface->fontName(); } QByteArray DPlatformTheme::monoFontName() const { D_DC(DPlatformTheme); return d->platformInterface->monoFontName(); } qreal DPlatformTheme::fontPointSize() const { D_DC(DPlatformTheme); return d->platformInterface->fontPointSize(); } QByteArray DPlatformTheme::gtkFontName() const { D_DC(DPlatformTheme); return d->platformInterface->gtkFontName(); } QColor DPlatformTheme::activeColor() const { D_DC(DPlatformTheme); return d->platformInterface->activeColor(); } QColor DPlatformTheme::darkActiveColor() const { D_DC(DPlatformTheme); return d->platformInterface->darkActiveColor(); } bool DPlatformTheme::isValidPalette() const { return !allKeys().isEmpty(); } #define GET_COLOR(Role) qvariant_cast(getSetting(QByteArrayLiteral(#Role))) #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QColor DPlatformTheme::window() const { D_DC(DPlatformTheme); return d->platformInterface->window(); } QColor DPlatformTheme::windowText() const { D_DC(DPlatformTheme); return d->platformInterface->windowText(); } QColor DPlatformTheme::base() const { D_DC(DPlatformTheme); return d->platformInterface->base(); } QColor DPlatformTheme::alternateBase() const { D_DC(DPlatformTheme); return d->platformInterface->alternateBase(); } QColor DPlatformTheme::toolTipBase() const { D_DC(DPlatformTheme); return d->platformInterface->toolTipBase(); } QColor DPlatformTheme::toolTipText() const { D_DC(DPlatformTheme); return d->platformInterface->toolTipText(); } QColor DPlatformTheme::text() const { D_DC(DPlatformTheme); return d->platformInterface->text(); } QColor DPlatformTheme::button() const { D_DC(DPlatformTheme); return d->platformInterface->button(); } QColor DPlatformTheme::buttonText() const { D_DC(DPlatformTheme); return d->platformInterface->buttonText(); } QColor DPlatformTheme::brightText() const { D_DC(DPlatformTheme); return d->platformInterface->brightText(); } QColor DPlatformTheme::light() const { D_DC(DPlatformTheme); return d->platformInterface->light(); } QColor DPlatformTheme::midlight() const { D_DC(DPlatformTheme); return d->platformInterface->midlight(); } QColor DPlatformTheme::dark() const { D_DC(DPlatformTheme); return d->platformInterface->dark(); } QColor DPlatformTheme::mid() const { D_DC(DPlatformTheme); return d->platformInterface->mid(); } QColor DPlatformTheme::shadow() const { D_DC(DPlatformTheme); return d->platformInterface->shadow(); } QColor DPlatformTheme::highlight() const { D_DC(DPlatformTheme); return d->platformInterface->highlight(); } QColor DPlatformTheme::highlightedText() const { D_DC(DPlatformTheme); return d->platformInterface->highlightedText(); } QColor DPlatformTheme::link() const { D_DC(DPlatformTheme); return d->platformInterface->link(); } QColor DPlatformTheme::linkVisited() const { D_DC(DPlatformTheme); return d->platformInterface->linkVisited(); } QColor DPlatformTheme::itemBackground() const { D_DC(DPlatformTheme); return d->platformInterface->itemBackground(); } QColor DPlatformTheme::textTitle() const { D_DC(DPlatformTheme); return d->platformInterface->textTitle(); } QColor DPlatformTheme::textTips() const { D_DC(DPlatformTheme); return d->platformInterface->textTips(); } QColor DPlatformTheme::textWarning() const { D_DC(DPlatformTheme); return d->platformInterface->textWarning(); } QColor DPlatformTheme::textLively() const { D_DC(DPlatformTheme); return d->platformInterface->textLively(); } QColor DPlatformTheme::lightLively() const { D_DC(DPlatformTheme); return d->platformInterface->lightLively(); } QColor DPlatformTheme::darkLively() const { D_DC(DPlatformTheme); return d->platformInterface->darkLively(); } QColor DPlatformTheme::frameBorder() const { D_DC(DPlatformTheme); return d->platformInterface->frameBorder(); } #endif int DPlatformTheme::dotsPerInch(const QString &screenName) const { D_DC(DPlatformTheme); return d->platformInterface->dotsPerInch(screenName); } /*! \property DPlatformTheme::sizeMode \brief This property holds the sizeMode of the system's SizeMode. */ int DPlatformTheme::sizeMode() const { D_DC(DPlatformTheme); return d->sizeMode; } /*! \property DPlatformTheme::scrollBarPolicy \brief This property holds the scrollBarPolicy of the system. same as Qt::ScrollBarPolicy \retval 0 show as needed auto hide, default \retval 1 always off \retval 2 always on */ int DPlatformTheme::scrollBarPolicy() const { D_DC(DPlatformTheme); return d->scrollBarPolicy; } void DPlatformTheme::setCursorBlinkTime(int cursorBlinkTime) { D_DC(DPlatformTheme); return d->platformInterface->setCursorBlinkTime(cursorBlinkTime); } void DPlatformTheme::setCursorBlinkTimeout(int cursorBlinkTimeout) { D_DC(DPlatformTheme); return d->platformInterface->setCursorBlinkTimeout(cursorBlinkTimeout); } void DPlatformTheme::setCursorBlink(bool cursorBlink) { D_DC(DPlatformTheme); return d->platformInterface->setCursorBlink(cursorBlink); } void DPlatformTheme::setDoubleClickDistance(int doubleClickDistance) { D_DC(DPlatformTheme); return d->platformInterface->setDoubleClickDistance(doubleClickDistance); } void DPlatformTheme::setDoubleClickTime(int doubleClickTime) { D_DC(DPlatformTheme); return d->platformInterface->setDoubleClickTime(doubleClickTime); } void DPlatformTheme::setDndDragThreshold(int dndDragThreshold) { D_DC(DPlatformTheme); return d->platformInterface->setDndDragThreshold(dndDragThreshold); } void DPlatformTheme::setThemeName(const QByteArray &themeName) { D_DC(DPlatformTheme); return d->platformInterface->setThemeName(themeName); } void DPlatformTheme::setIconThemeName(const QByteArray &iconThemeName) { D_DC(DPlatformTheme); return d->platformInterface->setIconThemeName(iconThemeName); } void DPlatformTheme::setSoundThemeName(const QByteArray &soundThemeName) { D_DC(DPlatformTheme); return d->platformInterface->setSoundThemeName(soundThemeName); } void DPlatformTheme::setFontName(const QByteArray &fontName) { D_DC(DPlatformTheme); return d->platformInterface->setFontName(fontName); } void DPlatformTheme::setMonoFontName(const QByteArray &monoFontName) { D_DC(DPlatformTheme); return d->platformInterface->setMonoFontName(monoFontName); } void DPlatformTheme::setFontPointSize(qreal fontPointSize) { D_DC(DPlatformTheme); return d->platformInterface->setFontPointSize(fontPointSize); } void DPlatformTheme::setGtkFontName(const QByteArray &fontName) { D_DC(DPlatformTheme); return d->platformInterface->setGtkFontName(fontName); } void DPlatformTheme::setActiveColor(const QColor activeColor) { D_DC(DPlatformTheme); return d->platformInterface->setActiveColor(activeColor); } void DPlatformTheme::setDarkActiveColor(const QColor &activeColor) { D_DC(DPlatformTheme); return d->platformInterface->setDarkActiveColor(activeColor); } #define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role) #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void DPlatformTheme::setWindow(const QColor &window) { D_DC(DPlatformTheme); return d->platformInterface->setWindow(window); } void DPlatformTheme::setWindowText(const QColor &windowText) { D_DC(DPlatformTheme); return d->platformInterface->setWindowText(windowText); } void DPlatformTheme::setBase(const QColor &base) { D_DC(DPlatformTheme); return d->platformInterface->setBase(base); } void DPlatformTheme::setAlternateBase(const QColor &alternateBase) { D_DC(DPlatformTheme); return d->platformInterface->setAlternateBase(alternateBase); } void DPlatformTheme::setToolTipBase(const QColor &toolTipBase) { D_DC(DPlatformTheme); return d->platformInterface->setToolTipBase(toolTipBase); } void DPlatformTheme::setToolTipText(const QColor &toolTipText) { D_DC(DPlatformTheme); return d->platformInterface->setToolTipText(toolTipText); } void DPlatformTheme::setText(const QColor &text) { D_DC(DPlatformTheme); return d->platformInterface->setText(text); } void DPlatformTheme::setButton(const QColor &button) { D_DC(DPlatformTheme); return d->platformInterface->setButton(button); } void DPlatformTheme::setButtonText(const QColor &buttonText) { D_DC(DPlatformTheme); return d->platformInterface->setButtonText(buttonText); } void DPlatformTheme::setBrightText(const QColor &brightText) { D_DC(DPlatformTheme); return d->platformInterface->setBrightText(brightText); } void DPlatformTheme::setLight(const QColor &light) { D_DC(DPlatformTheme); return d->platformInterface->setLight(light); } void DPlatformTheme::setMidlight(const QColor &midlight) { D_DC(DPlatformTheme); return d->platformInterface->setMidlight(midlight); } void DPlatformTheme::setDark(const QColor &dark) { D_DC(DPlatformTheme); return d->platformInterface->setDark(dark); } void DPlatformTheme::setMid(const QColor &mid) { D_DC(DPlatformTheme); return d->platformInterface->setMid(mid); } void DPlatformTheme::setShadow(const QColor &shadow) { D_DC(DPlatformTheme); return d->platformInterface->setShadow(shadow); } void DPlatformTheme::setHighlight(const QColor &highlight) { D_DC(DPlatformTheme); return d->platformInterface->setHighlight(highlight); } void DPlatformTheme::setHighlightedText(const QColor &highlightText) { D_DC(DPlatformTheme); return d->platformInterface->setHighlightedText(highlightText); } void DPlatformTheme::setLink(const QColor &link) { D_DC(DPlatformTheme); return d->platformInterface->setLink(link); } void DPlatformTheme::setLinkVisited(const QColor &linkVisited) { D_DC(DPlatformTheme); return d->platformInterface->setLinkVisited(linkVisited); } void DPlatformTheme::setItemBackground(const QColor &itemBackground) { D_DC(DPlatformTheme); return d->platformInterface->setItemBackground(itemBackground); } void DPlatformTheme::setTextTitle(const QColor &textTitle) { D_DC(DPlatformTheme); return d->platformInterface->setTextTitle(textTitle); } void DPlatformTheme::setTextTips(const QColor &textTips) { D_DC(DPlatformTheme); return d->platformInterface->setTextTips(textTips); } void DPlatformTheme::setTextWarning(const QColor &textWarning) { D_DC(DPlatformTheme); return d->platformInterface->setTextWarning(textWarning); } void DPlatformTheme::setTextLively(const QColor &textLively) { D_DC(DPlatformTheme); return d->platformInterface->setTextLively(textLively); } void DPlatformTheme::setLightLively(const QColor &lightLively) { D_DC(DPlatformTheme); return d->platformInterface->setLightLively(lightLively); } void DPlatformTheme::setDarkLively(const QColor &darkLively) { D_DC(DPlatformTheme); return d->platformInterface->setDarkLively(darkLively); } void DPlatformTheme::setFrameBorder(const QColor &frameBorder) { D_DC(DPlatformTheme); return d->platformInterface->setFrameBorder(frameBorder); } #endif void DPlatformTheme::setDotsPerInch(const QString &screenName, int dpi) { D_DC(DPlatformTheme); return d->platformInterface->setDotsPerInch(screenName, dpi); } void DPlatformTheme::setWindowRadius(int windowRadius) { D_DC(DPlatformTheme); return d->platformInterface->setWindowRadius(windowRadius); } DGUI_END_NAMESPACE #include "moc_dplatformtheme.cpp" dtkgui-6.7.46/src/kernel/dregionmonitor.cpp000066400000000000000000000166061522615413000207270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dregionmonitor.h" #include "private/dregionmonitor_p.h" #include #include #include #include DGUI_BEGIN_NAMESPACE /*! \class Dtk::Gui::DRegionMonitor \inmodule dtkgui \brief 一个在指定区域内监视鼠标键盘动作的类. */ /*! \enum DRegionMonitor::RegisterdFlag DRegionMonitor::RegisterdFlag 定义了 DRegionMonitor 监å�¬æ ‡å¿—。 \var Motion 代表监å�¬é¼ æ ‡ç§»åŠ¨ã€‚ \var Button 代表监å�¬é¼ æ ‡æŒ‰é”®ã€‚ \var Key 代表监å�¬é”®ç›˜æŒ‰é”®ã€‚ */ DRegionMonitor::DRegionMonitor(QObject *parent) : QObject(parent), DObject(*new DRegionMonitorPrivate(this)) { D_D(DRegionMonitor); d->init(); } bool DRegionMonitor::registered() const { D_DC(DRegionMonitor); return !d->registerKey.isEmpty(); } QRegion DRegionMonitor::watchedRegion() const { D_DC(DRegionMonitor); return d->watchedRegion; } DRegionMonitor::RegisterdFlags DRegionMonitor::registerFlags() const { D_DC(DRegionMonitor); return d->registerdFlags; } DRegionMonitor::CoordinateType DRegionMonitor::coordinateType() const { D_DC(DRegionMonitor); return d->type; } void DRegionMonitor::registerRegion() { if (registered()) { qWarning() << "region already registered!"; return; } D_D(DRegionMonitor); d->registerMonitorRegion(); } void DRegionMonitor::unregisterRegion() { D_D(DRegionMonitor); d->unregisterMonitorRegion(); } void DRegionMonitor::setWatchedRegion(const QRegion ®ion) { D_D(DRegionMonitor); d->watchedRegion = region; if (registered()) d->registerMonitorRegion(); } /*! \property DRegionMonitor::registerdFlags \brief 监å�¬æ¨¡å¼�属性. \brief 监å�¬æ¨¡å¼�,需è¦�注æ„� DRegionMonitor::Motion 监å�¬é¼ æ ‡ç§»åŠ¨ä¼šå½±å“�性能,默认包å�«ï¼Œå¦‚æžœ 需è¦�å�¯é€šè¿‡æ­¤å‡½æ•°åŽ»æŽ‰ DRegionMonitor::Motion . registerdFlagChanged ä¿¡å�·ä¼šåœ¨ç›‘å�¬æ ‡å¿— registerdFlags 被改å�˜çš„æ—¶å€™è¢«è§¦å�‘. \a flags 监å�¬æ¨¡å¼�. */ void DRegionMonitor::setRegisterFlags(RegisterdFlags flags) { D_D(DRegionMonitor); if (d->registerdFlags == flags) return; d->registerdFlags = flags; if (registered()) d->registerMonitorRegion(); Q_EMIT registerdFlagsChanged(flags); } void DRegionMonitor::setCoordinateType(DRegionMonitor::CoordinateType type) { D_D(DRegionMonitor); d->type = type; } DRegionMonitorPrivate::DRegionMonitorPrivate(DRegionMonitor *q) : DObjectPrivate(q) { if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.deepin.dde.XEventMonitor1"))) { eventInter = new XEventMonitor("org.deepin.dde.XEventMonitor1", "/org/deepin/dde/XEventMonitor1", "org.deepin.dde.XEventMonitor1", q); } else { eventInter = new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", "com.deepin.api.XEventMonitor", q); } } DRegionMonitorPrivate::~DRegionMonitorPrivate() { if (registered()) unregisterMonitorRegion(); eventInter->deleteLater(); } void DRegionMonitorPrivate::init() { D_Q(DRegionMonitor); QObject::connect(eventInter, SIGNAL(ButtonPress(int,int,int,QString)), q, SLOT(_q_ButtonPress(const int, const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(ButtonRelease(int,int,int,QString)), q, SLOT(_q_ButtonRelease(const int, const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(CursorMove(int,int,QString)), q, SLOT(_q_CursorMove(const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(CursorInto(int,int,QString)), q, SLOT(_q_CursorEnter(const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(CursorOut(int,int,QString)), q, SLOT(_q_CursorLeave(const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(KeyPress(QString,int,int,QString)), q, SLOT(_q_KeyPress(const QString&, const int, const int, const QString&))); QObject::connect(eventInter, SIGNAL(KeyRelease(QString,int,int,QString)), q, SLOT(_q_KeyRelease(const QString&, const int, const int, const QString&))); } void DRegionMonitorPrivate::registerMonitorRegion() { if (registered()) unregisterMonitorRegion(); if (watchedRegion.isEmpty()) { // 将监å�¬åŒºåŸŸè®¾ç½®ä¸ºæœ€å¤§ registerKey = eventInter->RegisterArea(INT_MIN, INT_MIN, INT_MAX, INT_MAX, registerdFlags); } else { const QRect rect = watchedRegion.boundingRect(); const int x1 = rect.x(); const int y1 = rect.y(); const int x2 = x1 + rect.width(); const int y2 = y1 + rect.height(); registerKey = eventInter->RegisterArea(x1, y1, x2, y2, registerdFlags); } } void DRegionMonitorPrivate::unregisterMonitorRegion() { if (registerKey.isEmpty()) return; eventInter->UnregisterArea(registerKey); registerKey.clear(); } void DRegionMonitorPrivate::_q_ButtonPress(const int flag, const int x, const int y, const QString &key) { if (registerKey != key) return; D_Q(DRegionMonitor); Q_EMIT q->buttonPress(deviceScaledCoordinate(QPoint(x, y), qApp->devicePixelRatio()), flag); } void DRegionMonitorPrivate::_q_ButtonRelease(const int flag, const int x, const int y, const QString &key) { if (registerKey != key) return; D_Q(DRegionMonitor); Q_EMIT q->buttonRelease(deviceScaledCoordinate(QPoint(x, y), qApp->devicePixelRatio()), flag); } void DRegionMonitorPrivate::_q_CursorMove(const int x, const int y, const QString &key) { if (registerKey != key) return; D_Q(DRegionMonitor); Q_EMIT q->cursorMove(deviceScaledCoordinate(QPoint(x, y), qApp->devicePixelRatio())); } void DRegionMonitorPrivate::_q_CursorEnter(const int x, const int y, const QString &key) { if (registerKey != key) return; D_Q(DRegionMonitor); Q_EMIT q->cursorEnter(deviceScaledCoordinate(QPoint(x, y), qApp->devicePixelRatio())); } void DRegionMonitorPrivate::_q_CursorLeave(const int x, const int y, const QString &key) { if (registerKey != key) return; D_Q(DRegionMonitor); Q_EMIT q->cursorLeave(deviceScaledCoordinate(QPoint(x, y), qApp->devicePixelRatio())); } void DRegionMonitorPrivate::_q_KeyPress(const QString &keyname, const int x, const int y, const QString &key) { if (registerKey != key) return; Q_UNUSED(x); Q_UNUSED(y); D_Q(DRegionMonitor); Q_EMIT q->keyPress(keyname); } void DRegionMonitorPrivate::_q_KeyRelease(const QString &keyname, const int x, const int y, const QString &key) { if (registerKey != key) return; Q_UNUSED(x); Q_UNUSED(y); D_Q(DRegionMonitor); Q_EMIT q->keyRelease(keyname); } const QPoint DRegionMonitorPrivate::deviceScaledCoordinate(const QPoint &p, const double ratio) const { D_QC(DRegionMonitor); if (type == q->Original) { return p; } for (const auto *s : qApp->screens()) { const QRect &g(s->geometry()); const QRect realRect(g.topLeft(), g.size() * ratio); if (realRect.contains(p)) return QPoint(realRect.topLeft() + (p - realRect.topLeft()) / ratio); } return p / ratio; } DGUI_END_NAMESPACE #include "moc_dregionmonitor.cpp" dtkgui-6.7.46/src/kernel/dwindowgroupleader.cpp000066400000000000000000000133671522615413000215760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dwindowgroupleader.h" #include #include #include DGUI_BEGIN_NAMESPACE #define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name DEFINE_CONST_CHAR(groupLeader); DEFINE_CONST_CHAR(createGroupWindow); DEFINE_CONST_CHAR(destoryGroupWindow); DEFINE_CONST_CHAR(setWindowGroup); DEFINE_CONST_CHAR(clientLeader); class DWindowGroupLeaderPrivate { public: explicit DWindowGroupLeaderPrivate(quint32 groupLeader) : groupLeader(groupLeader) { QFunctionPointer clientLeaderFun = qApp->platformFunction(_clientLeader); if (clientLeaderFun) { clientLeader = reinterpret_cast(clientLeaderFun)(); } } quint32 groupLeader; quint32 clientLeader = 0; bool groupLeaderFromUser = false; QList> windowList; void ensureGroupLeader(); bool setWindowGroupLeader(quint32 window, quint32 groupLeader); }; void DWindowGroupLeaderPrivate::ensureGroupLeader() { if (groupLeader != 0) return; QFunctionPointer createGroupWindow = qApp->platformFunction(_createGroupWindow); if (!createGroupWindow) return; groupLeader = reinterpret_cast(createGroupWindow)(); } bool DWindowGroupLeaderPrivate::setWindowGroupLeader(quint32 window, quint32 groupLeader) { QFunctionPointer setWindowGroup = qApp->platformFunction(_setWindowGroup); if (!setWindowGroup) { return false; } reinterpret_cast(setWindowGroup)(window, groupLeader); return true; } /*! \class Dtk::Gui::DWindowGroupLeader \inmodule dtkgui \brief DWindowGroupLeader 用于设置窗å�£æ‰€åœ¨çš„组,å�¯ä»¥æŠŠå¤šä¸ªçª—å�£åŠ åˆ°å�Œä¸€ä¸ªç»„. 在dxcbå¹³å�°ä¸Šï¼Œæ‰€æœ‰æœªæŒ‡å®šç»„的窗å�£éƒ½ä¼šè¢«åˆ†é…�到 DWindowGroupLeader::clientLeaderId 这个组,且在窗å�£å¯¹åº”的本地窗å�£è¢«åˆ›å»ºæ—¶ï¼Œä¼šå¯¹ Qt::Dialogã€�Qt::Sheetã€�Qt::Toolã€� Qt::SplashScreenã€�Qt::ToolTipã€�Qt::Drawerã€�Qt::Popup 类型的窗å�£è®¾ç½® WM_TRANSIENT_FOR 属性,对于此类型的窗å�£ï¼Œå¦‚果没有手动调用 QWindow::setTransientParent , 则会将其 WM_TRANSIENT_FOR 属性设置为所在组id,得到的效果就是:会ä¿�è¯�此窗å�£æ˜¾ç¤ºåˆ°è¿™ä¸ªç»„所有其它窗å�£ 之上。例å­�: \code DWindowGroupLeader leader; QWindow wa, wb; QWindow topWindow; leader.addWindow(&wa); leader.addWindow(&wb); leader.addWindow(&topWindow); wa.setTitle("窗å�£wa"); wa.resize(300, 100); wa.show(); wb.setTitle("窗å�£wb"); wb.resize(300, 100); wb.show(); topWindow.setTitle("窗å�£topWindow"); topWindow.setFlag(Qt::Dialog); topWindow.resize(300, 300); topWindow.show(); \endcode 窗å�£topWindow一直处于窗å�£waå’Œwb上层 \image wa_wb_topWindow.gif 如果一个组内å�Œæ—¶å­˜åœ¨å¤šä¸ªæœªè®¾ç½®è¿‡ QWindow::setTransientParent çš„ Qt::Dialog(其它会自动设置 WM_TRANSIENT_FOR 属性的窗å�£ä¹Ÿæˆ�立)类型的窗å�£ï¼Œè¿™äº›çª—å�£ä¹‹é—´ä¸�会互相影å“�显示顺åº�,具体的规则和 X11 ICCCM 标准一致。 \ref {https://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR} \sa DWindowGroupLeader::clientLeaderId \sa Dtk::Widget::DApplication::loadDXcbPlugin */ /*! \brief DWindowGroupLeader::DWindowGroupLeader \a groupId 为0时会在需è¦�时自动创建一个有效的 groupLeaderId \sa DWindowGroupLeader::groupLeaderId */ DWindowGroupLeader::DWindowGroupLeader(quint32 groupId) : d_ptr(new DWindowGroupLeaderPrivate(groupId)) { if (groupId != 0) d_ptr->groupLeaderFromUser = true; } /*! \brief DWindowGroupLeader::~DWindowGroupLeader 对象销æ¯�时会释放由自己自动创建的 groupLeaderId \sa DWindowGroupLeader::groupLeaderId */ DWindowGroupLeader::~DWindowGroupLeader() { Q_D(DWindowGroupLeader); for (auto window : d->windowList) removeWindow(window); if (!d->groupLeaderFromUser) { QFunctionPointer destoryGroupWindow = qApp->platformFunction(_destoryGroupWindow); if (!destoryGroupWindow) return; reinterpret_cast(destoryGroupWindow)(d->groupLeader); } } /*! \brief DWindowGroupLeader::groupLeaderId \return 返回组的id,类似于 QWindow::winId \warning 如果没有一个有效的id,则会先创建一个新的组id */ quint32 DWindowGroupLeader::groupLeaderId() const { Q_D(const DWindowGroupLeader); const_cast(d)->ensureGroupLeader(); return d->groupLeader; } /*! \brief DWindowGroupLeader::clientLeaderId \return 返回应用程åº�默认的组id */ quint32 DWindowGroupLeader::clientLeaderId() const { Q_D(const DWindowGroupLeader); return d->clientLeader; } /*! \brief DWindowGroupLeader::addWindow 将窗å�£æ·»åŠ åˆ°è¿™ä¸ªç»„ \a window \warning æ¯�个窗å�£å�ªèƒ½æœ‰ä¸€ä¸ªç»„,添加到新的组时,将ä¸�å†�å�—旧的组所带æ�¥çš„任何影å“� */ void DWindowGroupLeader::addWindow(QWindow *window) { Q_ASSERT(window); Q_D(DWindowGroupLeader); d->ensureGroupLeader(); window->setProperty(_groupLeader, d->groupLeader); if (window->handle()) { d->setWindowGroupLeader(window->winId(), d->groupLeader); } d->windowList << window; } /*! \brief DWindowGroupLeader::removeWindow 将窗å�£ä»Žè¿™ä¸ªç»„中移除 \a window \warning 窗å�£è¢«ç§»é™¤å�Žå°†ä¸�å†�å�—此组带æ�¥çš„任何影å“� */ void DWindowGroupLeader::removeWindow(QWindow *window) { if (!window) return; window->setProperty(_groupLeader, QVariant()); Q_D(DWindowGroupLeader); if (window->handle()) { d->setWindowGroupLeader(window->winId(), d->clientLeader); } } DGUI_END_NAMESPACE dtkgui-6.7.46/src/kernel/dwindowmanagerhelper.cpp000066400000000000000000000635761522615413000221060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dwindowmanagerhelper.h" #include "dforeignwindow.h" #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #include #define D_XCB_WINDOW_TYPE QNativeInterface::Private::QXcbWindow::WindowType #else #include #define D_XCB_WINDOW_TYPE QXcbWindowFunctions::WmWindowType #endif #include #include #include #ifndef DTK_DISABLE_TREELAND #include "plugins/platform/treeland/dtreelandwindowmanagerhelper.h" #include #include #include #include #endif DGUI_BEGIN_NAMESPACE #define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name #define MWM_FUNC_ALL (1L << 0) #define MWM_DECOR_ALL (1L << 0) // functions DEFINE_CONST_CHAR(hasBlurWindow); DEFINE_CONST_CHAR(hasComposite); DEFINE_CONST_CHAR(hasNoTitlebar); DEFINE_CONST_CHAR(hasWallpaperEffect); DEFINE_CONST_CHAR(windowManagerName); DEFINE_CONST_CHAR(connectWindowManagerChangedSignal); DEFINE_CONST_CHAR(connectHasBlurWindowChanged); DEFINE_CONST_CHAR(connectHasCompositeChanged); DEFINE_CONST_CHAR(connectHasNoTitlebarChanged); DEFINE_CONST_CHAR(connectHasWallpaperEffectChanged); DEFINE_CONST_CHAR(getCurrentWorkspaceWindows); DEFINE_CONST_CHAR(getWindows); DEFINE_CONST_CHAR(windowFromPoint); DEFINE_CONST_CHAR(connectWindowListChanged); DEFINE_CONST_CHAR(setMWMFunctions); DEFINE_CONST_CHAR(getMWMFunctions); DEFINE_CONST_CHAR(setMWMDecorations); DEFINE_CONST_CHAR(getMWMDecorations); DEFINE_CONST_CHAR(connectWindowMotifWMHintsChanged); DEFINE_CONST_CHAR(popupSystemWindowMenu); DEFINE_CONST_CHAR(setWMClassName); template static inline ReturnT callPlatformFunction(const QByteArray &funcName, Args... args) { QFunctionPointer func = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) func = qApp->platformFunction(funcName); #endif return func ? reinterpret_cast(func)(args...) : ReturnT(); } typedef bool(*func_t)(QObject *object, std::function); static bool connectWindowManagerChangedSignal(QObject *object, std::function slot) { return callPlatformFunction(_connectWindowManagerChangedSignal, object, slot); } static bool connectHasBlurWindowChanged(QObject *object, std::function slot) { return callPlatformFunction(_connectHasBlurWindowChanged, object, slot); } static bool connectHasCompositeChanged(QObject *object, std::function slot) { return callPlatformFunction(_connectHasCompositeChanged, object, slot); } static bool connectHasNoTitlebarChanged(QObject *object, std::function slot) { return callPlatformFunction(_connectHasNoTitlebarChanged, object, slot); } static bool connectHasWallpaperEffectChanged(QObject *object, std::function slot) { return callPlatformFunction(_connectHasWallpaperEffectChanged, object, slot); } static bool connectWindowListChanged(QObject *object, std::function slot) { return callPlatformFunction(_connectWindowListChanged, object, slot); } static bool connectWindowMotifWMHintsChanged(QObject *object, std::function slot) { typedef bool(*quint32_func_t)(QObject *object, std::function); return callPlatformFunction(_connectWindowMotifWMHintsChanged, object, slot); } class DWindowManagerHelperPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate { public: explicit DWindowManagerHelperPrivate(DWindowManagerHelper *qq) : DObjectPrivate(qq) {} mutable QList windowList; }; // TODO abstract an interface to adapt to various WM. #ifndef DTK_DISABLE_TREELAND Q_GLOBAL_STATIC(TreelandWindowManagerHelper, treelandWMHGlobal) #endif class DWindowManagerHelper_ : public DWindowManagerHelper {}; Q_GLOBAL_STATIC(DWindowManagerHelper_, wmhGlobal) /*! \class Dtk::Gui::DWindowManagerHelper \inmodule dtkgui \brief æ��供与窗å�£ç®¡ç�†å™¨äº¤äº’的接å�£ï¼Œå�Œ \a DPlatformWindowHandle ä¾�èµ– dxcb æ�’ä»¶. dxcb æ�’件抽象出所有需è¦�å’ŒX11å¹³å�°äº¤äº’的接å�£ä»¥ä¾›ä¸Šå±‚调用,DTK 使用æ�’件中æ��供的接å�£å†� 次å°�装æ��供给应用程åº�使用,从设计角度讲,DTK库中ä¸�应该直接使用任何跟平å�°ç›¸å…³çš„æŽ¥å�£ (如:X11ã€�Waylandã€�Windows),在这样的结构支撑下,在一个新的平å�°ä¸Šï¼Œå�ªéœ€è¦�æ��供和 dxcb å�Œæ ·çš„æŽ¥å�£ï¼ŒDTK应用å�³å�¯æ— ç¼�è¿�移。 \sa {https://github.com/linuxdeepin/qt5dxcb-plugin/}{dxcbæ�’ä»¶} \sa Dtk::Widget::DApplication::loadDXcbPlugin \sa Dtk::Widget::DApplication::isDXcbPlatform \sa Dtk::Widget::DPlatformWindowHandle */ /*! \property DWindowManagerHelper::hasBlurWindow \brief 窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�窗å�£èƒŒæ™¯æ¨¡ç³Šç‰¹æ•ˆ \note 在 dxcb æ�’件中目å‰�å�ªæ”¯æŒ� deepin-wm å’Œ kwin 这两ç§�窗管的模糊特效 \note å�ªè¯» */ /*! \property DWindowManagerHelper::hasComposite \brief 窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�æ··æˆ�效果。如果ä¸�支æŒ�æ··æˆ�,则表示所有窗å�£çš„背景都ä¸�能é€�明, éš�之而æ�¥ä¹Ÿä¸�会有窗å�£é˜´å½±ç­‰æ•ˆæžœï¼Œä¸�规则窗å�£çš„边缘也会存在锯齿。 \note å�ªè¯» */ /*! \property DWindowManagerHelper::hasNoTitlebar \brief 窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�éš�è—�窗å�£æ ‡é¢˜æ �。如果支æŒ�,则 DPlatformWindowHandle::enableDXcbForWindow 会优先使用此方法支æŒ�自定义窗å�£æ ‡é¢˜æ �。 \note å�ªè¯» \sa Dtk::Gui::DPlatformHandle::setEnabledNoTitlebarForWindow */ /*! \property DWindowManagerHelper::hasWallpaperEffect \brief 窗å�£ç®¡ç�†å™¨æ˜¯å�¦æ”¯æŒ�窗å�£èƒŒæ™¯ç‰¹æ•ˆç»˜åˆ¶ã€‚如果支æŒ�,则 绘制背景到é€�明窗å�£ 会使用此方法开å�¯ç‰¹æ•ˆçª—å�£å£�纸背景绘制。 \note å�ªè¯» \sa hasWallpaperEffectChanged() */ /*! \enum Dtk::Gui::DWindowManagerHelper::MotifFunction MotifFunction::MotifFunction 窗å�£ç®¡ç�†å™¨å¯¹çª—å�£æ‰€èƒ½æŽ§åˆ¶çš„行为 \value FUNC_RESIZE 控制窗å�£å¤§å°�。如果存在此标志,则窗å�£ç®¡ç�†å™¨å�¯ä»¥æ”¹å�˜çª—å�£å¤§å°�(如使用鼠标拖拽窗å�£è¾¹ç¼˜ï¼‰ï¼Œ å�¦åˆ™æ— æ³•通过外部行为调整窗å�£å¤§å°�。 \code DMainWindow w; w.resize(400, 200); w.show(); DWindowManagerHelper::setMotifFunctions(w.windowHandle(), DWindowManagerHelper::FUNC_RESIZE, false); \endcode \image disable_resize_function.gif \note 普通窗å�£é»˜è®¤å­˜åœ¨æ­¤æ ‡å¿—,对于 Qt::Popup å’Œ Qt::BypassWindowManagerHint 类型的窗å�£ï¼Œä¸�å�—此标志ä½�å½±å“� \note 设置此标志å�Žä¹Ÿä¼šå½±å“�窗å�£æ ‡é¢˜æ �对应功能入å�£çš„状æ€� \note 对于使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \sa Dtk::Gui::DPlatformHandle::enableDXcbForWindow \sa Dtk::Gui::DPlatformHandle::isEnabledDXcb \value FUNC_MOVE 控制窗å�£ä½�置。如果存在此标志,则窗å�£ç®¡ç�†å™¨å�¯ä»¥ç§»åŠ¨çª—å�£ï¼ˆå¦‚使用鼠标拖动标题æ �),å�¦åˆ™ 无法通过外部行为移动窗å�£ä½�置。 \code DWindowManagerHelper::setMotifFunctions(w.windowHandle(), DWindowManagerHelper::FUNC_MOVE, false); \endcode \image disable_move_function.gif \value FUNC_MINIMIZE 最å°�化窗å�£ã€‚如果存在此标志,则窗å�£å�¯ä»¥è¢«æœ€å°�化(如点击标题æ �的最å°�化按钮),å�¦åˆ™æ— æ³• 通过外部行为最å°�化窗å�£ã€‚ \code DWindowManagerHelper::setMotifFunctions(w.windowHandle(), DWindowManagerHelper::FUNC_MINIMIZE, false); \endcode \note 设置此标志å�Žä¹Ÿä¼šå½±å“�窗å�£æ ‡é¢˜æ �对应功能入å�£çš„状æ€� \value FUNC_MAXIMIZE 最大化窗å�£ã€‚如果存在此标志,则窗å�£å�¯ä»¥è¢«æœ€å¤§åŒ–(如点击标题æ �的最大化按钮),å�¦åˆ™æ— æ³• 通过外部行为最大化窗å�£ã€‚ \code DWindowManagerHelper::setMotifFunctions(w.windowHandle(), DWindowManagerHelper::FUNC_MAXIMIZE, false); \endcode \note 设置此标志å�Žä¹Ÿä¼šå½±å“�窗å�£æ ‡é¢˜æ �对应功能入å�£çš„状æ€� \value FUNC_CLOSE 关闭窗å�£ã€‚如果存在此标志,则窗å�£å�¯ä»¥è¢«å…³é—­ï¼ˆå¦‚点击标题æ �的关闭按钮或使用Alt+F4å¿«æ�·é”®ï¼‰ï¼Œ å�¦åˆ™æ— æ³•通过外部行为关闭窗å�£ã€‚ \code DWindowManagerHelper::setMotifFunctions(w.windowHandle(), DWindowManagerHelper::FUNC_CLOSE, false); \endcode \note 设置此标志å�Žä¹Ÿä¼šå½±å“�窗å�£æ ‡é¢˜æ �对应功能入å�£çš„状æ€� \value FUNC_ALL 所有功能性行为 */ /*! \enum Dtk::Gui::DWindowManagerHelper::MotifDecoration MotifFunction::MotifDecoration 窗å�£ç®¡ç�†å™¨å¯¹çª—å�£æ·»åŠ çš„ä¿®é¥°ã€‚å�ªå½±å“�窗å�£ä¸Šå¯¹åº”功能 的入å�£ï¼Œä¸�å½±å“�实际的功能,比如:ç¦�用掉 FUNC_MAXIMIZE å�Žï¼Œè¿˜å�¯ä»¥ä½¿ç”¨å¿«æ�·é”®æœ€å¤§åŒ–窗å�£ \value DECOR_BORDER 窗å�£æ��边。如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šä¸ºçª—å�£ç»˜åˆ¶æ��边,å�¦åˆ™çª—å�£æ²¡æœ‰æ��边。 å�¦åˆ™æ— æ³•通过外部行为调整窗å�£å¤§å°�。 \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \value DECOR_RESIZEH 改å�˜çª—å�£å¤§å°�。如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šåœ¨çª—å�£çš„修饰上显示一个更改窗å�£å¤§å°�的控件, å�¦åˆ™æ— æ­¤æŽ§ä»¶ã€‚ \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \value DECOR_TITLE 窗å�£æ ‡é¢˜ã€‚如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šåœ¨çª—å�£çš„修饰上显示窗å�£æ ‡é¢˜ï¼Œå�¦åˆ™ä¸�显示。 \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \value DECOR_MENU 窗å�£è�œå�•。如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šåœ¨çª—å�£çš„修饰上显示一个窗å�£è�œå�•控件,å�¦åˆ™ä¸�显示。 \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \value DECOR_MINIMIZE 窗å�£æœ€å°�化。如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šåœ¨çª—å�£çš„修饰上显示一个最å°�化窗å�£æŽ§ä»¶ï¼Œå�¦åˆ™ä¸�显示。 \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \sa Qt::WindowMinimizeButtonHint \value DECOR_MAXIMIZE 窗å�£æœ€å¤§åŒ–。如果存在此标志,则窗å�£ç®¡ç�†å™¨ä¼šåœ¨çª—å�£çš„修饰上显示一个最大化窗å�£æŽ§ä»¶ï¼Œå�¦åˆ™ä¸�显示。 \note å�ªæ”¯æŒ�使用系统标题æ �的窗å�£ï¼Œæ­¤åŠŸèƒ½å’Œå…·ä½“çª—å�£ç®¡ç�†å™¨å®žçŽ°ç›¸å…³ï¼Œdeepin-wm 中设置 此标志无效。 \sa Qt::WindowMaximizeButtonHint \value DECOR_ALL 所有窗å�£ä¿®é¥°ã€‚ */ /*! \enum Dtk::Gui::DWindowManagerHelper::WMName DWindowManagerHelper::WMName 窗å�£ç®¡ç�†å™¨ç±»åž‹ \value DeepinWM 深度系统桌é�¢çŽ¯å¢ƒçª—å�£ç®¡ç�†å™¨ \value KWinWM KDE系统桌é�¢çŽ¯å¢ƒçª—å�£ç®¡ç�†å™¨ \value OtherWM 其它窗å�£ç®¡ç�†å™¨ */ /*! \fn void DWindowManagerHelper::windowManagerChanged() \brief ä¿¡å�·ä¼šåœ¨å½“å‰�环境窗å�£ç®¡ç�†å™¨å�˜åŒ–时被å�‘é€�. */ /*! \fn void DWindowManagerHelper::hasBlurWindowChanged() \brief ä¿¡å�·ä¼šåœ¨ hasBlurWindow 属性的值改å�˜æ—¶è¢«å�‘é€�. */ /*! \fn void DWindowManagerHelper::hasCompositeChanged() \brief ä¿¡å�·ä¼šåœ¨ hasComposite 属性的值改å�˜æ—¶è¢«å�‘é€�. */ /*! \fn void DWindowManagerHelper::hasNoTitlebarChanged() \brief ä¿¡å�·ä¼šåœ¨ hasNoTitlebar 属性的值改å�˜æ—¶è¢«å�‘é€�. */ /*! \fn void DWindowManagerHelper::hasWallpaperEffectChanged() \brief ä¿¡å�·ä¼šåœ¨ hasWallpaperEffect 属性的值改å�˜æ—¶è¢«å�‘é€�. */ /*! \fn void DWindowManagerHelper::windowListChanged() \brief ä¿¡å�·ä¼šåœ¨å½“å‰�环境本地窗å�£åˆ—表å�˜åŒ–时被å�‘é€�。包å�«æ‰“开新窗å�£ã€�关闭窗å�£ã€�改å�˜çª—å�£çš„ 层å� é¡ºåº�. */ /*! \fn void DWindowManagerHelper::windowMotifWMHintsChanged(quint32 winId) \brief ä¿¡å�·ä¼šåœ¨çª—å�£åŠŸèƒ½æˆ–ä¿®é¥°æ ‡å¿—æ”¹å�˜æ—¶è¢«å�‘é€�. \a winId 窗å�£id \note å�ªå¯¹å½“å‰�应用程åº�中的窗å�£æœ‰æ•ˆ */ DWindowManagerHelper::~DWindowManagerHelper() { D_DC(DWindowManagerHelper); for (QWindow *w : d->windowList) { w->deleteLater(); } } /*! \brief DWindowManagerHelper::instance DWindowManagerHelper çš„å�•例对象,使用 Q_GLOBAL_STATIC 定义,在第一次调用时实例化。 \return */ DWindowManagerHelper *DWindowManagerHelper::instance() { #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { return treelandWMHGlobal; } #endif return wmhGlobal; } /*! \brief DWindowManagerHelper::setMotifFunctions 设置窗å�£çš„功能性标志,会覆盖之å‰�的设置 \a window \a hints */ void DWindowManagerHelper::setMotifFunctions(const QWindow *window, MotifFunctions hints) { QFunctionPointer setMWMFunctions = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) setMWMFunctions = qApp->platformFunction(_setMWMFunctions); #endif if (setMWMFunctions && window->handle()) { /* fix bug: 18775, 3391 当所有function标志都设置时,用MWM_FUNC_ALL代替会导致窗管无法正确处ç�† dockæ �å�‘é€�的关闭消æ�¯.所以å�–消此设置 if (hints == FUNC_ALL) hints = (MotifFunction)MWM_FUNC_ALL; */ reinterpret_cast(setMWMFunctions)(window->handle()->winId(), (quint32)hints); } } /*! \brief DWindowManagerHelper::setMotifFunctions 设置窗å�£æŸ�些标志ä½�的开å�¯çжæ€�,ä¸�å½±å“�其它标志ä½� \a window \a hints è¦�设置的标志ä½� \a on 如果值为 true 则开å�¯æ ‡å¿—,å�¦åˆ™å…³é—­ \return 返回设置å�Žçš„窗å�£æ ‡å¿— */ DWindowManagerHelper::MotifFunctions DWindowManagerHelper::setMotifFunctions(const QWindow *window, MotifFunctions hints, bool on) { MotifFunctions old_hints = getMotifFunctions(window); if (on) hints |= old_hints; else hints = old_hints & ~hints; setMotifFunctions(window, hints); return hints; } /*! \brief DWindowManagerHelper::getMotifFunctions \a window \return 返回窗å�£å½“å‰�的功能标志 */ DWindowManagerHelper::MotifFunctions DWindowManagerHelper::getMotifFunctions(const QWindow *window) { QFunctionPointer getMWMFunctions = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) getMWMFunctions = qApp->platformFunction(_getMWMFunctions); #endif if (getMWMFunctions && window->handle()) { quint32 hints = reinterpret_cast(getMWMFunctions)(window->handle()->winId()); if (!(hints & MWM_FUNC_ALL)) return (MotifFunctions)hints; } return FUNC_ALL; } /*! \brief DWindowManagerHelper::setMotifDecorations 设置窗å�£çš„修饰性标志,会覆盖之å‰�的设置 \a window \a hints */ void DWindowManagerHelper::setMotifDecorations(const QWindow *window, MotifDecorations hints) { QFunctionPointer setMWMDecorations = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) setMWMDecorations = qApp->platformFunction(_setMWMDecorations); #endif if (setMWMDecorations && window->handle()) { if (hints == DECOR_ALL) hints = (MotifDecoration)MWM_DECOR_ALL; reinterpret_cast(setMWMDecorations)(window->handle()->winId(), (quint32)hints); } } /*! \brief DWindowManagerHelper::setMotifFunctions 设置窗å�£æŸ�些标志ä½�的开å�¯çжæ€�,ä¸�å½±å“�其它标志ä½� \a window \a hints è¦�设置的标志ä½� \a on 如果值为 true 则开å�¯æ ‡å¿—,å�¦åˆ™å…³é—­ \return 返回设置å�Žçš„窗å�£æ ‡å¿— */ DWindowManagerHelper::MotifDecorations DWindowManagerHelper::setMotifDecorations(const QWindow *window, MotifDecorations hints, bool on) { MotifDecorations old_hints = getMotifDecorations(window); if (on) hints |= old_hints; else hints = old_hints & ~hints; setMotifDecorations(window, hints); return hints; } /*! \brief DWindowManagerHelper::getMotifFunctions \a window \return 返回窗å�£å½“å‰�的修饰标志 */ DWindowManagerHelper::MotifDecorations DWindowManagerHelper::getMotifDecorations(const QWindow *window) { QFunctionPointer getMWMDecorations = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) getMWMDecorations = qApp->platformFunction(_getMWMDecorations); #endif if (getMWMDecorations && window->handle()) { quint32 hints = reinterpret_cast(getMWMDecorations)(window->handle()->winId()); if (!(hints & MWM_DECOR_ALL)) return (MotifDecorations)hints; } return DECOR_ALL; } /*! \brief DWindowManagerHelper::setWmWindowTypes 直接设置窗å�£ç®¡ç�†å™¨å±‚级æ��供的窗å�£ç±»åž‹ï¼Œå¦‚DesktopTypeå’ŒDockType类型也被 桌é�¢çŽ¯å¢ƒéœ€è¦�,但是Qt自身并没有æ��供对应的设置接å�£ \a window \a types */ void DWindowManagerHelper::setWmWindowTypes(QWindow *window, WmWindowTypes types) { const int _types = static_cast(types); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) typedef QNativeInterface::Private::QXcbWindow QXcbWindow_P; if (auto w = dynamic_cast(window->handle())) { w->setWindowType(static_cast(_types)); } else { qWarning() << "cast" << window << "to platform window failed"; } #else QXcbWindowFunctions::setWmWindowType(window, static_cast(_types)); #endif } /*! \brief DWindowManagerHelper::setWmClassName 设置x11环境上默认使用的wm class name,主è¦�是在窗å�£åˆ›å»ºæ—¶ç”¨äºŽè®¾ç½®WM_CLASS窗å�£å±žæ€§ \a name \note 如果值为空,Qt将在下次使用此值时根æ�®ç¨‹åº�å��ç§°å†�次åˆ�始化此值 \sa QCoreApplication::applicationName */ void DWindowManagerHelper::setWmClassName(const QByteArray &name) { typedef void (*SetWmNameType)(const QByteArray&); return callPlatformFunction(_setWMClassName, name); } /*! \brief DWindowManagerHelper::popupSystemWindowMenu 显示窗å�£ç®¡ç�†å™¨å¯¹çª—å�£çš„è�œå�•,和有边框的窗å�£åœ¨æ ‡é¢˜æ �上点击鼠标å�³é”®å¼¹å‡ºçš„è�œå�•内容一致。 在 DMainWindow 的标题æ �上点击鼠标å�³é”®ä¼šè°ƒç”¨æ­¤å‡½æ•°æ‰“开系统è�œå�•: \image window_system_menu.gif \a window */ void DWindowManagerHelper::popupSystemWindowMenu(const QWindow *window) { #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { if (window && window->handle()) { if (auto *wlWindow = dynamic_cast(window->handle())) { if (auto *shellSurface = wlWindow->shellSurface()) { auto *wlIntegration = static_cast( QGuiApplicationPrivate::platformIntegration()); shellSurface->showWindowMenu(wlIntegration->display()->defaultInputDevice()); } } } return; } #endif return callPlatformFunction(_popupSystemWindowMenu, quint32(window->handle()->winId())); } /*! \brief DWindowManagerHelper::hasBlurWindow \return 如果当å‰�窗å�£ç®¡ç�†å™¨æ”¯æŒ�窗å�£èƒŒæ™¯æ¨¡ç³Šç‰¹æ•ˆåˆ™è¿”回 true,å�¦åˆ™è¿”回 false */ bool DWindowManagerHelper::hasBlurWindow() const { #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { return treelandWMHGlobal->hasBlurWindow(); } #endif return callPlatformFunction(_hasBlurWindow); } /*! \brief DWindowManagerHelper::hasComposite \return 如果当å‰�窗å�£ç®¡ç�†å™¨æ”¯æŒ�æ··æˆ�则返回 true,å�¦åˆ™è¿”回 false */ bool DWindowManagerHelper::hasComposite() const { #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { return treelandWMHGlobal->hasComposite(); } #endif QFunctionPointer hasComposite = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) hasComposite = qApp->platformFunction(_hasComposite); #endif if (!hasComposite) { #ifdef Q_OS_LINUX if (DGuiApplicationHelper::isXWindowPlatform()) { QPlatformNativeInterface *native = qApp->platformNativeInterface(); if (Q_LIKELY(native)) { QScreen *scr = QGuiApplication::primaryScreen(); return native->nativeResourceForScreen(QByteArray("compositingEnabled"), scr); } } #endif // 在其它平å�°ä¸Šé»˜è®¤è®¤ä¸ºæ··æˆ�是开å�¯çš„ return true; } return callPlatformFunction(_hasComposite); } /*! \brief DWindowManagerHelper::hasNoTitlebar \return 如果窗å�£ç®¡ç�†å™¨å½“å‰�支æŒ�设置éš�è—�窗å�£æ ‡é¢˜æ �则返回 true,å�¦åˆ™è¿”回 false */ bool DWindowManagerHelper::hasNoTitlebar() const { #ifndef DTK_DISABLE_TREELAND if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { return treelandWMHGlobal->hasNoTitlebar(); } #endif return callPlatformFunction(_hasNoTitlebar); } /*! \brief DWindowManagerHelper::hasWallpaperEffect \return 如果窗å�£ç®¡ç�†å™¨å½“å‰�支æŒ�背景图片特效绘制返回 true,å�¦åˆ™è¿”回 false */ bool DWindowManagerHelper::hasWallpaperEffect() const { return callPlatformFunction(_hasWallpaperEffect); } /*! \brief DWindowManagerHelper::windowManagerNameString \return 返回窗å�£ç®¡ç�†å™¨å��称。在X11å¹³å�°ä¸Šï¼Œæ­¤å€¼ä¸ºçª—å�£ç®¡ç�†å™¨å¯¹åº”窗å�£çš„ _NET_WM_NAME 的值 \ref {https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html}{_NET_SUPPORTING_WM_CHECK} \ref {https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html}{_NET_WM_NAME} */ QString DWindowManagerHelper::windowManagerNameString() const { return callPlatformFunction(_windowManagerName); } /*! \brief DWindowManagerHelper::windowManagerName \return 返回当å‰�窗å�£ç®¡ç�†å™¨ç±»åž‹ \sa DWindowManagerHelper::windowManagerNameString */ DWindowManagerHelper::WMName DWindowManagerHelper::windowManagerName() const { const QString &wmName = windowManagerNameString(); if (wmName == QStringLiteral("Mutter(DeepinGala)")) { return DeepinWM; } if (wmName == QStringLiteral("KWin")) { return KWinWM; } return OtherWM; } /*! \brief DWindowManagerHelper::allWindowIdList \return 返回当å‰�环境所有本地窗å�£çš„窗å�£id列表 \note 顺åº�和窗å�£å±‚å� é¡ºåº�相关,显示越é� ä¸‹å±‚的窗å�£åœ¨åˆ—表中顺åº�è¶Šé� å‰� \sa DWindowManagerHelper::currentWorkspaceWindowIdList */ QVector DWindowManagerHelper::allWindowIdList() const { return callPlatformFunction, QVector(*)()>(_getWindows); } /*! \brief DWindowManagerHelper::currentWorkspaceWindowIdList \return 返回当å‰�工作区所有本地窗å�£çš„窗å�£id列表 \note 顺åº�和窗å�£å±‚å� é¡ºåº�相关,显示越é� ä¸‹å±‚的窗å�£åœ¨åˆ—表中顺åº�è¶Šé� å‰� \sa DWindowManagerHelper::allWindowIdList */ QVector DWindowManagerHelper::currentWorkspaceWindowIdList() const { return callPlatformFunction, QVector(*)()>(_getCurrentWorkspaceWindows); } /*! \brief DWindowManagerHelper::currentWorkspaceWindowIdList \return 返回当å‰�工作区所有本地窗å�£å¯¹è±¡åˆ—表。和 currentWorkspaceWindowIdList 类似,å�ªä¸�过自动通过窗å�£id创建了 DForeignWindow 对象 \note 顺åº�和窗å�£å±‚å� é¡ºåº�相关,显示越é� ä¸‹å±‚的窗å�£åœ¨åˆ—表中顺åº�è¶Šé� å‰� \note 列表中对象的生命周期由 DForeignWindow è´Ÿè´£ \warning 此列表中ä¸�包å�«ç”±å½“å‰�应用创建的窗å�£ \sa DWindowManagerHelper::currentWorkspaceWindowIdList \sa DForeignWindow::fromWinId */ QList DWindowManagerHelper::currentWorkspaceWindows() const { D_DC(DWindowManagerHelper); for (QWindow *w : d->windowList) { w->deleteLater(); } d->windowList.clear(); QList currentApplicationWindowList; const QWindowList &list = qApp->allWindows(); currentApplicationWindowList.reserve(list.size()); for (auto window : list) { if (window->property("_q_foreignWinId").isValid()) continue; currentApplicationWindowList.append(window->winId()); } QVector wmClientList = currentWorkspaceWindowIdList(); for (WId wid : wmClientList) { if (currentApplicationWindowList.contains(wid)) continue; if (DForeignWindow *w = DForeignWindow::fromWinId(wid)) { d->windowList << w; } } return d->windowList; } /*! \brief DWindowManagerHelper::windowFromPoint \return 返回 \a p ä½�置的窗å�£ Id,如果出错返回 0 \note å�¯ä»¥é€šè¿‡ DForeignWindow::fromWinId 创建窗å�£å¯¹è±¡ */ quint32 DWindowManagerHelper::windowFromPoint(const QPoint &p) { return callPlatformFunction(_windowFromPoint, p); } /*! \brief DWindowManagerHelper::DWindowManagerHelper ä¸�å…�许直接实例化此对象 \a parent \sa DWindowManagerHelper::instance */ DWindowManagerHelper::DWindowManagerHelper(QObject *parent) : QObject(parent) , DObject(*new DWindowManagerHelperPrivate(this)) { connectWindowManagerChangedSignal(this, [this] { Q_EMIT windowManagerChanged(); }); connectHasBlurWindowChanged(this, [this] { Q_EMIT hasBlurWindowChanged(); }); connectHasCompositeChanged(this, [this] { Q_EMIT hasCompositeChanged(); }); connectHasNoTitlebarChanged(this, [this] { Q_EMIT hasNoTitlebarChanged(); }); connectHasWallpaperEffectChanged(this, [this] { Q_EMIT hasWallpaperEffectChanged(); }); connectWindowListChanged(this, [this] { Q_EMIT windowListChanged(); }); connectWindowMotifWMHintsChanged(this, [this] (quint32 winId) { Q_EMIT windowMotifWMHintsChanged(winId); }); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/kernel/kernel.cmake000066400000000000000000000005571522615413000174440ustar00rootroot00000000000000file(GLOB KERNEL_HEADER ${CMAKE_CURRENT_LIST_DIR}/../../include/kernel/*.h ) file(GLOB KERNEL_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(kernel_SRC ${KERNEL_HEADER} ${KERNEL_SOURCE} ) dtk_add_config_to_cpp(kernel_SRC /usr/share/dsg/configs/org.deepin.dtk.preference.json OUTPUT_FILE_NAME orgdeepindtkpreference.hpp CLASS_NAME OrgDeepinDTKPreference ) dtkgui-6.7.46/src/plugins/000077500000000000000000000000001522615413000153545ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/dplatforminterface.cpp000066400000000000000000000142411522615413000217330ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dplatformtheme.h" #include "private/dplatforminterface_p.h" DGUI_BEGIN_NAMESPACE DPlatformInterface::DPlatformInterface(DPlatformTheme *platformTheme) : m_platformTheme(platformTheme) { } DPlatformInterface::~DPlatformInterface() { } int DPlatformInterface::cursorBlinkTime() const { return {}; } int DPlatformInterface::cursorBlinkTimeout() const { return {}; } bool DPlatformInterface::cursorBlink() const { return {}; } int DPlatformInterface::doubleClickDistance() const { return {}; } int DPlatformInterface::doubleClickTime() const { return {}; } int DPlatformInterface::dndDragThreshold() const { return {}; } int DPlatformInterface::windowRadius() const { return -1; } int DPlatformInterface::windowRadius(int defaultValue) const { return defaultValue; } QByteArray DPlatformInterface::themeName() const { return {}; } QByteArray DPlatformInterface::iconThemeName() const { return {}; } QByteArray DPlatformInterface::soundThemeName() const { return {}; } QByteArray DPlatformInterface::fontName() const { return {}; } QByteArray DPlatformInterface::monoFontName() const { return {}; } qreal DPlatformInterface::fontPointSize() const { return {}; } QByteArray DPlatformInterface::gtkFontName() const { return {}; } QColor DPlatformInterface::activeColor() const { return {}; } QColor DPlatformInterface::darkActiveColor() const { return {}; } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QColor DPlatformInterface::window() const { return {}; } QColor DPlatformInterface::windowText() const { return {}; } QColor DPlatformInterface::base() const { return {}; } QColor DPlatformInterface::alternateBase() const { return {}; } QColor DPlatformInterface::toolTipBase() const { return {}; } QColor DPlatformInterface::toolTipText() const { return {}; } QColor DPlatformInterface::text() const { return {}; } QColor DPlatformInterface::button() const { return {}; } QColor DPlatformInterface::buttonText() const { return {}; } QColor DPlatformInterface::brightText() const { return {}; } QColor DPlatformInterface::light() const { return {}; } QColor DPlatformInterface::midlight() const { return {}; } QColor DPlatformInterface::dark() const { return {}; } QColor DPlatformInterface::mid() const { return {}; } QColor DPlatformInterface::shadow() const { return {}; } QColor DPlatformInterface::highlight() const { return {}; } QColor DPlatformInterface::highlightedText() const { return {}; } QColor DPlatformInterface::link() const { return {}; } QColor DPlatformInterface::linkVisited() const { return {}; } QColor DPlatformInterface::itemBackground() const { return {}; } QColor DPlatformInterface::textTitle() const { return {}; } QColor DPlatformInterface::textTips() const { return {}; } QColor DPlatformInterface::textWarning() const { return {}; } QColor DPlatformInterface::textLively() const { return {}; } QColor DPlatformInterface::lightLively() const { return {}; } QColor DPlatformInterface::darkLively() const { return {}; } QColor DPlatformInterface::frameBorder() const { return {}; } #endif int DPlatformInterface::dotsPerInch(const QString &) const { return {}; } int DPlatformInterface::sizeMode() const { return {}; } int DPlatformInterface::scrollBarPolicy() const { return {}; } void DPlatformInterface::setCursorBlinkTime(int) { } void DPlatformInterface::setCursorBlinkTimeout(int) { } void DPlatformInterface::setCursorBlink(bool) { } void DPlatformInterface::setDoubleClickDistance(int) { } void DPlatformInterface::setDoubleClickTime(int) { } void DPlatformInterface::setDndDragThreshold(int) { } void DPlatformInterface::setThemeName(const QByteArray &) { } void DPlatformInterface::setIconThemeName(const QByteArray &) { } void DPlatformInterface::setSoundThemeName(const QByteArray &) { } void DPlatformInterface::setFontName(const QByteArray &) { } void DPlatformInterface::setMonoFontName(const QByteArray &) { } void DPlatformInterface::setFontPointSize(qreal) { } void DPlatformInterface::setGtkFontName(const QByteArray &) { } void DPlatformInterface::setActiveColor(const QColor) { } void DPlatformInterface::setDarkActiveColor(const QColor &) { } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void DPlatformInterface::setWindow(const QColor &) { } void DPlatformInterface::setWindowText(const QColor &) { } void DPlatformInterface::setBase(const QColor &) { } void DPlatformInterface::setAlternateBase(const QColor &) { } void DPlatformInterface::setToolTipBase(const QColor &) { } void DPlatformInterface::setToolTipText(const QColor &) { } void DPlatformInterface::setText(const QColor &) { } void DPlatformInterface::setButton(const QColor &) { } void DPlatformInterface::setButtonText(const QColor &) { } void DPlatformInterface::setBrightText(const QColor &) { } void DPlatformInterface::setLight(const QColor &) { } void DPlatformInterface::setMidlight(const QColor &) { } void DPlatformInterface::setDark(const QColor &) { } void DPlatformInterface::setMid(const QColor &) { } void DPlatformInterface::setShadow(const QColor &) { } void DPlatformInterface::setHighlight(const QColor &) { } void DPlatformInterface::setHighlightedText(const QColor &) { } void DPlatformInterface::setLink(const QColor &) { } void DPlatformInterface::setLinkVisited(const QColor &) { } void DPlatformInterface::setItemBackground(const QColor &) { } void DPlatformInterface::setTextTitle(const QColor &) { } void DPlatformInterface::setTextTips(const QColor &) { } void DPlatformInterface::setTextWarning(const QColor &) { } void DPlatformInterface::setTextLively(const QColor &) { } void DPlatformInterface::setLightLively(const QColor &) { } void DPlatformInterface::setDarkLively(const QColor &) { } void DPlatformInterface::setFrameBorder(const QColor &) { } #endif void DPlatformInterface::setDotsPerInch(const QString &, int) { } void DPlatformInterface::setWindowRadius(int) { } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/dplatformwindowinterface.cpp000066400000000000000000000070461522615413000231700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "private/dplatformwindowinterface_p.h" DGUI_BEGIN_NAMESPACE DPlatformWindowInterface::DPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle) : m_window(window) , m_platformHandle(platformHandle) { } DPlatformWindowInterface::~DPlatformWindowInterface() { } QWindow *DPlatformWindowInterface::window() const { return m_window; } void DPlatformWindowInterface::setEnabled(bool enabled) { Q_UNUSED(enabled) } bool DPlatformWindowInterface::isEnabled() const { return false; } bool DPlatformWindowInterface::isEnabledNoTitlebar() const { return {}; } bool DPlatformWindowInterface::setEnabledNoTitlebar(bool enable) { Q_UNUSED(enable) return {}; } void DPlatformWindowInterface::setDisableWindowOverrideCursor(bool disable) { Q_UNUSED(disable) } int DPlatformWindowInterface::windowRadius() const { return -1; } void DPlatformWindowInterface::setWindowRadius(int windowRadius) { Q_UNUSED(windowRadius) } int DPlatformWindowInterface::borderWidth() const { return -1; } void DPlatformWindowInterface::setBorderWidth(int borderWidth) { Q_UNUSED(borderWidth) } QColor DPlatformWindowInterface::borderColor() const { return {}; } void DPlatformWindowInterface::setBorderColor(const QColor &borderColor) { Q_UNUSED(borderColor) } int DPlatformWindowInterface::shadowRadius() const { return {}; } void DPlatformWindowInterface::setShadowRadius(int shadowRadius) { Q_UNUSED(shadowRadius) } QPoint DPlatformWindowInterface::shadowOffset() const { return {}; } void DPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset) { Q_UNUSED(shadowOffset) } QColor DPlatformWindowInterface::shadowColor() const { return {}; } void DPlatformWindowInterface::setShadowColor(const QColor &shadowColor) { Q_UNUSED(shadowColor) } DPlatformHandle::EffectScene DPlatformWindowInterface::windowEffect() { return {}; } void DPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { Q_UNUSED(effectScene) } DPlatformHandle::EffectType DPlatformWindowInterface::windowStartUpEffect() { return {}; } void DPlatformWindowInterface::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) { Q_UNUSED(effectType) } QPainterPath DPlatformWindowInterface::clipPath() const { return {}; } void DPlatformWindowInterface::setClipPath(const QPainterPath &clipPath) { Q_UNUSED(clipPath) } QRegion DPlatformWindowInterface::frameMask() const { return {}; } void DPlatformWindowInterface::setFrameMask(const QRegion &frameMask) { Q_UNUSED(frameMask) } QMargins DPlatformWindowInterface::frameMargins() const { return {}; } bool DPlatformWindowInterface::translucentBackground() const { return {}; } void DPlatformWindowInterface::setTranslucentBackground(bool translucentBackground) { Q_UNUSED(translucentBackground) } bool DPlatformWindowInterface::enableSystemResize() const { return {}; } void DPlatformWindowInterface::setEnableSystemResize(bool enableSystemResize) { Q_UNUSED(enableSystemResize) } bool DPlatformWindowInterface::enableSystemMove() const { return {}; } void DPlatformWindowInterface::setEnableSystemMove(bool enableSystemMove) { Q_UNUSED(enableSystemMove) } bool DPlatformWindowInterface::enableBlurWindow() const { return {}; } void DPlatformWindowInterface::setEnableBlurWindow(bool enableBlurWindow) { Q_UNUSED(enableBlurWindow) } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/000077500000000000000000000000001522615413000172005ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/platform/config.tests/000077500000000000000000000000001522615413000216065ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/platform/config.tests/treeland_test/000077500000000000000000000000001522615413000244435ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/platform/config.tests/treeland_test/CMakeLists.txt000066400000000000000000000036201522615413000272040ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later cmake_minimum_required(VERSION 3.16) project(wayland_test) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(AUTOMOC_COMPILER_PREDEFINES ON) find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui WaylandClient) if(${QT_VERSION_MAJOR} STREQUAL "5") find_package(Qt5 REQUIRED COMPONENTS XkbCommonSupport) endif() find_package(PkgConfig REQUIRED) pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client) find_package(TreelandProtocols) set(TreelandProtocols_FOUND ${TreelandProtocols_FOUND}) add_executable(${PROJECT_NAME} main.cpp) if("${QT_VERSION_MAJOR}" STREQUAL "6") qt6_generate_wayland_protocol_client_sources(${PROJECT_NAME} FILES ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml ) if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0") set(QT_NO_PRIVATE_MODULE_WARNING ON) find_package(Qt6 REQUIRED COMPONENTS GuiPrivate CorePrivate WaylandClientPrivate) endif() else() # ECM setup include(FeatureSummary) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}") find_package(QtWaylandScanner) ecm_add_qtwayland_client_protocol(TABLET_SRCS PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml BASENAME treeland-personalization-manager-v1 ) target_sources(${PROJECT_NAME} PRIVATE ${TABLET_SRCS}) target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::XkbCommonSupportPrivate ) endif() target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::GuiPrivate Qt${QT_VERSION_MAJOR}::CorePrivate Qt${QT_VERSION_MAJOR}::WaylandClientPrivate ${WAYLAND_CLIENT_LIBRARIES} ) dtkgui-6.7.46/src/plugins/platform/config.tests/treeland_test/main.cpp000066400000000000000000000022721522615413000260760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include "qwayland-treeland-personalization-manager-v1.h" #include #include #include #include #include class PersonalizationWindowContext : public QWaylandClientExtensionTemplate, public QtWayland::treeland_personalization_window_context_v1 { public: PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context) : QWaylandClientExtensionTemplate(1) , QtWayland::treeland_personalization_window_context_v1(context) { set_titlebar(enable_mode::enable_mode_disable); } }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); return 0; } dtkgui-6.7.46/src/plugins/platform/treeland/000077500000000000000000000000001522615413000207765ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandplatforminterface.cpp000066400000000000000000000066141522615413000271010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dtreelandplatforminterface.h" #include "dplatformtheme.h" #include "private/dplatforminterface_p.h" #include "personalizationwaylandclientextension.h" #include #include #include DGUI_BEGIN_NAMESPACE DTreelandPlatformInterface::DTreelandPlatformInterface(DPlatformTheme *platformTheme) : DPlatformInterface(platformTheme) , m_manager(nullptr) , m_activeColor(QColor()) , m_titleHeight(0) , m_fontName(QByteArray()) , m_monoFontName(QByteArray()) , m_iconThemeName(QByteArray()) , m_cursorThemeName(QByteArray()) , m_fontPointSize(0.0) , m_windowRadius(0) , m_scrollBarPolicy(0) , m_themeName(QByteArray()) , m_blurOpacity(0) { m_manager = PersonalizationManager::instance(); connect(m_manager, &PersonalizationManager::activeChanged, this, [this](){ if (m_manager->isActive()) { initContext(); } }); } void DTreelandPlatformInterface::initContext() { if (m_appearanceContext.isNull()) { m_appearanceContext.reset(new PersonalizationAppearanceContext(m_manager->get_appearance_context(), this)); } if (m_fontContext.isNull()) { m_fontContext.reset(new PersonalizationFontContext(m_manager->get_font_context(), this)); } } QByteArray DTreelandPlatformInterface::iconThemeName() const { return m_iconThemeName; } QByteArray DTreelandPlatformInterface::fontName() const { return m_fontName; } QByteArray DTreelandPlatformInterface::monoFontName() const { return m_monoFontName; } qreal DTreelandPlatformInterface::fontPointSize() const { return m_fontPointSize; } QColor DTreelandPlatformInterface::activeColor() const { return m_activeColor; } QColor DTreelandPlatformInterface::darkActiveColor() const { // treeland does not provide dark active color, return active color as fallback return m_activeColor; } QByteArray DTreelandPlatformInterface::themeName() const { return m_themeName; } int DTreelandPlatformInterface::windowRadius() const { return m_windowRadius; } int DTreelandPlatformInterface::windowRadius(int defaultValue) const { return m_windowRadius > 0 ? m_windowRadius : defaultValue; } void DTreelandPlatformInterface::setWindowRadius(int windowRadius) { if (m_appearanceContext) { m_appearanceContext->set_round_corner_radius(windowRadius); } } void DTreelandPlatformInterface::setIconThemeName(const QByteArray &iconThemeName) { if (m_appearanceContext) { m_appearanceContext->set_icon_theme(iconThemeName); } } void DTreelandPlatformInterface::setFontName(const QByteArray &fontName) { if (m_fontContext) { m_fontContext->set_font(fontName); } } void DTreelandPlatformInterface::setMonoFontName(const QByteArray &monoFontName) { if (m_fontContext) { m_fontContext->set_monospace_font(monoFontName); } } void DTreelandPlatformInterface::setFontPointSize(qreal fontPointSize) { if (m_fontContext) { m_fontContext->set_font_size(fontPointSize); } } void DTreelandPlatformInterface::setActiveColor(const QColor activeColor) { if (m_appearanceContext) { m_appearanceContext->set_active_color(activeColor.name()); } } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandplatforminterface.h000066400000000000000000000041671522615413000265470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTREELANDPLATFORMINTERFACE_H #define DTREELANDPLATFORMINTERFACE_H #include "private/dplatforminterface_p.h" #include #include #include DGUI_BEGIN_NAMESPACE class DTreelandPlatformInterfacePrivate; class PersonalizationManager; class PersonalizationFontContext; class PersonalizationAppearanceContext; class PersonalizationWindowContext; class DTreelandPlatformInterface : public QObject, public DPlatformInterface, public DCORE_NAMESPACE::DObject { Q_OBJECT friend PersonalizationFontContext; friend PersonalizationAppearanceContext; friend PersonalizationWindowContext; public: explicit DTreelandPlatformInterface(DPlatformTheme *platformTheme); QByteArray iconThemeName() const override; QByteArray fontName() const override; QByteArray monoFontName() const override; qreal fontPointSize() const override; QColor activeColor() const override; QColor darkActiveColor() const override; QByteArray themeName() const override; int windowRadius() const override; int windowRadius(int defaultValue = 12) const override; void setWindowRadius(int windowRadius) override; void setIconThemeName(const QByteArray &iconThemeName) override; void setFontName(const QByteArray &fontName) override; void setMonoFontName(const QByteArray &monoFontName) override; void setFontPointSize(qreal fontPointSize) override; void setActiveColor(const QColor activeColor) override; private: void initContext(); private: PersonalizationManager *m_manager; QScopedPointer m_appearanceContext; QScopedPointer m_fontContext; QColor m_activeColor; int m_titleHeight; QByteArray m_fontName; QByteArray m_monoFontName; QByteArray m_iconThemeName; QByteArray m_cursorThemeName; qreal m_fontPointSize; int m_windowRadius; int m_scrollBarPolicy; QByteArray m_themeName; uint32_t m_blurOpacity; }; DGUI_END_NAMESPACE #endif dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp000066400000000000000000000431331522615413000303260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include "dtreelandplatformwindowinterface.h" #include "util/dprivateaccessor_p.h" #include #include #include #include #include #include #include "dvtablehook.h" #include "personalizationwaylandclientextension.h" DCORE_USE_NAMESPACE D_DECLARE_PRIVATE_METHOD(QWindow_event_tag, QWindow, event, bool, QEvent *); DGUI_BEGIN_NAMESPACE static inline auto qWindowEventMember() { return get(QWindow_event_tag{}); } class Q_DECL_HIDDEN MoveWindowHelper : public QObject { public: explicit MoveWindowHelper(QWindow *w); ~MoveWindowHelper(); static QHash mapped; private: static bool windowEvent(QWindow *w, QEvent *event); void updateEnableSystemMoveFromProperty(); QWindow *m_window; bool m_windowMoving; bool m_enableSystemMove; QPointF m_pressPoint; }; QHash MoveWindowHelper::mapped; MoveWindowHelper::MoveWindowHelper(QWindow *window) : QObject(window) , m_window(window) , m_windowMoving(false) , m_enableSystemMove(false) { mapped[window] = this; updateEnableSystemMoveFromProperty(); } MoveWindowHelper::~MoveWindowHelper() { mapped.remove(static_cast(parent())); } void MoveWindowHelper::updateEnableSystemMoveFromProperty() { if (!m_window) { return; } const QVariant &v = m_window->property("_d_enableSystemMove"); m_enableSystemMove = !v.isValid() || v.toBool(); if (m_enableSystemMove) { DVtableHook::overrideVfptrFun(m_window, qWindowEventMember(), &MoveWindowHelper::windowEvent); } else if (DVtableHook::hasVtable(m_window)) { m_windowMoving = false; m_pressPoint = QPointF(); DVtableHook::resetVfptrFun(m_window, qWindowEventMember()); } } bool MoveWindowHelper::windowEvent(QWindow *w, QEvent *event) { MoveWindowHelper *self = mapped.value(w); if (!self) return DVtableHook::callOriginalFun(w, qWindowEventMember(), event); // TODO Crashed when delete by Vtable. if (event->type() == QEvent::DeferredDelete) { DVtableHook::resetVtable(w); return D_PRIVATE_CALL(*w, QWindow_event_tag{}, event); } // get touch begin position static bool isTouchDown = false; static QPointF touchBeginPosition; if (event->type() == QEvent::TouchBegin) { isTouchDown = true; } if (event->type() == QEvent::TouchEnd || event->type() == QEvent::MouseButtonRelease) { isTouchDown = false; } if (isTouchDown && event->type() == QEvent::MouseButtonPress) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) touchBeginPosition = static_cast(event)->globalPosition(); #else touchBeginPosition = static_cast(event)->globalPos(); #endif } // add some redundancy to distinguish trigger between system menu and system move if (event->type() == QEvent::MouseMove) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QPointF currentPos = static_cast(event)->globalPosition(); #else QPointF currentPos = static_cast(event)->globalPos(); #endif QPointF delta = touchBeginPosition - currentPos; if (delta.manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) { return DVtableHook::callOriginalFun(w, qWindowEventMember(), event); } } bool is_mouse_move = event->type() == QEvent::MouseMove && static_cast(event)->buttons() == Qt::LeftButton; if (event->type() == QEvent::MouseButtonRelease) { self->m_windowMoving = false; self->m_pressPoint = QPointF(); } bool ret = DVtableHook::callOriginalFun(w, qWindowEventMember(), event); // workaround for kwin: Qt receives no release event when kwin finishes MOVE operation, // which makes app hang in windowMoving state. when a press happens, there's no sense of // keeping the moving state, we can just reset it back to normal. if (event->type() == QEvent::MouseButtonPress) { self->m_windowMoving = false; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) self->m_pressPoint = static_cast(event)->globalPosition(); #else self->m_pressPoint = static_cast(event)->globalPos(); #endif } if (is_mouse_move && !event->isAccepted() && !self->m_pressPoint.isNull()) { QMouseEvent *me = static_cast(event); QRect windowRect = QRect(QPoint(0, 0), w->size()); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (!windowRect.contains(me->scenePosition().toPoint())) { #else if (!windowRect.contains(me->localPos().toPoint())) { #endif return ret; } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QPointF delta = me->globalPosition() - self->m_pressPoint; #else QPointF delta = me->globalPos() - self->m_pressPoint; #endif if (delta.manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) { return ret; } if (!self->m_windowMoving && self->m_enableSystemMove) { self->m_windowMoving = true; event->accept(); if (w && w->handle()) { #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) static_cast(w->handle())->startSystemMove(QCursor::pos()); #else static_cast(w->handle())->startSystemMove(); #endif } } } return ret; } QMap DTreeLandPlatformWindowHelper::windowMap; DTreeLandPlatformWindowHelper *DTreeLandPlatformWindowHelper::get(QWindow *window) { if (!PersonalizationManager::instance()->isSupported()) { return nullptr; } if (!window) { return nullptr; } if (auto helper = windowMap.value(window)) { return helper; } auto helper = new DTreeLandPlatformWindowHelper(window); windowMap[window] = helper; return helper; } DTreeLandPlatformWindowHelper::DTreeLandPlatformWindowHelper(QWindow *window) : QObject(window) { window->installEventFilter(this); if (!PersonalizationManager::instance()->isActive()) { qWarning() << "Personalization is not active" << window; connect(PersonalizationManager::instance(), &PersonalizationManager::activeChanged, this, &DTreeLandPlatformWindowHelper::onActiveChanged, Qt::QueuedConnection); } if (window->handle()) { initWaylandWindow(); } } DTreeLandPlatformWindowHelper::~DTreeLandPlatformWindowHelper() { if (m_windowContext) { delete m_windowContext; m_windowContext = nullptr; } windowMap.remove(static_cast(parent())); } bool DTreeLandPlatformWindowHelper::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::PlatformSurface) { QPlatformSurfaceEvent *se = static_cast(event); if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { if (PersonalizationManager::instance()->isActive()) { initWaylandWindow(); onSurfaceCreated(); } } } return QObject::eventFilter(watched, event); } void DTreeLandPlatformWindowHelper::initWaylandWindow() { auto waylandWindow = dynamic_cast(window()->handle()); if (!waylandWindow) { qWarning() << "waylandWindow is nullptr!!!"; return; } connect(waylandWindow, &QtWaylandClient::QWaylandWindow::wlSurfaceCreated, this, &DTreeLandPlatformWindowHelper::onSurfaceCreated, Qt::UniqueConnection); connect(waylandWindow, &QtWaylandClient::QWaylandWindow::wlSurfaceDestroyed, this, &DTreeLandPlatformWindowHelper::onSurfaceDestroyed, Qt::UniqueConnection); } void DTreeLandPlatformWindowHelper::onActiveChanged() { if (PersonalizationManager::instance()->isActive()) { if (window()->handle()) { initWaylandWindow(); onSurfaceCreated(); } } } void DTreeLandPlatformWindowHelper::onSurfaceCreated() { m_dirty = m_initialized; scheduleApply(); } void DTreeLandPlatformWindowHelper::onSurfaceDestroyed() { if (m_windowContext) { delete m_windowContext; m_windowContext = nullptr; } } PersonalizationWindowContext *DTreeLandPlatformWindowHelper::windowContext() const { if (m_windowContext) { return m_windowContext; } auto waylandWindow = dynamic_cast(window()->handle()); if (!waylandWindow) return nullptr; if (!waylandWindow->waylandSurface()) { qWarning() << "waylandSurface is nullptr!!!"; return nullptr; } auto surface = waylandWindow->waylandSurface()->object(); if (!surface) { qWarning() << "wl_surface is nullptr!!!"; return nullptr; } if (!m_windowContext) { const_cast(this)->m_windowContext = new PersonalizationWindowContext(PersonalizationManager::instance()->get_window_context(surface)); } return m_windowContext; } void DTreeLandPlatformWindowHelper::setEnabledNoTitlebar(bool enable) { updateFeature(m_noTitlebar, enable, NoTitlebar); } void DTreeLandPlatformWindowHelper::setWindowRadius(int windowRadius) { updateFeature(m_radius, windowRadius, Radius); } void DTreeLandPlatformWindowHelper::setBorderWidth(int borderWidth) { updateFeature(m_borderWidth, borderWidth, Border); } void DTreeLandPlatformWindowHelper::setBorderColor(const QColor &borderColor) { updateFeature(m_borderColor, borderColor, Border); } void DTreeLandPlatformWindowHelper::setShadowRadius(int shadowRadius) { updateFeature(m_shadowRadius, shadowRadius, Shadow); } void DTreeLandPlatformWindowHelper::setShadowOffset(const QPoint &shadowOffset) { updateFeature(m_shadowOffset, shadowOffset, Shadow); } void DTreeLandPlatformWindowHelper::setShadowColor(const QColor &shadowColor) { updateFeature(m_shadowColor, shadowColor, Shadow); } void DTreeLandPlatformWindowHelper::setEnableBlurWindow(bool enableBlurWindow) { updateFeature(m_blur, enableBlurWindow, Blur); } void DTreeLandPlatformWindowHelper::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { updateFeature(m_effectScene, effectScene, WindowEffect); } void DTreeLandPlatformWindowHelper::setPlatformHandle(DPlatformHandle *handle) { m_platformHandle = handle; } void DTreeLandPlatformWindowHelper::scheduleApply() { if (m_applyScheduled) return; m_applyScheduled = true; QMetaObject::invokeMethod(this, &DTreeLandPlatformWindowHelper::applyPending); } void DTreeLandPlatformWindowHelper::applyPending() { m_applyScheduled = false; if (auto context = windowContext()) { if (m_dirty & NoTitlebar) { m_dirty &= ~NoTitlebar; context->set_titlebar(m_noTitlebar ? PersonalizationWindowContext::enable_mode_disable : PersonalizationWindowContext::enable_mode_enable); } if (m_dirty & Radius) { m_dirty &= ~Radius; context->set_round_corner_radius(m_radius); } if (m_dirty & Blur) { m_dirty &= ~Blur; context->set_blend_mode(m_blur ? PersonalizationWindowContext::blend_mode_blur : PersonalizationWindowContext::blend_mode_transparent); } if (m_dirty & Border) { m_dirty &= ~Border; context->set_border(m_borderWidth, m_borderColor.red(), m_borderColor.green(), m_borderColor.blue(), m_borderColor.alpha()); } if (m_dirty & Shadow) { m_dirty &= ~Shadow; context->set_shadow(m_shadowRadius, m_shadowOffset.x(), m_shadowOffset.y(), m_shadowColor.red(), m_shadowColor.green(), m_shadowColor.blue(), m_shadowColor.alpha()); } if (m_dirty & WindowEffect) { m_dirty &= ~WindowEffect; if (m_effectScene.testFlag(DPlatformHandle::EffectNoRadius)) { context->set_round_corner_radius(0); } if (m_effectScene.testFlag(DPlatformHandle::EffectNoShadow)) { context->set_shadow(0, 0, 0, 0, 0, 0, 0); } if (m_effectScene.testFlag(DPlatformHandle::EffectNoBorder)) { context->set_border(0, 0, 0, 0, 0); } } } } DTreeLandPlatformWindowInterface::DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent) : QObject(parent) , DPlatformWindowInterface(window, platformHandle) { if (!MoveWindowHelper::mapped.value(window)) { Q_UNUSED(new MoveWindowHelper(window)) } if (auto helper = DTreeLandPlatformWindowHelper::get(window)) { helper->setPlatformHandle(platformHandle); } } DTreeLandPlatformWindowInterface::~DTreeLandPlatformWindowInterface() { } void DTreeLandPlatformWindowInterface::setEnabled(bool enabled) { setEnabledNoTitlebar(enabled); } bool DTreeLandPlatformWindowInterface::isEnabled() const { return isEnabledNoTitlebar(); } bool DTreeLandPlatformWindowInterface::isEnabledNoTitlebar() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->isEnabledNoTitlebar(); return false; } bool DTreeLandPlatformWindowInterface::setEnabledNoTitlebar(bool enable) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setEnabledNoTitlebar(enable); return true; } return false; } int DTreeLandPlatformWindowInterface::windowRadius() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->windowRadius(); return 0; } void DTreeLandPlatformWindowInterface::setWindowRadius(int windowRadius) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setWindowRadius(windowRadius); if (m_platformHandle) Q_EMIT m_platformHandle->windowRadiusChanged(); } } int DTreeLandPlatformWindowInterface::borderWidth() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->borderWidth(); return 0; } void DTreeLandPlatformWindowInterface::setBorderWidth(int borderWidth) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setBorderWidth(borderWidth); if (m_platformHandle) Q_EMIT m_platformHandle->borderWidthChanged(); } } QColor DTreeLandPlatformWindowInterface::borderColor() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->borderColor(); return {}; } void DTreeLandPlatformWindowInterface::setBorderColor(const QColor &borderColor) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setBorderColor(borderColor); if (m_platformHandle) Q_EMIT m_platformHandle->borderColorChanged(); } } int DTreeLandPlatformWindowInterface::shadowRadius() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->shadowRadius(); return 0; } void DTreeLandPlatformWindowInterface::setShadowRadius(int shadowRadius) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setShadowRadius(shadowRadius); if (m_platformHandle) Q_EMIT m_platformHandle->shadowRadiusChanged(); } } QPoint DTreeLandPlatformWindowInterface::shadowOffset() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->shadowOffset(); return {}; } void DTreeLandPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setShadowOffset(shadowOffset); if (m_platformHandle) Q_EMIT m_platformHandle->shadowOffsetChanged(); } } QColor DTreeLandPlatformWindowInterface::shadowColor() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->shadowColor(); return {}; } void DTreeLandPlatformWindowInterface::setShadowColor(const QColor &shadowColor) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setShadowColor(shadowColor); if (m_platformHandle) Q_EMIT m_platformHandle->shadowColorChanged(); } } bool DTreeLandPlatformWindowInterface::enableBlurWindow() const { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return helper->enableBlurWindow(); return false; } void DTreeLandPlatformWindowInterface::setEnableBlurWindow(bool enable) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setEnableBlurWindow(enable); if (m_platformHandle) Q_EMIT m_platformHandle->enableBlurWindowChanged(); } } DPlatformHandle::EffectScene DTreeLandPlatformWindowInterface::windowEffect() { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) return static_cast(static_cast(helper->windowEffect())); return {}; } void DTreeLandPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) { helper->setWindowEffect(effectScene); if (m_platformHandle) Q_EMIT m_platformHandle->windowEffectChanged(); } } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandplatformwindowinterface.h000066400000000000000000000105651522615413000277760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTREELANDPLATFORMWINDOWINTERFACE_H #define DTREELANDPLATFORMWINDOWINTERFACE_H #include "dtkgui_global.h" #include #include #include #include "private/dplatformwindowinterface_p.h" DGUI_BEGIN_NAMESPACE class PersonalizationWindowContext; class DTreeLandPlatformWindowHelper : public QObject { Q_OBJECT public: static DTreeLandPlatformWindowHelper *get(QWindow *window); ~DTreeLandPlatformWindowHelper() override; enum Feature { NoTitlebar = 1 << 0, Radius = 1 << 1, Blur = 1 << 2, Border = 1 << 3, Shadow = 1 << 4, WindowEffect = 1 << 5, }; Q_DECLARE_FLAGS(Features, Feature) QWindow *window() const { return qobject_cast(parent()); } PersonalizationWindowContext *windowContext() const; void setEnabledNoTitlebar(bool enable); void setWindowRadius(int windowRadius); void setBorderWidth(int borderWidth); void setBorderColor(const QColor &borderColor); void setShadowRadius(int shadowRadius); void setShadowOffset(const QPoint &shadowOffset); void setShadowColor(const QColor &shadowColor); void setEnableBlurWindow(bool enableBlurWindow); void setWindowEffect(DPlatformHandle::EffectScenes effectScene); void setPlatformHandle(DPlatformHandle *handle); bool isEnabledNoTitlebar() const { return m_noTitlebar; } int windowRadius() const { return m_radius; } int borderWidth() const { return m_borderWidth; } QColor borderColor() const { return m_borderColor; } int shadowRadius() const { return m_shadowRadius; } QPoint shadowOffset() const { return m_shadowOffset; } QColor shadowColor() const { return m_shadowColor; } bool enableBlurWindow() const { return m_blur; } DPlatformHandle::EffectScenes windowEffect() const { return m_effectScene; } private slots: void onActiveChanged(); void onSurfaceCreated(); void onSurfaceDestroyed(); void applyPending(); private: explicit DTreeLandPlatformWindowHelper(QWindow *window); bool eventFilter(QObject *watched, QEvent *event) override; void initWaylandWindow(); void scheduleApply(); template void updateFeature(T &member, const T &value, Feature flag) { member = value; m_initialized |= flag; m_dirty |= flag; scheduleApply(); } private: PersonalizationWindowContext *m_windowContext = nullptr; static QMap windowMap; DPlatformHandle *m_platformHandle = nullptr; bool m_noTitlebar = false; bool m_blur = false; int m_radius = 0; int m_borderWidth = 0; QColor m_borderColor; int m_shadowRadius = 0; QPoint m_shadowOffset; QColor m_shadowColor; DPlatformHandle::EffectScenes m_effectScene; Features m_initialized; Features m_dirty; bool m_applyScheduled = false; }; class DTreeLandPlatformWindowInterface : public QObject, public DPlatformWindowInterface { Q_OBJECT public: DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr); ~DTreeLandPlatformWindowInterface() override; void setEnabled(bool enabled) override; bool isEnabled() const override; bool isEnabledNoTitlebar() const override; bool setEnabledNoTitlebar(bool enable) override; int windowRadius() const override; void setWindowRadius(int windowRadius) override; int borderWidth() const override; void setBorderWidth(int borderWidth) override; QColor borderColor() const override; void setBorderColor(const QColor &borderColor) override; int shadowRadius() const override; void setShadowRadius(int shadowRadius) override; QPoint shadowOffset() const override; void setShadowOffset(const QPoint &shadowOffset) override; QColor shadowColor() const override; void setShadowColor(const QColor &shadowColor) override; bool enableBlurWindow() const override; void setEnableBlurWindow(bool enableBlurWindow) override; DPlatformHandle::EffectScene windowEffect() override; void setWindowEffect(DPlatformHandle::EffectScenes effectScene) override; }; DGUI_END_NAMESPACE #endif // DTREELANDPLATFORMWINDOWINTERFACE_H dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandwindowmanagerhelper.cpp000066400000000000000000000015641522615413000274350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dtreelandwindowmanagerhelper.h" #include "personalizationwaylandclientextension.h" DGUI_BEGIN_NAMESPACE TreelandWindowManagerHelper::TreelandWindowManagerHelper(QObject *parent) : DWindowManagerHelper(parent) { connect(PersonalizationManager::instance(), &PersonalizationManager::activeChanged, this, [this](){ Q_EMIT hasBlurWindowChanged(); Q_EMIT hasNoTitlebarChanged(); }); } bool TreelandWindowManagerHelper::hasBlurWindow() const { return PersonalizationManager::instance()->isSupported(); } bool TreelandWindowManagerHelper::hasComposite() const { return true; } bool TreelandWindowManagerHelper::hasNoTitlebar() const { return PersonalizationManager::instance()->isSupported(); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/treeland/dtreelandwindowmanagerhelper.h000066400000000000000000000011311522615413000270700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTREELANDWINDOWMANAGERHELPER_H #define DTREELANDWINDOWMANAGERHELPER_H #include "dtkgui_global.h" #include "dwindowmanagerhelper.h" #include DGUI_BEGIN_NAMESPACE class TreelandWindowManagerHelper : public DWindowManagerHelper { public: explicit TreelandWindowManagerHelper(QObject *parent = 0); bool hasBlurWindow() const; bool hasComposite() const; bool hasNoTitlebar() const; }; DGUI_END_NAMESPACE #endif // DTREELANDWINDOWMANAGERHELPER_H dtkgui-6.7.46/src/plugins/platform/treeland/personalizationwaylandclientextension.cpp000066400000000000000000000140341522615413000314410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "personalizationwaylandclientextension.h" #include #include #include #include #include "dplatformtheme.h" #include #include #include DGUI_BEGIN_NAMESPACE PersonalizationManager::PersonalizationManager() : QWaylandClientExtensionTemplate(treeland_personalization_manager_v1_interface.version) , m_isSupported(false) { QtWaylandClient::QWaylandIntegration *waylandIntegration = static_cast(QGuiApplicationPrivate::platformIntegration()); if (!waylandIntegration) { qWarning() << "waylandIntegration is nullptr!!!"; return; } m_waylandDisplay = waylandIntegration->display(); if (m_waylandDisplay == nullptr) { qWarning() << "waylandDisplay is nullptr!!!"; return; } addListener(); m_isSupported = m_waylandDisplay->hasRegistryGlobal(QString::fromUtf8(treeland_personalization_manager_v1_interface.name)); if (!m_isSupported) { qWarning() << "PersonalizationManager is not support"; } } void PersonalizationManager::addListener() { m_waylandDisplay->addRegistryListener(&handleListenerGlobal, this); } void PersonalizationManager::removeListener() { m_waylandDisplay->removeListener(&handleListenerGlobal, this); } void PersonalizationManager::handleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version) { if (interface == treeland_personalization_manager_v1_interface.name) { PersonalizationManager *integration = static_cast(data); if (!integration) { qWarning() << "integration is nullptr!!!"; return; } integration->init(registry, id, version); } } PersonalizationManager *PersonalizationManager::instance() { static PersonalizationManager instance; return &instance; } PersonalizationWindowContext::PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context) : QWaylandClientExtensionTemplate(treeland_personalization_window_context_v1_interface.version) , QtWayland::treeland_personalization_window_context_v1(context) { } PersonalizationWindowContext::~PersonalizationWindowContext() { if (isInitialized()) destroy(); } PersonalizationAppearanceContext::~PersonalizationAppearanceContext() { if (isInitialized()) destroy(); } PersonalizationAppearanceContext::PersonalizationAppearanceContext(struct ::treeland_personalization_appearance_context_v1 *context, DTreelandPlatformInterface *interface) : QWaylandClientExtensionTemplate(treeland_personalization_appearance_context_v1_interface.version) , QtWayland::treeland_personalization_appearance_context_v1(context) , m_interface(interface) { get_round_corner_radius(); get_icon_theme(); get_active_color(); get_window_theme_type(); get_window_opacity(); } void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_round_corner_radius(int32_t radius) { m_interface->m_windowRadius = radius; emit m_interface->m_platformTheme->windowRadiusChanged(radius); } void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_icon_theme(const QString &theme_name) { m_interface->m_iconThemeName = theme_name.toUtf8(); emit m_interface->m_platformTheme->iconThemeNameChanged(theme_name.toUtf8()); } void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_active_color(const QString &active_color) { m_interface->m_activeColor = active_color; emit m_interface->m_platformTheme->activeColorChanged(active_color); } void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_window_theme_type(uint32_t type) { QString theme = QStringLiteral("deepin"); if (type == PersonalizationAppearanceContext::theme_type::theme_type_dark) { theme = theme + QStringLiteral("-dark"); } m_interface->m_themeName = theme.toUtf8(); emit m_interface->m_platformTheme->themeNameChanged(theme.toUtf8()); } void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_window_opacity(uint32_t opacity) { m_interface->m_blurOpacity = opacity; } PersonalizationFontContext::~PersonalizationFontContext() { if (isInitialized()) destroy(); } PersonalizationFontContext::PersonalizationFontContext(struct ::treeland_personalization_font_context_v1 *context, DTreelandPlatformInterface *interface) : QWaylandClientExtensionTemplate(treeland_personalization_font_context_v1_interface.version) , QtWayland::treeland_personalization_font_context_v1(context) , m_interface(interface) { get_font(); get_monospace_font(); get_font_size(); } void PersonalizationFontContext::treeland_personalization_font_context_v1_font(const QString &font_name) { m_interface->m_fontName = font_name.toUtf8(); emit m_interface->m_platformTheme->fontNameChanged(font_name.toUtf8()); } void PersonalizationFontContext::treeland_personalization_font_context_v1_monospace_font(const QString &font_name) { m_interface->m_monoFontName = font_name.toUtf8(); emit m_interface->m_platformTheme->monoFontNameChanged(font_name.toUtf8()); } void PersonalizationFontContext::treeland_personalization_font_context_v1_font_size(uint32_t font_size) { // treeland侧无法存储浮点数,约定 font_size 为 10 å€�çš„ pointSize qreal pointSize = font_size / 10.0; pointSize = qBound(8.25, pointSize, 15.00); m_interface->m_fontPointSize = pointSize; emit m_interface->m_platformTheme->fontPointSizeChanged(pointSize); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/treeland/personalizationwaylandclientextension.h000066400000000000000000000067331522615413000311150ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef PERSONALIZATIONWAYLANDCLIENTEXTENSION_H #define PERSONALIZATIONWAYLANDCLIENTEXTENSION_H #include "dtreelandplatforminterface.h" #include "qwayland-treeland-personalization-manager-v1.h" #include #include #include #include DGUI_BEGIN_NAMESPACE class PersonalizationAppearanceContext; class PersonalizationCursorContext; class PersonalizationFontContext; class DTreelandPlatformInterfacePrivate; class PersonalizationManager: public QWaylandClientExtensionTemplate, public QtWayland::treeland_personalization_manager_v1 { Q_OBJECT public: static PersonalizationManager *instance(); [[nodiscard]]inline bool isSupported() const { return m_isSupported; } private: void addListener(); void removeListener(); explicit PersonalizationManager(); static void handleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version); private: QtWaylandClient::QWaylandDisplay *m_waylandDisplay; bool m_isSupported; }; class PersonalizationWindowContext : public QWaylandClientExtensionTemplate, public QtWayland::treeland_personalization_window_context_v1 { Q_OBJECT public: explicit PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context); ~PersonalizationWindowContext() override; }; class PersonalizationAppearanceContext : public QWaylandClientExtensionTemplate, public QtWayland::treeland_personalization_appearance_context_v1 { Q_OBJECT public: explicit PersonalizationAppearanceContext(struct ::treeland_personalization_appearance_context_v1 *context, DTreelandPlatformInterface *interface); ~PersonalizationAppearanceContext() override; protected: void treeland_personalization_appearance_context_v1_round_corner_radius(int32_t radius) override; void treeland_personalization_appearance_context_v1_icon_theme(const QString &theme_name) override; void treeland_personalization_appearance_context_v1_active_color(const QString &active_color) override; void treeland_personalization_appearance_context_v1_window_theme_type(uint32_t type) override; void treeland_personalization_appearance_context_v1_window_opacity(uint32_t opacity) override; private: DTreelandPlatformInterface *m_interface; }; class PersonalizationFontContext : public QWaylandClientExtensionTemplate, public QtWayland::treeland_personalization_font_context_v1 { Q_OBJECT public: explicit PersonalizationFontContext(struct ::treeland_personalization_font_context_v1 *context, DTreelandPlatformInterface *interface); ~PersonalizationFontContext() override; protected: void treeland_personalization_font_context_v1_font(const QString &font_name) override; void treeland_personalization_font_context_v1_monospace_font(const QString &font_name) override; void treeland_personalization_font_context_v1_font_size(uint32_t font_size) override; private: DTreelandPlatformInterface *m_interface; }; DGUI_END_NAMESPACE #endif // PERSONALIZATIONWAYLANDCLIENTEXTENSION_H dtkgui-6.7.46/src/plugins/platform/treeland/treeland.cmake000066400000000000000000000003001522615413000235670ustar00rootroot00000000000000file(GLOB TREELAND_HEADER ${CMAKE_CURRENT_LIST_DIR}/*.h ) file(GLOB TREELAND_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(treeland_SRC ${TREELAND_HEADER} ${TREELAND_SOURCE} ) dtkgui-6.7.46/src/plugins/platform/xcb/000077500000000000000000000000001522615413000177545ustar00rootroot00000000000000dtkgui-6.7.46/src/plugins/platform/xcb/dxcbplatforminterface.cpp000066400000000000000000000402001522615413000250220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dxcbplatforminterface.h" #include "dxcbplatforminterface_p.h" #include #include #include #include #include #include "dplatformtheme.h" #include "dguiapplicationhelper.h" #include DGUI_BEGIN_NAMESPACE #define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name #define FETCH_PROPERTY(Name, Function) \ D_DC(DXCBPlatformInterface); \ QVariant value = d->theme->getSetting(QByteArrayLiteral(Name)); \ if (d->fallbackProperty && !value.isValid() && d->parent) \ return d->parent->Function(); \ #define FETCH_PROPERTY_WITH_ARGS(Name, Function, Args) \ D_DC(DXCBPlatformInterface); \ QVariant value = d->theme->getSetting(Name); \ if (d->fallbackProperty && !value.isValid() && d->parent) \ return d->parent->Function(Args); \ DXCBPlatformInterfacePrivate::DXCBPlatformInterfacePrivate(DXCBPlatformInterface *qq) :DCORE_NAMESPACE::DObjectPrivate(qq) { } void DXCBPlatformInterfacePrivate::_q_onThemePropertyChanged(const QByteArray &name, const QVariant &value) { D_Q(DXCBPlatformInterface); // 转å�‘属性å�˜åŒ–的信å�·ï¼Œæ­¤ä¿¡å�·æ�¥æº�å�¯èƒ½ä¸ºparent theme或“é�žè°ƒè‰²æ�¿â€�的属性å�˜åŒ–。 // 使用队列的形å¼�转å�‘,é�¿å…�多次å�‘出å�Œæ ·çš„ä¿¡å�· // q->staticMetaObject.invokeMethod(q, "propertyChanged", Qt::QueuedConnection, // Q_ARG(const QByteArray&, name), Q_ARG(const QVariant&, value)); if (QByteArrayLiteral("Gtk/FontName") == name) { Q_EMIT q->m_platformTheme->gtkFontNameChanged(value.toByteArray()); return; } if (name.startsWith("Qt/DPI/")) { const QString &screen_name = QString::fromLocal8Bit(name.mid(7)); if (!screen_name.isEmpty()) { bool ok = false; int dpi = value.toInt(&ok); Q_EMIT q->m_platformTheme->dotsPerInchChanged(screen_name, ok ? dpi : -1); } return; } if (QByteArrayLiteral("Xft/DPI") == name) { bool ok = false; int dpi = value.toInt(&ok); Q_EMIT q->m_platformTheme->dotsPerInchChanged(QString(), ok ? dpi : -1); } const QByteArrayList &list = name.split('/'); if (list.count() != 2) return; QByteArray pn = list.last(); if (pn.isEmpty()) return; // 转æ�¢é¦–å­—æ¯�为å°�写 pn[0] = QChar(pn.at(0)).toLower().toLatin1(); // 直接使用é�™æ€�çš„meta object,防止通过metaObject函数调用到dynamic metaobject const QMetaObject *mo = &DPlatformTheme::staticMetaObject; int index = mo->indexOfProperty(pn.constData()); if (index < 0) return; const QMetaProperty &p = mo->property(index); bool is_parent_signal = q->sender() != theme; // 当自己的属性有效时应该忽略父主题的属性å�˜åŒ–ä¿¡å�·ï¼Œä¼˜å…ˆä»¥è‡ªèº«çš„属性值为准。 if (is_parent_signal && p.read(q).isValid()) { return; } if (p.hasNotifySignal()) { // invoke会å�šQ_ASSERT(mobj->cast(object))判断, DPlatformThemeçš„dynamic metaObject为 // qt5platform-pluginæ�’ä»¶çš„DNativeSettings. 导致崩溃. // invokeOnGadget与invoke代ç �逻辑一致, å�ªæ˜¯å°‘了异步支æŒ�. // return; if (!p.notifySignal().invokeOnGadget(q->m_platformTheme, QGenericArgument(value.typeName(), value.constData()))) qWarning() << "_q_onThemePropertyChanged() error when notify signal" << p.notifySignal().name(); } } DXCBPlatformInterface::DXCBPlatformInterface(quint32 window, DPlatformTheme *platformTheme) : DPlatformInterface(platformTheme) , Core::DObject(*new DXCBPlatformInterfacePrivate(this)) { D_D(DXCBPlatformInterface); d->theme = new DNativeSettings(window, QByteArray(), platformTheme); connect(d->theme, SIGNAL(propertyChanged(const QByteArray &, const QVariant &)), this, SLOT(_q_onThemePropertyChanged(const QByteArray &, const QVariant &))); } int DXCBPlatformInterface::cursorBlinkTime() const { FETCH_PROPERTY("Net/CursorBlinkTime", cursorBlinkTime) return value.toInt(); } int DXCBPlatformInterface::cursorBlinkTimeout() const { FETCH_PROPERTY("Net/CursorBlinkTimeout", cursorBlinkTimeout) return value.toInt(); } bool DXCBPlatformInterface::cursorBlink() const { FETCH_PROPERTY("Net/CursorBlink", cursorBlink) return value.toInt(); } int DXCBPlatformInterface::doubleClickDistance() const { FETCH_PROPERTY("Net/DoubleClickDistance", doubleClickDistance) return value.toInt(); } int DXCBPlatformInterface::doubleClickTime() const { FETCH_PROPERTY("Net/DoubleClickTime", doubleClickTime) return value.toInt(); } int DXCBPlatformInterface::dndDragThreshold() const { FETCH_PROPERTY("Net/DndDragThreshold", dndDragThreshold) return value.toInt(); } int DXCBPlatformInterface::windowRadius() const { return windowRadius(-1); } int DXCBPlatformInterface::windowRadius(int defaultValue) const { Q_D(const DXCBPlatformInterface); QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/WindowRadius")); bool ok = false; if (d->fallbackProperty && !value.isValid() && d->parent) return d->parent->windowRadius(defaultValue); int radius = value.toInt(&ok); return ok ? radius : defaultValue; } QByteArray DXCBPlatformInterface::themeName() const { FETCH_PROPERTY("Net/ThemeName", themeName) return value.toByteArray(); } QByteArray DXCBPlatformInterface::iconThemeName() const { FETCH_PROPERTY("Net/IconThemeName", iconThemeName) return value.toByteArray(); } QByteArray DXCBPlatformInterface::soundThemeName() const { FETCH_PROPERTY("Net/SoundThemeName", soundThemeName) return value.toByteArray(); } QByteArray DXCBPlatformInterface::fontName() const { FETCH_PROPERTY("Qt/FontName", fontName) return value.toByteArray(); } QByteArray DXCBPlatformInterface::monoFontName() const { FETCH_PROPERTY("Qt/MonoFontName", monoFontName) return value.toByteArray(); } qreal DXCBPlatformInterface::fontPointSize() const { FETCH_PROPERTY("Qt/FontPointSize", fontPointSize) return value.toDouble(); } QByteArray DXCBPlatformInterface::gtkFontName() const { FETCH_PROPERTY("Gtk/FontName", gtkFontName) return value.toByteArray(); } QColor DXCBPlatformInterface::activeColor() const { FETCH_PROPERTY("Qt/ActiveColor", activeColor) return qvariant_cast(value); } QColor DXCBPlatformInterface::darkActiveColor() const { FETCH_PROPERTY("Qt/DarkActiveColor", darkActiveColor) return qvariant_cast(value); } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) #define GET_COLOR(Role) qvariant_cast(getSetting(QByteArrayLiteral(#Role))) static QColor getSetting(const QByteArray &key) { Q_UNUSED(key); qWarning() << "Not implemented, key:" << key; return {}; } QColor DXCBPlatformInterface::window() const { return GET_COLOR(window); } QColor DXCBPlatformInterface::windowText() const { return GET_COLOR(windowText); } QColor DXCBPlatformInterface::base() const { return GET_COLOR(base); } QColor DXCBPlatformInterface::alternateBase() const { return GET_COLOR(alternateBase); } QColor DXCBPlatformInterface::toolTipBase() const { return GET_COLOR(toolTipBase); } QColor DXCBPlatformInterface::toolTipText() const { return GET_COLOR(toolTipText); } QColor DXCBPlatformInterface::text() const { return GET_COLOR(text); } QColor DXCBPlatformInterface::button() const { return GET_COLOR(button); } QColor DXCBPlatformInterface::buttonText() const { return GET_COLOR(buttonText); } QColor DXCBPlatformInterface::brightText() const { return GET_COLOR(brightText); } QColor DXCBPlatformInterface::light() const { return GET_COLOR(light); } QColor DXCBPlatformInterface::midlight() const { return GET_COLOR(midlight); } QColor DXCBPlatformInterface::dark() const { return GET_COLOR(dark); } QColor DXCBPlatformInterface::mid() const { return GET_COLOR(mid); } QColor DXCBPlatformInterface::shadow() const { return GET_COLOR(shadow); } QColor DXCBPlatformInterface::highlight() const { return GET_COLOR(highlight); } QColor DXCBPlatformInterface::highlightedText() const { return GET_COLOR(highlightedText); } QColor DXCBPlatformInterface::link() const { return GET_COLOR(link); } QColor DXCBPlatformInterface::linkVisited() const { return GET_COLOR(linkVisited); } QColor DXCBPlatformInterface::itemBackground() const { return GET_COLOR(itemBackground); } QColor DXCBPlatformInterface::textTitle() const { return GET_COLOR(textTitle); } QColor DXCBPlatformInterface::textTips() const { return GET_COLOR(textTips); } QColor DXCBPlatformInterface::textWarning() const { return GET_COLOR(textWarning); } QColor DXCBPlatformInterface::textLively() const { return GET_COLOR(textLively); } QColor DXCBPlatformInterface::lightLively() const { return GET_COLOR(lightLively); } QColor DXCBPlatformInterface::darkLively() const { return GET_COLOR(darkLively); } QColor DXCBPlatformInterface::frameBorder() const { return GET_COLOR(frameBorder); } #endif int DXCBPlatformInterface::dotsPerInch(const QString &screenName) const { bool ok = false; if (!screenName.isEmpty()) { FETCH_PROPERTY_WITH_ARGS("Qt/DPI/" + screenName.toLocal8Bit(), dotsPerInch, screenName); int dpi = value.toInt(&ok); if (ok) return dpi; } FETCH_PROPERTY_WITH_ARGS("Xft/DPI", dotsPerInch, screenName); int dpi = value.toInt(&ok); return ok ? dpi : -1; } /*! \property DXCBPlatformInterface::sizeMode \brief This property holds the sizeMode of the system's SizeMode. */ int DXCBPlatformInterface::sizeMode() const { D_DC(DXCBPlatformInterface); QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/SizeMode")); return value.toInt(); } /*! \property DXCBPlatformInterface::scrollBarPolicy \brief This property holds the scrollBarPolicy of the system. same as Qt::ScrollBarPolicy \retval 0 show as needed auto hide, default \retval 1 always off \retval 2 always on */ int DXCBPlatformInterface::scrollBarPolicy() const { FETCH_PROPERTY("Qt/ScrollBarPolicy", scrollBarPolicy) return qvariant_cast(value); } void DXCBPlatformInterface::setCursorBlinkTime(int cursorBlinkTime) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/CursorBlinkTime", cursorBlinkTime); } void DXCBPlatformInterface::setCursorBlinkTimeout(int cursorBlinkTimeout) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/CursorBlinkTimeout", cursorBlinkTimeout); } void DXCBPlatformInterface::setCursorBlink(bool cursorBlink) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/CursorBlink", cursorBlink); } void DXCBPlatformInterface::setDoubleClickDistance(int doubleClickDistance) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/DoubleClickDistance", doubleClickDistance); } void DXCBPlatformInterface::setDoubleClickTime(int doubleClickTime) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/DoubleClickTime", doubleClickTime); } void DXCBPlatformInterface::setDndDragThreshold(int dndDragThreshold) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/DndDragThreshold", dndDragThreshold); } void DXCBPlatformInterface::setThemeName(const QByteArray &themeName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/ThemeName", themeName); } void DXCBPlatformInterface::setIconThemeName(const QByteArray &iconThemeName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/IconThemeName", iconThemeName); } void DXCBPlatformInterface::setSoundThemeName(const QByteArray &soundThemeName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Net/SoundThemeName", soundThemeName); } void DXCBPlatformInterface::setFontName(const QByteArray &fontName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Qt/FontName", fontName); } void DXCBPlatformInterface::setMonoFontName(const QByteArray &monoFontName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Qt/MonoFontName", monoFontName); } void DXCBPlatformInterface::setFontPointSize(qreal fontPointSize) { D_D(DXCBPlatformInterface); d->theme->setSetting("Qt/FontPointSize", fontPointSize); } void DXCBPlatformInterface::setGtkFontName(const QByteArray &fontName) { D_D(DXCBPlatformInterface); d->theme->setSetting("Gtk/FontName", fontName); } void DXCBPlatformInterface::setActiveColor(const QColor activeColor) { D_D(DXCBPlatformInterface); d->theme->setSetting("Qt/ActiveColor", activeColor); } void DXCBPlatformInterface::setDarkActiveColor(const QColor &activeColor) { D_D(DXCBPlatformInterface); d->theme->setSetting("Qt/DarkActiveColor", activeColor); } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) #define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role) static void setSetting(const QByteArray &key, const QColor &color) { Q_UNUSED(key); Q_UNUSED(color); qWarning() << "Not implemented, key: " << key << "value: " << color; } void DXCBPlatformInterface::setWindow(const QColor &window) { SET_COLOR(window); } void DXCBPlatformInterface::setWindowText(const QColor &windowText) { SET_COLOR(windowText); } void DXCBPlatformInterface::setBase(const QColor &base) { SET_COLOR(base); } void DXCBPlatformInterface::setAlternateBase(const QColor &alternateBase) { SET_COLOR(alternateBase); } void DXCBPlatformInterface::setToolTipBase(const QColor &toolTipBase) { SET_COLOR(toolTipBase); } void DXCBPlatformInterface::setToolTipText(const QColor &toolTipText) { SET_COLOR(toolTipText); } void DXCBPlatformInterface::setText(const QColor &text) { SET_COLOR(text); } void DXCBPlatformInterface::setButton(const QColor &button) { SET_COLOR(button); } void DXCBPlatformInterface::setButtonText(const QColor &buttonText) { SET_COLOR(buttonText); } void DXCBPlatformInterface::setBrightText(const QColor &brightText) { SET_COLOR(brightText); } void DXCBPlatformInterface::setLight(const QColor &light) { SET_COLOR(light); } void DXCBPlatformInterface::setMidlight(const QColor &midlight) { SET_COLOR(midlight); } void DXCBPlatformInterface::setDark(const QColor &dark) { SET_COLOR(dark); } void DXCBPlatformInterface::setMid(const QColor &mid) { SET_COLOR(mid); } void DXCBPlatformInterface::setShadow(const QColor &shadow) { SET_COLOR(shadow); } void DXCBPlatformInterface::setHighlight(const QColor &highlight) { SET_COLOR(highlight); } void DXCBPlatformInterface::setHighlightedText(const QColor &highlightText) { SET_COLOR(highlightText); } void DXCBPlatformInterface::setLink(const QColor &link) { SET_COLOR(link); } void DXCBPlatformInterface::setLinkVisited(const QColor &linkVisited) { SET_COLOR(linkVisited); } void DXCBPlatformInterface::setItemBackground(const QColor &itemBackground) { SET_COLOR(itemBackground); } void DXCBPlatformInterface::setTextTitle(const QColor &textTitle) { SET_COLOR(textTitle); } void DXCBPlatformInterface::setTextTips(const QColor &textTips) { SET_COLOR(textTips); } void DXCBPlatformInterface::setTextWarning(const QColor &textWarning) { SET_COLOR(textWarning); } void DXCBPlatformInterface::setTextLively(const QColor &textLively) { SET_COLOR(textLively); } void DXCBPlatformInterface::setLightLively(const QColor &lightLively) { SET_COLOR(lightLively); } void DXCBPlatformInterface::setDarkLively(const QColor &darkLively) { SET_COLOR(darkLively); } void DXCBPlatformInterface::setFrameBorder(const QColor &frameBorder) { SET_COLOR(frameBorder); } #endif void DXCBPlatformInterface::setDotsPerInch(const QString &screenName, int dpi) { D_D(DXCBPlatformInterface); if (screenName.isEmpty()) { d->theme->setSetting("Xft/DPI", dpi); } else { d->theme->setSetting("Qt/DPI/" + screenName.toLocal8Bit(), dpi); } } void DXCBPlatformInterface::setWindowRadius(int windowRadius) { D_D(DXCBPlatformInterface); d->theme->setSetting("DTK/WindowRadius", windowRadius); } DGUI_END_NAMESPACE #include "moc_dxcbplatforminterface.cpp" dtkgui-6.7.46/src/plugins/platform/xcb/dxcbplatforminterface.h000066400000000000000000000124621522615413000245000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DXCBPLATFORMINTERFACE_H #define DXCBPLATFORMINTERFACE_H #include "private/dplatforminterface_p.h" #include DGUI_BEGIN_NAMESPACE class DXCBPlatformInterfacePrivate; class DXCBPlatformInterface : public QObject, public DPlatformInterface, public DCORE_NAMESPACE::DObject { Q_OBJECT D_DECLARE_PRIVATE(DXCBPlatformInterface) public: explicit DXCBPlatformInterface(quint32 window, DPlatformTheme *platformTheme); int cursorBlinkTime() const override; int cursorBlinkTimeout() const override; bool cursorBlink() const override; int doubleClickDistance() const override; int doubleClickTime() const override; int dndDragThreshold() const override; int windowRadius() const override; int windowRadius(int defaultValue) const override; QByteArray themeName() const override; QByteArray iconThemeName() const override; QByteArray soundThemeName() const override; QByteArray fontName() const override; QByteArray monoFontName() const override; qreal fontPointSize() const override; QByteArray gtkFontName() const override; QColor activeColor() const override; QColor darkActiveColor() const override; #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) QColor window() const override; QColor windowText() const override; QColor base() const override; QColor alternateBase() const override; QColor toolTipText() const override; QColor toolTipBase() const override; QColor text() const override; QColor button() const override; QColor buttonText() const override; QColor brightText() const override; QColor light() const override; QColor midlight() const override; QColor dark() const override; QColor mid() const override; QColor shadow() const override; QColor highlight() const override; QColor highlightedText() const override; QColor link() const override; QColor linkVisited() const override; QColor itemBackground() const override; QColor textTitle() const override; QColor textTips() const override; QColor textWarning() const override; QColor textLively() const override; QColor lightLively() const override; QColor darkLively() const override; QColor frameBorder() const override; #endif int sizeMode() const override; int scrollBarPolicy() const override; public Q_SLOTS: void setCursorBlinkTime(int cursorBlinkTime) override; void setCursorBlinkTimeout(int cursorBlinkTimeout) override; void setCursorBlink(bool cursorBlink) override; void setDoubleClickDistance(int doubleClickDistance) override; void setDoubleClickTime(int doubleClickTime) override; void setDndDragThreshold(int dndDragThreshold) override; void setThemeName(const QByteArray &themeName) override; void setIconThemeName(const QByteArray &iconThemeName) override; void setSoundThemeName(const QByteArray &soundThemeName) override; void setFontName(const QByteArray &fontName) override; void setMonoFontName(const QByteArray &monoFontName) override; void setFontPointSize(qreal fontPointSize) override; void setGtkFontName(const QByteArray &fontName) override; void setActiveColor(const QColor activeColor) override; void setDarkActiveColor(const QColor &activeColor) override; #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) void setWindow(const QColor &window) override; void setWindowText(const QColor &windowText) override; void setBase(const QColor &base) override; void setAlternateBase(const QColor &alternateBase) override; void setToolTipBase(const QColor &toolTipBase) override; void setToolTipText(const QColor &toolTipText) override; void setText(const QColor &text) override; void setButton(const QColor &button) override; void setButtonText(const QColor &buttonText) override; void setBrightText(const QColor &brightText) override; void setLight(const QColor &light) override; void setMidlight(const QColor &midlight) override; void setDark(const QColor &dark) override; void setMid(const QColor &mid) override; void setShadow(const QColor &shadow) override; void setHighlight(const QColor &highlight) override; void setHighlightedText(const QColor &highlightedText) override; void setLink(const QColor &link) override; void setLinkVisited(const QColor &linkVisited) override; void setItemBackground(const QColor &itemBackground) override; void setTextTitle(const QColor &textTitle) override; void setTextTips(const QColor &textTips) override; void setTextWarning(const QColor &textWarning) override; void setTextLively(const QColor &textLively) override; void setLightLively(const QColor &lightLively) override; void setDarkLively(const QColor &darkLively) override; void setFrameBorder(const QColor &frameBorder) override; #endif int dotsPerInch(const QString &screenName = QString()) const override; void setDotsPerInch(const QString &screenName, int dpi) override; void setWindowRadius(int windowRadius) override; private: friend class DPlatformThemePrivate; D_PRIVATE_SLOT(void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value)) }; DGUI_END_NAMESPACE #endif // DXCBPLATFORMINTERFACE_H dtkgui-6.7.46/src/plugins/platform/xcb/dxcbplatforminterface_p.h000066400000000000000000000015351522615413000250160ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DXCBPLATFORMINTERFACE_P_H #define DXCBPLATFORMINTERFACE_P_H #include "dxcbplatforminterface.h" #include "private/dplatforminterface_p.h" #include #include DGUI_BEGIN_NAMESPACE class DNativeSettings; class DPlatformTheme; class DXCBPlatformInterfacePrivate : public DCORE_NAMESPACE::DObjectPrivate { public: D_DECLARE_PUBLIC(DXCBPlatformInterface) DXCBPlatformInterfacePrivate(DXCBPlatformInterface *qq); void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value); public: DPlatformTheme *parent = nullptr; bool fallbackProperty = true; DNativeSettings *theme; QHash m_properties; }; DGUI_END_NAMESPACE #endif // DNATIVESETTINGS_P_H dtkgui-6.7.46/src/plugins/platform/xcb/dxcbplatformwindowinterface.cpp000066400000000000000000000544461522615413000262730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dxcbplatformwindowinterface.h" #include "dguiapplicationhelper.h" #include "dplatformtheme.h" #include "dwindowmanagerhelper.h" #include #include #include #include DGUI_BEGIN_NAMESPACE #define DXCB_PLUGIN_KEY "dxcb" #define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb" #define DEFINE_CONST_CHAR(Name) [[maybe_unused]] const char _##Name[] = "_d_" #Name DEFINE_CONST_CHAR(useDxcb); DEFINE_CONST_CHAR(redirectContent); DEFINE_CONST_CHAR(netWmStates); DEFINE_CONST_CHAR(windowRadius); DEFINE_CONST_CHAR(borderWidth); DEFINE_CONST_CHAR(borderColor); DEFINE_CONST_CHAR(windowEffect); DEFINE_CONST_CHAR(windowStartUpEffect); DEFINE_CONST_CHAR(shadowRadius); DEFINE_CONST_CHAR(shadowOffset); DEFINE_CONST_CHAR(shadowColor); DEFINE_CONST_CHAR(clipPath); DEFINE_CONST_CHAR(frameMask); DEFINE_CONST_CHAR(frameMargins); DEFINE_CONST_CHAR(translucentBackground); DEFINE_CONST_CHAR(enableSystemResize); DEFINE_CONST_CHAR(enableSystemMove); DEFINE_CONST_CHAR(enableBlurWindow); DEFINE_CONST_CHAR(windowBlurAreas); DEFINE_CONST_CHAR(windowBlurPaths); DEFINE_CONST_CHAR(windowWallpaperParas); DEFINE_CONST_CHAR(autoInputMaskByClipPath); DEFINE_CONST_CHAR(resolve_mask); enum PropRole { WindowRadius, // TO BE CONTINUE }; // functions DEFINE_CONST_CHAR(setWmBlurWindowBackgroundArea); DEFINE_CONST_CHAR(setWmBlurWindowBackgroundPathList); DEFINE_CONST_CHAR(setWmBlurWindowBackgroundMaskImage); DEFINE_CONST_CHAR(setWmWallpaperParameter); DEFINE_CONST_CHAR(setWindowProperty); DEFINE_CONST_CHAR(pluginVersion); DEFINE_CONST_CHAR(disableOverrideCursor); DEFINE_CONST_CHAR(enableDxcb); DEFINE_CONST_CHAR(isEnableDxcb); DEFINE_CONST_CHAR(setEnableNoTitlebar); DEFINE_CONST_CHAR(isEnableNoTitlebar); DEFINE_CONST_CHAR(clientLeader); static void resolve(QObject *obj, PropRole role) { int mask = obj->property(_resolve_mask).toInt(); obj->setProperty(_resolve_mask, (mask |= 1 << role)); } static bool resolved(QObject *obj, PropRole role) { int mask = obj->property(_resolve_mask).toInt(); return mask & (1 << role); } static void setWindowProperty(QWindow *window, const char *name, const QVariant &value) { if (!window) return; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) static QFunctionPointer setWindowProperty = qApp->platformFunction(_setWindowProperty); #else constexpr QFunctionPointer setWindowProperty = nullptr; #endif if (!setWindowProperty) { window->setProperty(name, value); return; } reinterpret_cast(setWindowProperty)(window, name, value); } DXCBPlatformWindowInterface::DXCBPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent) : QObject(parent) , DPlatformWindowInterface(window, platformHandle) { if (window) { window->installEventFilter(this); } } DXCBPlatformWindowInterface::~DXCBPlatformWindowInterface() { } QString DXCBPlatformWindowInterface::pluginVersion() { QFunctionPointer pv = 0; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) pv = qApp->platformFunction(_pluginVersion); #endif if (Q_UNLIKELY(!pv)) return QString(); return reinterpret_cast(pv)(); } bool DXCBPlatformWindowInterface::isDXcbPlatform() { if (!qApp) return false; static bool _is_dxcb = qApp->platformName() == DXCB_PLUGIN_KEY || qApp->property(DXCB_PLUGIN_SYMBOLIC_PROPERTY).toBool(); return _is_dxcb; } bool DXCBPlatformWindowInterface::connectWindowManagerChangedSignal(QObject *object, std::function slot) { if (object) { return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, object, slot); } return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, slot); } bool DXCBPlatformWindowInterface::connectHasBlurWindowChanged(QObject *object, std::function slot) { if (object) { return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, object, slot); } return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, slot); } WId DXCBPlatformWindowInterface::windowLeader() { QFunctionPointer clientLeader = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) clientLeader = qApp->platformFunction(_clientLeader); #endif if (!clientLeader) { return 0; } return reinterpret_cast(clientLeader)(); } void DXCBPlatformWindowInterface::setEnabled(bool enabled) { // 优先使用窗å�£ç®¡ç�†å™¨ä¸­å®žçŽ°çš„no titlebar接å�£å®žçŽ°è‡ªå®šä¹‰çª—å�£ä¿®é¥°å™¨çš„æ•ˆæžœ if (setEnabledNoTitlebar(enabled)) { return; } if (!isDXcbPlatform()) return; QFunctionPointer enable_dxcb = nullptr; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) enable_dxcb = qApp->platformFunction(_enableDxcb); #endif if (enable_dxcb) { (*reinterpret_cast(enable_dxcb))(m_window); } else if (m_window->handle()) { Q_ASSERT_X(m_window->property(_useDxcb).toBool(), "DXCBPlatformWindowInterfacer:", "Must be called before window handle has been created. See also QWindow::handle()"); } else { m_window->setProperty(_useDxcb, enabled); } } void DXCBPlatformWindowInterface::enableDXcb(bool redirectContent) { m_window->setProperty(_redirectContent, redirectContent); setEnabled(true); } bool DXCBPlatformWindowInterface::isEnabled() const { if (isEnabledNoTitlebar()) return true; QFunctionPointer is_enable_dxcb = nullptr; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) is_enable_dxcb = qApp->platformFunction(_isEnableDxcb); #endif if (is_enable_dxcb) { return (*reinterpret_cast(is_enable_dxcb))(m_window); } return m_window->property(_useDxcb).toBool(); } bool DXCBPlatformWindowInterface::eventFilter(QObject *obj, QEvent *event) { if (obj == m_window && m_platformHandle) { if (event->type() == QEvent::DynamicPropertyChange) { QDynamicPropertyChangeEvent *e = static_cast(event); if (e->propertyName() == _windowRadius) { Q_EMIT m_platformHandle->windowRadiusChanged(); } else if (e->propertyName() == _borderWidth) { Q_EMIT m_platformHandle->borderWidthChanged(); } else if (e->propertyName() == _borderColor) { Q_EMIT m_platformHandle->borderColorChanged(); } else if (e->propertyName() == _shadowRadius) { Q_EMIT m_platformHandle->shadowRadiusChanged(); } else if (e->propertyName() == _shadowOffset) { Q_EMIT m_platformHandle->shadowOffsetChanged(); } else if (e->propertyName() == _shadowColor) { Q_EMIT m_platformHandle->shadowColorChanged(); } else if (e->propertyName() == _clipPath) { Q_EMIT m_platformHandle->clipPathChanged(); } else if (e->propertyName() == _frameMask) { Q_EMIT m_platformHandle->frameMaskChanged(); } else if (e->propertyName() == _frameMargins) { Q_EMIT m_platformHandle->frameMarginsChanged(); } else if (e->propertyName() == _translucentBackground) { Q_EMIT m_platformHandle->translucentBackgroundChanged(); } else if (e->propertyName() == _enableSystemResize) { Q_EMIT m_platformHandle->enableSystemResizeChanged(); } else if (e->propertyName() == _enableSystemMove) { Q_EMIT m_platformHandle->enableSystemMoveChanged(); } else if (e->propertyName() == _enableBlurWindow) { Q_EMIT m_platformHandle->enableBlurWindowChanged(); } else if (e->propertyName() == _autoInputMaskByClipPath) { Q_EMIT m_platformHandle->autoInputMaskByClipPathChanged(); } } } return QObject::eventFilter(obj, event); } static void initWindowRadius(QWindow *window) { if (window->property(_windowRadius).isValid()) return; auto theme = DGuiApplicationHelper::instance()->systemTheme(); int radius = theme->windowRadius(12); //###(zccrs): 暂时在此处给窗å�£é»˜è®¤è®¾ç½®ä¸º12px的圆角 setWindowProperty(window, _windowRadius, radius); // Qt::UniqueConnection will report a warning // to `unique connections require a pointer to member function of a QObject subclass`. const char *uniqueueConnectionFlag("_d_uniqueueConnectionFlag"); bool connected = window->property(uniqueueConnectionFlag).toBool(); if (!connected) { window->setProperty(uniqueueConnectionFlag, true); window->connect(theme, &DPlatformTheme::windowRadiusChanged, window, [window] (int radius) { if (!resolved(window, PropRole::WindowRadius)) setWindowProperty(window, _windowRadius, radius); }); } } class Q_DECL_HIDDEN CreatorWindowEventFilter : public QObject { public: CreatorWindowEventFilter(QObject *par= nullptr): QObject(par){} public: bool eventFilter(QObject *watched, QEvent *event) override { if (event->type() == QEvent::PlatformSurface) { QPlatformSurfaceEvent *se = static_cast(event); if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信å�·ï¼Œ 则 WinID 已被创建 auto window = qobject_cast(watched); initWindowRadius(window); } } return QObject::eventFilter(watched, event); } }; bool DXCBPlatformWindowInterface::isEnabledNoTitlebar() const { QFunctionPointer is_enable_no_titlebar = nullptr; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) is_enable_no_titlebar = qApp->platformFunction(_isEnableNoTitlebar); #endif if (is_enable_no_titlebar) { return (*reinterpret_cast(is_enable_no_titlebar))(m_window); } return false; } bool DXCBPlatformWindowInterface::setEnabledNoTitlebar(bool enable) { if (isEnabledNoTitlebar() == enable) return true; QFunctionPointer enable_no_titlear = nullptr; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) enable_no_titlear = qApp->platformFunction(_setEnableNoTitlebar); #endif if (enable_no_titlear) { bool ok = (*reinterpret_cast(enable_no_titlear))(m_window, enable); if (ok && enable) { if (m_window->handle()) { initWindowRadius(m_window); } else { m_window->installEventFilter(new CreatorWindowEventFilter(m_window)); } } return ok; } return false; } inline DPlatformHandle::WMBlurArea operator *(const DPlatformHandle::WMBlurArea &area, qreal scale) { if (qFuzzyCompare(scale, 1.0)) return area; DPlatformHandle::WMBlurArea new_area; new_area.x = qRound64(area.x * scale); new_area.y = qRound64(area.y * scale); new_area.width = qRound64(area.width * scale); new_area.height = qRound64(area.height * scale); new_area.xRadius = qRound64(area.xRadius * scale); new_area.yRaduis = qRound64(area.yRaduis * scale); return new_area; } /*! \brief DXCBPlatformWindowInterface::setWindowBlurAreaByWM 设置窗å�£èƒŒæ™¯çš„æ¨¡ç³ŠåŒºåŸŸï¼Œç¤ºä¾‹ï¼š \code QWindow w; QVector area_list; DXCBPlatformWindowInterface::WMBlurArea area; area.x = 50; area.y = 50; area.width = 200; area.height = 200; area.xRadius = 10; area.yRaduis = 10; area_list.append(area); DXCBPlatformWindowInterface::setWindowBlurAreaByWM(&w, area_list); QSurfaceFormat format = w.format(); format.setAlphaBufferSize(8); w.setFormat(format); w.resize(300, 300); w.show(); \endcode \image blur_window_demo1.png \a window 目标窗å�£å¯¹è±¡ \a area 模糊区域,此区域范围内的窗å�£èƒŒæ™¯å°†å¡«å……为窗å�£å�Žé�¢å†…容模糊之å�Žçš„图åƒ� \return 如果设置æˆ�功则返回 true,å�¦åˆ™è¿”回 false \note 对于需è¦�显示模糊背景的窗å�£ï¼Œéœ€è¦�将其 QSurfaceFormat çš„ alpha 通é�“设置为8 \note 调用此接å�£è®¾ç½®çª—å�£èƒŒæ™¯æ¨¡ç³ŠåŒºåŸŸå�Žå°†è¦†ç›–之å‰�所设置的区域,包括调用 setWindowBlurAreaByWM(QWindow *, const QList &) 所设置的区域 \note 建议使用 DBlurEffectWidget 实现窗å�£èƒŒæ™¯æ¨¡ç³Šæ•ˆæžœ \note 此功能ä¾�赖于窗å�£ç®¡ç�†å™¨çš„实现,目å‰�仅支æŒ� deepin-wm å’Œ kwin 这两个窗å�£ç®¡ç�†å™¨ \sa Dtk::Widget::DBlurEffectWidget \sa QSurfaceFormat::setAlphaBufferSize \sa QWindow::setFormat \sa DWindowManagerHelper::hasBlurWindow \sa DXCBPlatformWindowInterface::setWindowBlurAreaByWM(QWindow *, const QList &) */ bool DXCBPlatformWindowInterface::setWindowBlurArea(const QVector &area) { if (!m_window) { return false; } if (isEnabled()) { QVector areas; for (auto item : area) areas << item.x << item.y << item.width << item.height << item.xRadius << item.yRaduis; setWindowProperty(m_window, _windowBlurAreas, QVariant::fromValue(areas)); return true; } QFunctionPointer setWmBlurWindowBackgroundArea = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) setWmBlurWindowBackgroundArea = qApp->platformFunction(_setWmBlurWindowBackgroundArea); #endif if (!setWmBlurWindowBackgroundArea) { qWarning("setWindowBlurAreaByWM is not support"); return false; } QSurfaceFormat format = m_window->format(); format.setAlphaBufferSize(8); m_window->setFormat(format); const qreal device_ratio = m_window->devicePixelRatio(); if (qFuzzyCompare(device_ratio, 1.0)) { return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(m_window->winId(), area); } QVector new_areas; new_areas.reserve(area.size()); for (const DPlatformHandle::WMBlurArea &a : area) { new_areas.append(a * device_ratio); } return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(m_window->winId(), new_areas); } inline QPainterPath operator *(const QPainterPath &path, qreal scale) { if (qFuzzyCompare(1.0, scale)) return path; QPainterPath new_path = path; for (int i = 0; i < path.elementCount(); ++i) { const QPainterPath::Element &e = path.elementAt(i); new_path.setElementPositionAt(i, qRound(e.x * scale), qRound(e.y * scale)); } return new_path; } bool DXCBPlatformWindowInterface::setWindowBlurArea(const QList &paths) { if (!m_window) { return false; } if (isEnabled()) { setWindowProperty(m_window, _windowBlurPaths, QVariant::fromValue(paths)); return true; } QFunctionPointer setWmBlurWindowBackgroundPathList = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) setWmBlurWindowBackgroundPathList = qApp->platformFunction(_setWmBlurWindowBackgroundPathList); #endif if (!setWmBlurWindowBackgroundPathList) { qWarning("setWindowBlurAreaByWM is not support"); return false; } QSurfaceFormat format = m_window->format(); format.setAlphaBufferSize(8); m_window->setFormat(format); const qreal device_ratio = m_window->devicePixelRatio(); if (qFuzzyCompare(device_ratio, 1.0)) { return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(m_window->winId(), paths); } QList new_paths; new_paths.reserve(paths.size()); for (const QPainterPath &p : paths) { new_paths.append(p * device_ratio); } return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(m_window->winId(), new_paths); } bool DXCBPlatformWindowInterface::setWindowWallpaperPara(const QRect &area, DPlatformHandle::WallpaperScaleMode sMode, DPlatformHandle::WallpaperFillMode fMode) { if (!m_window) { return false; } QFunctionPointer setWmWallpaperParameter = Q_NULLPTR; #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) setWmWallpaperParameter = qApp->platformFunction(_setWmWallpaperParameter); #endif if (!setWmWallpaperParameter) { qWarning("setWindowWallpaperParaByWM is not support"); return false; } QSurfaceFormat format = m_window->format(); format.setAlphaBufferSize(8); m_window->setFormat(format); quint32 bMode = sMode | fMode; // 激活 backing store m_window->setProperty("_d_dxcb_wallpaper", QVariant::fromValue(QPair(area, bMode))); if (!m_window->handle()) { return true; } else { qWarning() << "because the window handle has been created, so 2D mode will have no effect"; } const qreal device_ratio = m_window->devicePixelRatio(); if (qFuzzyCompare(device_ratio, 1.0) || !area.isValid()) { return reinterpret_cast(setWmWallpaperParameter)(m_window->winId(), area, bMode); } QRect new_area(area.x() * device_ratio, area.y() * device_ratio, area.width() * device_ratio, area.height() * device_ratio); return reinterpret_cast(setWmWallpaperParameter)(m_window->winId(), new_area, bMode); } void DXCBPlatformWindowInterface::setDisableWindowOverrideCursor(bool disable) { m_window->setProperty(_disableOverrideCursor, disable); } int DXCBPlatformWindowInterface::windowRadius() const { return m_window->property(_windowRadius).toInt(); } void DXCBPlatformWindowInterface::setWindowRadius(int windowRadius) { setWindowProperty(m_window, _windowRadius, windowRadius); resolve(m_window, PropRole::WindowRadius); } int DXCBPlatformWindowInterface::borderWidth() const { return m_window->property(_borderWidth).toInt(); } void DXCBPlatformWindowInterface::setBorderWidth(int borderWidth) { setWindowProperty(m_window, _borderWidth, borderWidth); } QColor DXCBPlatformWindowInterface::borderColor() const { return qvariant_cast(m_window->property(_borderColor)); } void DXCBPlatformWindowInterface::setBorderColor(const QColor &borderColor) { setWindowProperty(m_window, _borderColor, QVariant::fromValue(borderColor)); } int DXCBPlatformWindowInterface::shadowRadius() const { return m_window->property(_shadowRadius).toInt(); } void DXCBPlatformWindowInterface::setShadowRadius(int shadowRadius) { setWindowProperty(m_window, _shadowRadius, shadowRadius); } QPoint DXCBPlatformWindowInterface::shadowOffset() const { return m_window->property(_shadowOffset).toPoint(); } void DXCBPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset) { setWindowProperty(m_window, _shadowOffset, shadowOffset); } QColor DXCBPlatformWindowInterface::shadowColor() const { return qvariant_cast(m_window->property(_shadowColor)); } void DXCBPlatformWindowInterface::setShadowColor(const QColor &shadowColor) { setWindowProperty(m_window, _shadowColor, QVariant::fromValue(shadowColor)); } DPlatformHandle::EffectScene DXCBPlatformWindowInterface::windowEffect() { return qvariant_cast(m_window->property(_windowEffect)); } void DXCBPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { setWindowProperty(m_window, _windowEffect, static_cast(effectScene)); } DPlatformHandle::EffectType DXCBPlatformWindowInterface::windowStartUpEffect() { return qvariant_cast(m_window->property(_windowStartUpEffect)); } void DXCBPlatformWindowInterface::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) { setWindowProperty(m_window, _windowStartUpEffect, static_cast(effectType)); } QPainterPath DXCBPlatformWindowInterface::clipPath() const { return qvariant_cast(m_window->property(_clipPath)); } void DXCBPlatformWindowInterface::setClipPath(const QPainterPath &clipPath) { setWindowProperty(m_window, _clipPath, QVariant::fromValue(clipPath)); } QRegion DXCBPlatformWindowInterface::frameMask() const { return qvariant_cast(m_window->property(_frameMask)); } void DXCBPlatformWindowInterface::setFrameMask(const QRegion &frameMask) { setWindowProperty(m_window, _frameMask, QVariant::fromValue(frameMask)); } QMargins DXCBPlatformWindowInterface::frameMargins() const { return qvariant_cast(m_window->property(_frameMargins)); } bool DXCBPlatformWindowInterface::translucentBackground() const { return m_window->property(_translucentBackground).toBool(); } void DXCBPlatformWindowInterface::setTranslucentBackground(bool translucentBackground) { setWindowProperty(m_window, _translucentBackground, translucentBackground); } bool DXCBPlatformWindowInterface::enableSystemResize() const { return m_window->property(_enableSystemResize).toBool(); } void DXCBPlatformWindowInterface::setEnableSystemResize(bool enableSystemResize) { setWindowProperty(m_window, _enableSystemResize, enableSystemResize); } bool DXCBPlatformWindowInterface::enableSystemMove() const { return m_window->property(_enableSystemMove).toBool(); } void DXCBPlatformWindowInterface::setEnableSystemMove(bool enableSystemMove) { setWindowProperty(m_window, _enableSystemMove, enableSystemMove); } bool DXCBPlatformWindowInterface::enableBlurWindow() const { return m_window->property(_enableBlurWindow).toBool(); } void DXCBPlatformWindowInterface::setEnableBlurWindow(bool enableBlurWindow) { setWindowProperty(m_window, _enableBlurWindow, enableBlurWindow); } bool DXCBPlatformWindowInterface::autoInputMaskByClipPath() const { return m_window->property(_autoInputMaskByClipPath).toBool(); } void DXCBPlatformWindowInterface::setAutoInputMaskByClipPath(bool autoInputMaskByClipPath) { setWindowProperty(m_window, _autoInputMaskByClipPath, autoInputMaskByClipPath); } WId DXCBPlatformWindowInterface::realWindowId() const { return qvariant_cast(m_window->property("_d_real_content_window")); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/plugins/platform/xcb/dxcbplatformwindowinterface.h000066400000000000000000000063001522615413000257220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DXCBPLATFORMWINDOWINTERFACE_H #define DXCBPLATFORMWINDOWINTERFACE_H #include "private/dplatformwindowinterface_p.h" #include DGUI_BEGIN_NAMESPACE class DXCBPlatformWindowInterface : public QObject, public DPlatformWindowInterface { Q_OBJECT public: DXCBPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr); ~DXCBPlatformWindowInterface() override; static QString pluginVersion(); static bool isDXcbPlatform(); static bool connectWindowManagerChangedSignal(QObject *object, std::function slot); static bool connectHasBlurWindowChanged(QObject *object, std::function slot); static WId windowLeader(); void enableDXcb(bool redirectContent); bool setWindowBlurArea(const QVector &area); bool setWindowBlurArea(const QList &paths); bool setWindowWallpaperPara(const QRect &area, DPlatformHandle::WallpaperScaleMode sMode, DPlatformHandle::WallpaperFillMode fMode); bool autoInputMaskByClipPath() const; void setAutoInputMaskByClipPath(bool autoInputMaskByClipPath); WId realWindowId() const; void setEnabled(bool enabled) override; bool isEnabled() const override; void setDisableWindowOverrideCursor(bool disable) override; bool isEnabledNoTitlebar() const override; bool setEnabledNoTitlebar(bool enable) override; int windowRadius() const override; void setWindowRadius(int windowRadius) override; int borderWidth() const override; void setBorderWidth(int borderWidth) override; QColor borderColor() const override; void setBorderColor(const QColor &borderColor) override; int shadowRadius() const override; void setShadowRadius(int shadowRadius) override; QPoint shadowOffset() const override; void setShadowOffset(const QPoint &shadowOffset) override; QColor shadowColor() const override; void setShadowColor(const QColor &shadowColor) override; DPlatformHandle::EffectScene windowEffect() override; void setWindowEffect(DPlatformHandle::EffectScenes effectScene) override; DPlatformHandle::EffectType windowStartUpEffect() override; void setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) override; QPainterPath clipPath() const override; void setClipPath(const QPainterPath &clipPath) override; QRegion frameMask() const override; void setFrameMask(const QRegion &frameMask) override; QMargins frameMargins() const override; bool translucentBackground() const override; void setTranslucentBackground(bool translucentBackground) override; bool enableSystemResize() const override; void setEnableSystemResize(bool enableSystemResize) override; bool enableSystemMove() const override; void setEnableSystemMove(bool enableSystemMove) override; bool enableBlurWindow() const override; void setEnableBlurWindow(bool enableBlurWindow) override; protected: bool eventFilter(QObject *watched, QEvent *event) override; }; DGUI_END_NAMESPACE #endif // DXCBPLATFORMWINDOWINTERFACE_H dtkgui-6.7.46/src/plugins/platform/xcb/xcb.cmake000066400000000000000000000002471522615413000215350ustar00rootroot00000000000000file(GLOB XCB_HEADER ${CMAKE_CURRENT_LIST_DIR}/*.h ) file(GLOB XCB_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(xcb_SRC ${XCB_HEADER} ${XCB_SOURCE} ) dtkgui-6.7.46/src/plugins/plugins.cmake000066400000000000000000000050121522615413000200350ustar00rootroot00000000000000option(DTK_DISABLE_XCB "Disable XCB Protocols" OFF) option(DTK_DISABLE_TREELAND "Disable Treeland Protocols" OFF) file(GLOB PLATFORM_INTERFACE_HEADER ${CMAKE_CURRENT_LIST_DIR}/*.h ) file(GLOB PLATFORM_INTERFACE_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(platform_interface_SRC ${PLATFORM_INTERFACE_HEADER} ${PLATFORM_INTERFACE_SOURCE} ) target_sources(${LIB_NAME} PRIVATE ${platform_interface_SRC} ) set(PRIVATE_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/private/dplatforminterface_p.h) set(PRIVATE_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${DTK_VERSION_MAJOR}/DGui/Private") # XCB if(NOT DTK_DISABLE_XCB) message("Support XCB!") include(plugins/platform/xcb/xcb.cmake) target_sources(${LIB_NAME} PRIVATE ${xcb_SRC} ) else() target_compile_definitions(${LIB_NAME} PRIVATE DTK_DISABLE_XCB) endif() # Treeland try_compile(DEEPIN_WAYLAND_TEST_COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR}/treeland_test ${CMAKE_CURRENT_LIST_DIR}/platform/config.tests/treeland_test treeland_test CMAKE_FLAGS -DQT_VERSION_MAJOR=${QT_VERSION_MAJOR}) if(NOT DEEPIN_WAYLAND_TEST_COMPILE_RESULT) message("wayland_test failed, disable treeland support") set(DTK_DISABLE_TREELAND ON) endif() if(NOT DTK_DISABLE_TREELAND) find_package(TreelandProtocols) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS WaylandClient) set(TreelandProtocols_FOUND ${TreelandProtocols_FOUND}) endif() if(NOT DTK_DISABLE_TREELAND AND TreelandProtocols_FOUND) message("Support Treeland!") if("${QT_VERSION_MAJOR}" STREQUAL "6") qt6_generate_wayland_protocol_client_sources(${LIB_NAME} FILES ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml ) else() # ECM setup include(FeatureSummary) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}") find_package(QtWaylandScanner) ecm_add_qtwayland_client_protocol(CLIENT_LIB_SRCS PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml BASENAME treeland-personalization-manager-v1 ) target_sources(${LIB_NAME} PRIVATE ${CLIENT_LIB_SRCS} ) endif() include(plugins/platform/treeland/treeland.cmake) target_sources(${LIB_NAME} PRIVATE ${treeland_SRC} ) else() target_compile_definitions(${LIB_NAME} PRIVATE DTK_DISABLE_TREELAND) endif() install(FILES ${PRIVATE_HEADER_FILES} DESTINATION "${PRIVATE_INCLUDE_INSTALL_DIR}") dtkgui-6.7.46/src/private/000077500000000000000000000000001522615413000153455ustar00rootroot00000000000000dtkgui-6.7.46/src/private/dfiledragcommon_p.h000066400000000000000000000006731522615413000211750ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DDNDCOMMON_H #define DDNDCOMMON_H #define DND_INTERFACE "com.deepin.dtk.FileDrag" #define DND_OBJPATH "/Ddnd" #define DND_MIME_SERVICE "x-dtk-file-drag/service" #define DND_MIME_PID "x-dtk-file-drag/pid" #define DND_MIME_UUID "x-dtk-file-drag/uuid" #define DND_TARGET_URL_KEY "targetUrl" #endif // DDNDCOMMON_H dtkgui-6.7.46/src/private/dfiledragserver_p.h000066400000000000000000000015401522615413000212050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFILEDRAGSERVER_P_H #define DFILEDRAGSERVER_P_H #include "dfiledragserver.h" #include #include #include DGUI_BEGIN_NAMESPACE class DDndSourceInterface; class DFileDragServer; class DFileDragServerPrivate : public DCORE_NAMESPACE::DObjectPrivate { QMap data; QUuid uuid; DFileDragServerPrivate(DFileDragServer *q); ~DFileDragServerPrivate(); void writeMimeData(QMimeData *dest); static DDndSourceInterface *dbusif; static int refcnt; static QHash servermap; D_DECLARE_PUBLIC(DFileDragServer) friend class DDndSourceInterface; friend class DFileDrag; }; DGUI_END_NAMESPACE #endif // DFILEDRAGSERVER_P_H dtkgui-6.7.46/src/private/dfontmanager_p.h000066400000000000000000000013121522615413000204770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DFONTSIZEMANAGER_P_H #define DFONTSIZEMANAGER_P_H #include #include #include "dfontmanager.h" DGUI_BEGIN_NAMESPACE class DFontManagerPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate { public: DFontManagerPrivate(DFontManager *qq); int fontPixelSize[DFontManager::NSizeTypes] = {40, 30, 24, 20, 16, 14, 13, 12, 11, 10, 8}; int baseFontSizeType = DFontManager::T6; // å­—å�·çš„差值 int fontPixelSizeDiff = 0; QFont baseFont; private: D_DECLARE_PUBLIC(DFontManager) }; DGUI_END_NAMESPACE #endif // DFONTSIZEMANAGER_P_H dtkgui-6.7.46/src/private/dguiapplicationhelper_p.h000066400000000000000000000037421522615413000224170ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DGUIAPPLICATIONHELPER_P_H #define DGUIAPPLICATIONHELPER_P_H #include "dguiapplicationhelper.h" #include "dplatformtheme.h" #include QT_BEGIN_NAMESPACE class QLocalServer; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE /*! @private */ class DGuiApplicationHelperPrivate : public DCORE_NAMESPACE::DObjectPrivate { public: D_DECLARE_PUBLIC(DGuiApplicationHelper) DGuiApplicationHelperPrivate(DGuiApplicationHelper *qq); void init(); void initApplication(QGuiApplication *app); static void staticInitApplication(); static void staticCleanApplication(); DPlatformTheme *initWindow(QWindow *window) const; void _q_initApplicationTheme(bool notifyChange = false); void _q_sizeModeChanged(int mode); DGuiApplicationHelper::SizeMode fetchSizeMode(bool *isSystemSizeMode = nullptr) const; void notifyAppThemeChanged(); void notifyAppThemeChangedByEvent(); void onApplicationPaletteChanged(); // 返回程åº�是å�¦è‡ªå®šä¹‰äº†è°ƒè‰²æ�¿ inline bool isCustomPalette() const; void setPaletteType(DGuiApplicationHelper::ColorType ct, bool emitSignal); void initPaletteType() const; bool paletteTypeInited = false; DGuiApplicationHelper::ColorType paletteType = DGuiApplicationHelper::UnknownType; // 系统级别的主题设置 DPlatformTheme *systemTheme = nullptr; QScopedPointer appPalette; // 获å�–QLocalSever消æ�¯çš„等待时间 static int waitTime; static DGuiApplicationHelper::Attributes attributes; DGuiApplicationHelper::SizeMode systemSizeMode = DGuiApplicationHelper::NormalMode; DGuiApplicationHelper::SizeMode explicitSizeMode; private: // 应用程åº�级别的主题设置 DPlatformTheme *appTheme = nullptr; }; Q_DECLARE_OPERATORS_FOR_FLAGS(DGuiApplicationHelper::Attributes) DGUI_END_NAMESPACE #endif // DGUIAPPLICATIONHELPER_P_H dtkgui-6.7.46/src/private/dnativesettings_p.h000066400000000000000000000012721522615413000212520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DNATIVESETTINGS_P_H #define DNATIVESETTINGS_P_H #include #include #include DGUI_BEGIN_NAMESPACE class DNativeSettingsPrivate : public DCORE_NAMESPACE::DObjectPrivate { D_DECLARE_PUBLIC(DNativeSettings) public: DNativeSettingsPrivate(DNativeSettings *qq, const QByteArray &domain); ~DNativeSettingsPrivate(); bool init(const QMetaObject *mo, quint32 window); public: QByteArray domain; bool valid = false; QByteArrayList allKeys; }; DGUI_END_NAMESPACE #endif // DNATIVESETTINGS_P_H dtkgui-6.7.46/src/private/dplatforminterface_p.h000066400000000000000000000122731522615413000217130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMINTERFACE_H #define DPLATFORMINTERFACE_H #include #include #include "dtkgui_global.h" DGUI_BEGIN_NAMESPACE class DPlatformTheme; class LIBDTKCORESHARED_EXPORT DPlatformInterface { public: explicit DPlatformInterface(DPlatformTheme *platformTheme); virtual ~DPlatformInterface(); virtual int cursorBlinkTime() const; virtual int cursorBlinkTimeout() const; virtual bool cursorBlink() const; virtual int doubleClickDistance() const; virtual int doubleClickTime() const; virtual int dndDragThreshold() const; virtual int windowRadius() const; virtual int windowRadius(int defaultValue) const; virtual QByteArray themeName() const; virtual QByteArray iconThemeName() const; virtual QByteArray soundThemeName() const; virtual QByteArray fontName() const; virtual QByteArray monoFontName() const; virtual qreal fontPointSize() const; virtual QByteArray gtkFontName() const; virtual QColor activeColor() const; virtual QColor darkActiveColor() const; #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) virtual QColor window() const; virtual QColor windowText() const; virtual QColor base() const; virtual QColor alternateBase() const; virtual QColor toolTipBase() const; virtual QColor toolTipText() const; virtual QColor text() const; virtual QColor button() const; virtual QColor buttonText() const; virtual QColor brightText() const; virtual QColor light() const; virtual QColor midlight() const; virtual QColor dark() const; virtual QColor mid() const; virtual QColor shadow() const; virtual QColor highlight() const; virtual QColor highlightedText() const; virtual QColor link() const; virtual QColor linkVisited() const; virtual QColor itemBackground() const; virtual QColor textTitle() const; virtual QColor textTips() const; virtual QColor textWarning() const; virtual QColor textLively() const; virtual QColor lightLively() const; virtual QColor darkLively() const; virtual QColor frameBorder() const; #endif virtual int sizeMode() const; virtual int scrollBarPolicy() const; public: virtual void setCursorBlinkTime(int cursorBlinkTime); virtual void setCursorBlinkTimeout(int cursorBlinkTimeout); virtual void setCursorBlink(bool cursorBlink); virtual void setDoubleClickDistance(int doubleClickDistance); virtual void setDoubleClickTime(int doubleClickTime); virtual void setDndDragThreshold(int dndDragThreshold); virtual void setThemeName(const QByteArray &themeName); virtual void setIconThemeName(const QByteArray &iconThemeName); virtual void setSoundThemeName(const QByteArray &soundThemeName); virtual void setFontName(const QByteArray &fontName); virtual void setMonoFontName(const QByteArray &monoFontName); virtual void setFontPointSize(qreal fontPointSize); virtual void setGtkFontName(const QByteArray &fontName); virtual void setActiveColor(const QColor activeColor); virtual void setDarkActiveColor(const QColor &activeColor); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) virtual void setWindow(const QColor &window); virtual void setWindowText(const QColor &windowText); virtual void setBase(const QColor &base); virtual void setAlternateBase(const QColor &alternateBase); virtual void setToolTipBase(const QColor &toolTipBase); virtual void setToolTipText(const QColor &toolTipText); virtual void setText(const QColor &text); virtual void setButton(const QColor &button); virtual void setButtonText(const QColor &buttonText); virtual void setBrightText(const QColor &brightText); virtual void setLight(const QColor &light); virtual void setMidlight(const QColor &midlight); virtual void setDark(const QColor &dark); virtual void setMid(const QColor &mid); virtual void setShadow(const QColor &shadow); virtual void setHighlight(const QColor &highlight); virtual void setHighlightedText(const QColor &highlightedText); virtual void setLink(const QColor &link); virtual void setLinkVisited(const QColor &linkVisited); virtual void setItemBackground(const QColor &itemBackground); virtual void setTextTitle(const QColor &textTitle); virtual void setTextTips(const QColor &textTips); virtual void setTextWarning(const QColor &textWarning); virtual void setTextLively(const QColor &textLively); virtual void setLightLively(const QColor &lightLively); virtual void setDarkLively(const QColor &darkLively); virtual void setFrameBorder(const QColor &frameBorder); #endif virtual int dotsPerInch(const QString &screenName = QString()) const; virtual void setDotsPerInch(const QString &screenName, int dpi); virtual void setWindowRadius(int windowRadius); protected: DPlatformTheme *m_platformTheme; }; class LIBDTKCORESHARED_EXPORT DPlatformInterfaceFactory { public: using HelperCreator = DPlatformInterface * (*)(DPlatformTheme*); static void registerInterface(HelperCreator creator); }; DGUI_END_NAMESPACE #endif // DNATIVESETTINGS_P_H dtkgui-6.7.46/src/private/dplatformtheme_p.h000066400000000000000000000033431522615413000210530ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMTHEME_P_H #define DPLATFORMTHEME_P_H #include "private/dplatforminterface_p.h" #include "dplatformtheme.h" #include "dnativesettings_p.h" #include class OrgDeepinDTKPreference; DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE class DPlatformThemePrivate : public DNativeSettingsPrivate { public: D_DECLARE_PUBLIC(DPlatformTheme) DPlatformThemePrivate(DPlatformTheme *qq); // 接收parent主题或é�žè°ƒè‰²æ�¿DNativeSettings对象(theme对象)的属性å�˜åŒ–通知 // 调色æ�¿ç›¸å…³çš„属性å�˜åŒ–与此无关 void onQtColorChanged(QPalette::ColorRole role, const QColor &color); void onDtkColorChanged(DPalette::ColorType type, const QColor &color); void notifyPaletteChanged(); // 父主题,å�¯ä»¥ä»Žå…¶ç»§æ‰¿é™¤è°ƒè‰²æ�¿ä¹‹å¤–的所有窗å�£è®¾ç½® DPlatformTheme *parent = nullptr; // 用于控制是å�¦fallback到父主题中获å�–属性 bool fallbackProperty = true; // 默认时,DPlatformTheme会从/deepin/palette域下获å�–调色æ�¿ç›¸å…³çš„属性值 // 此处的DNativeSettings用于获å�–除调色æ�¿ä¹‹å¤–的属性设置 DNativeSettings *theme; // 缓存的调色æ�¿æ•°æ�® DPalette *palette = nullptr; // å‡�少调色æ�¿changedä¿¡å�·çš„通知频率 QTimer *notifyPaletteChangeTimer = nullptr; OrgDeepinDTKPreference *dtkPreferenceConfig = nullptr; DPlatformInterface *platformInterface = nullptr; DGuiApplicationHelper::SizeMode sizeMode = DGuiApplicationHelper::NormalMode; Qt::ScrollBarPolicy scrollBarPolicy = Qt::ScrollBarAsNeeded; }; DGUI_END_NAMESPACE #endif // DPLATFORMTHEME_P_H dtkgui-6.7.46/src/private/dplatformwindowinterface_p.h000066400000000000000000000051471522615413000231450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMWINDOWINTERFACE_P_H #define DPLATFORMWINDOWINTERFACE_P_H #include #include #include "dplatformhandle.h" DGUI_BEGIN_NAMESPACE class LIBDTKCORESHARED_EXPORT DPlatformWindowInterface { public: explicit DPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle); virtual ~DPlatformWindowInterface(); QWindow* window() const; virtual void setEnabled(bool enabled); virtual bool isEnabled() const; virtual bool isEnabledNoTitlebar() const; virtual bool setEnabledNoTitlebar(bool enable); virtual void setDisableWindowOverrideCursor(bool disable); virtual int windowRadius() const; virtual void setWindowRadius(int windowRadius); virtual int borderWidth() const; virtual void setBorderWidth(int borderWidth); virtual QColor borderColor() const; virtual void setBorderColor(const QColor &borderColor); virtual int shadowRadius() const; virtual void setShadowRadius(int shadowRadius); virtual QPoint shadowOffset() const; virtual void setShadowOffset(const QPoint &shadowOffset); virtual QColor shadowColor() const; virtual void setShadowColor(const QColor &shadowColor); virtual DPlatformHandle::EffectScene windowEffect(); virtual void setWindowEffect(DPlatformHandle::EffectScenes effectScene); virtual DPlatformHandle::EffectType windowStartUpEffect(); virtual void setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType); virtual QPainterPath clipPath() const; virtual void setClipPath(const QPainterPath &clipPath); virtual QRegion frameMask() const; virtual void setFrameMask(const QRegion &frameMask); virtual QMargins frameMargins() const; virtual bool translucentBackground() const; virtual void setTranslucentBackground(bool translucentBackground); virtual bool enableSystemResize() const; virtual void setEnableSystemResize(bool enableSystemResize); virtual bool enableSystemMove() const; virtual void setEnableSystemMove(bool enableSystemMove); virtual bool enableBlurWindow() const; virtual void setEnableBlurWindow(bool enableBlurWindow); protected: QPointer m_window; QPointer m_platformHandle; }; class LIBDTKCORESHARED_EXPORT DPlatformWindowInterfaceFactory { public: using Creator = DPlatformWindowInterface * (*)(QWindow *, DPlatformHandle*); static void registerInterface(Creator creator); }; DGUI_END_NAMESPACE #endif // DPLATFORMWINDOWINTERFACE_P_H dtkgui-6.7.46/src/private/dregionmonitor_p.h000066400000000000000000000033321522615413000210750ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DREGIONMONITOR_P_H #define DREGIONMONITOR_P_H #include "dregionmonitor.h" #include "xeventmonitor_interface.h" #include #include #include #include DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE using XEventMonitor = ::com::deepin::api::XEventMonitor; class DRegionMonitorPrivate : public DObjectPrivate { D_DECLARE_PUBLIC(DRegionMonitor) public: DRegionMonitorPrivate(DRegionMonitor *q); ~DRegionMonitorPrivate(); bool registered() const { return !registerKey.isEmpty(); } void init(); void registerMonitorRegion(); void unregisterMonitorRegion(); void _q_ButtonPress(const int flag, const int x, const int y, const QString &key); void _q_ButtonRelease(const int flag, const int x, const int y, const QString &key); void _q_CursorMove(const int x, const int y, const QString &key); void _q_CursorEnter(const int x, const int y, const QString &key); void _q_CursorLeave(const int x, const int y, const QString &key); void _q_KeyPress(const QString &keyname, const int x, const int y, const QString &key); void _q_KeyRelease(const QString &keyname, const int x, const int y, const QString &key); const QPoint deviceScaledCoordinate(const QPoint &p, const double ratio) const; XEventMonitor *eventInter; QRegion watchedRegion; QString registerKey; DRegionMonitor::CoordinateType type = DRegionMonitor::ScaleRatio; DRegionMonitor::RegisterdFlags registerdFlags = DRegionMonitor::Motion | DRegionMonitor::Button | DRegionMonitor::Key; }; DGUI_END_NAMESPACE #endif // DREGIONMONITOR_P_H dtkgui-6.7.46/src/private/dtaskbarcontrol_p.h000066400000000000000000000012211522615413000212250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTASKBARCONTROL_P_H #define DTASKBARCONTROL_P_H #include #include #include #include "dtaskbarcontrol.h" DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE class DTaskbarControlPrivate : public DObjectPrivate { D_DECLARE_PUBLIC(DTaskbarControl) public: DTaskbarControlPrivate(DTaskbarControl *q); ~DTaskbarControlPrivate(); int m_counter; bool m_counterVisible; double m_progress; bool m_progressVisible; }; DGUI_END_NAMESPACE #endif // DTASKBARCONTROL_P_H dtkgui-6.7.46/src/private/private.cmake000066400000000000000000000010061522615413000200160ustar00rootroot00000000000000set(private_SRC ${CMAKE_CURRENT_LIST_DIR}/dnativesettings_p.h ${CMAKE_CURRENT_LIST_DIR}/dguiapplicationhelper_p.h ${CMAKE_CURRENT_LIST_DIR}/dplatformtheme_p.h ${CMAKE_CURRENT_LIST_DIR}/dfiledragcommon_p.h ${CMAKE_CURRENT_LIST_DIR}/dfiledragserver_p.h ${CMAKE_CURRENT_LIST_DIR}/dregionmonitor_p.h ${CMAKE_CURRENT_LIST_DIR}/dtaskbarcontrol_p.h ${CMAKE_CURRENT_LIST_DIR}/dfontmanager_p.h ${CMAKE_CURRENT_LIST_DIR}/dplatforminterface_p.h ${CMAKE_CURRENT_LIST_DIR}/dplatformwindowinterface_p.h ) dtkgui-6.7.46/src/util/000077500000000000000000000000001522615413000146505ustar00rootroot00000000000000dtkgui-6.7.46/src/util/ddciicon.cpp000066400000000000000000001127071522615413000171400ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "ddciicon.h" #include "dguiapplicationhelper.h" #include "dicontheme.h" #include #include #include #include #include #include #include #include #include #include DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE #define MODE_NORMAL "normal" #define MODE_DISABLED "disabled" #define MODE_HOVER "hover" #define MODE_PRESSED "pressed" #define THEME_LIGHT "light" #define THEME_DARK "dark" #define ALPHA8STRING "alpha8" struct DDciIconEntry { struct ScalableLayer { int imagePixelRatio = 0; struct Layer { int prior = 0; DDciIconPalette::PaletteRole role = DDciIconPalette::NoPalette; QByteArray format; QByteArray data; bool isAlpha8Format = false; qint8 hue = 0; qint8 saturation = 0; qint8 lightness = 0; qint8 red = 0; qint8 green = 0; qint8 blue = 0; qint8 alpha = 0; qint16 padding = 0; }; QVector layers; }; int iconSize = 0; qint16 maxPaddings = 0; DDciIcon::Mode mode = DDciIcon::Normal; DDciIcon::Theme theme = DDciIcon::Light; QVector scalableLayers; inline bool isNull() const { return scalableLayers.isEmpty(); } }; struct EntryNode { int iconSize = 0; qint16 maxPaddings = 0; QVector entries; }; using EntryNodeList = QVector; class EntryPropertyParser { public: static void registerSteps(); static void doParse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties); private: static struct Step { virtual ~Step() {} Step *nextStep = nullptr; virtual QVector parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) = 0; } *root; struct PriorStep : public Step { QVector parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) override; }; struct FormatAndAlpha8Step : public Step { QVector parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) override; }; struct PaddingStep : public Step { QVector parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) override; }; struct PaletteStep : public Step { QVector parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) override; }; }; EntryPropertyParser::Step *EntryPropertyParser::root = nullptr; void EntryPropertyParser::registerSteps() { static PriorStep priorSt; static FormatAndAlpha8Step formatSt; static PaddingStep paddingSt; static PaletteStep paletteSt; priorSt.nextStep = &formatSt; formatSt.nextStep = &paddingSt; paddingSt.nextStep = &paletteSt; paletteSt.nextStep = nullptr; root = &priorSt; } void EntryPropertyParser::doParse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) { Q_ASSERT(layer); if (!root) registerSteps(); EntryPropertyParser::Step *step = root; QVector ps = properties; while (step) { // If the input information flow is empty, it means that the next steps do not need to be continued if (ps.isEmpty()) break; ps = step->parse(layer, ps); step = step->nextStep; } } QVector EntryPropertyParser::PriorStep::parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) { bool ok = false; QVector ps = properties; layer->prior = ps.takeFirst().toString().toInt(&ok); if (!ok) return {}; // error priority. return ps; } QVector EntryPropertyParser::FormatAndAlpha8Step::parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) { QVector ps = properties; const QString alpha8OrFormat = ps.takeLast().toString(); if (alpha8OrFormat.compare(ALPHA8STRING, Qt::CaseInsensitive) == 0) { // Alpha8 format layer->isAlpha8Format = true; layer->format = ps.takeLast().toLatin1(); } else { // normal format layer->format = alpha8OrFormat.toLatin1(); } return ps; } QVector EntryPropertyParser::PaddingStep::parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) { QVector ps = properties; // Take the padding property auto it = std::find_if(ps.cbegin(), ps.cend(), [](const QStringView &p) { return p.endsWith(QLatin1Char('p')); }); if (it != ps.cend()) { layer->padding = it->left(it->length() - 1).toString().toShort(); ps.removeOne(*it); } return ps; } QVector EntryPropertyParser::PaletteStep::parse(DDciIconEntry::ScalableLayer::Layer *layer, const QVector &properties) { QVector ps = properties; QStringView palettes = ps.takeFirst(); // `role_hue_saturation_lightness_red_green_blue_alpha` or `role` if (palettes.toString().contains(QLatin1Char('_'))) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // QVector is an alias for QList in Qt6 const QVector paletteProps = palettes.split(QLatin1Char('_')); #elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 2) // QStringView::split() has been added in 5.12.2. const QVector paletteProps = QVector::fromList(palettes.split(QLatin1Char('_'))); #else QStringList strList = palettes.toString().split(QLatin1Char('_')); QList viewList; for (auto str : strList) { viewList.append(QStringView(str)); } const QVector paletteProps = QVector::fromList(viewList); #endif if (paletteProps.length() != 8) return ps; int role = paletteProps.at(0).toString().toInt(); if (role < DDciIconPalette::NoPalette || role > DDciIconPalette::PaletteCount) role = DDciIconPalette::NoPalette; layer->role = DDciIconPalette::PaletteRole(role); layer->hue = static_cast(paletteProps.at(1).toString().toShort()); layer->saturation = static_cast(paletteProps.at(2).toString().toShort()); layer->lightness = static_cast(paletteProps.at(3).toString().toShort()); layer->red = static_cast(paletteProps.at(4).toString().toShort()); layer->green = static_cast(paletteProps.at(5).toString().toShort()); layer->blue = static_cast(paletteProps.at(6).toString().toShort()); layer->alpha = static_cast(paletteProps.at(7).toString().toShort()); } else { // only palette int role = palettes.toString().toInt(); if (role < DDciIconPalette::NoPalette || role > DDciIconPalette::PaletteCount) role = DDciIconPalette::NoPalette; layer->role = DDciIconPalette::PaletteRole(role); } return ps; } void alpha8ImageDeleter(void *image) { delete static_cast(image); } static QImage readImageData(QImageReader &reader, qreal pixmapScale, bool isAlpha8Format) { QImage image; if (reader.canRead()) { bool scaled = false; int imageSize = qMax(reader.size().width(), reader.size().height()); int scaledSize = qRound(pixmapScale * imageSize); if (!isAlpha8Format && reader.supportsOption(QImageIOHandler::ScaledSize)) { reader.setScaledSize(reader.size().scaled(scaledSize, scaledSize, Qt::KeepAspectRatio)); scaled = true; } QImage *imagePtr = ℑ if (isAlpha8Format) imagePtr = new QImage(); reader.read(imagePtr); if (isAlpha8Format) { QImage tt(imagePtr->bits(), imagePtr->width(), imagePtr->width(), imagePtr->bytesPerLine(), QImage::Format_Alpha8, alpha8ImageDeleter, static_cast(imagePtr)); return tt.scaled(scaledSize, scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } if (!scaled) image = image.scaled(scaledSize, scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { qWarning() << reader.errorString() << reader.format(); } return image; } class DDciIconImagePrivate { public: DDciIconImagePrivate(const DDciIconImagePrivate &other) : imageSize(other.imageSize) , devicePixelRatio(other.devicePixelRatio) , imageScale(other.imageScale) , layers(other.layers) { } DDciIconImagePrivate(qreal imageSize, qreal devicePixelRatio, qreal imageScale, const DDciIconEntry::ScalableLayer &sLayer) : imageSize(imageSize) , devicePixelRatio(devicePixelRatio) , imageScale(imageScale) , layers(sLayer.layers) { } void init(); inline bool loaded() const { return layers.size() == readers.size(); } inline void ensureLoad() { if (loaded()) return; init(); } const qreal imageSize; const qreal devicePixelRatio; const qreal imageScale; const QVector layers; struct ReaderData { ReaderData() {} ~ReaderData() {} ReaderData(const ReaderData &other) : index(other.index) , buffer(nullptr) , reader(nullptr) , pastImageDelay(other.pastImageDelay) , currentImage(other.currentImage) , currentImageIsValid(other.currentImageIsValid) , m_currentImageEndTime(other.m_currentImageEndTime) {} ReaderData(ReaderData &&other) { index = std::move(other.index); buffer.swap(other.buffer); reader.swap(other.reader); pastImageDelay = std::move(other.pastImageDelay); currentImage.swap(other.currentImage); currentImageIsValid = std::move(other.currentImageIsValid); m_currentImageEndTime = std::move(other.m_currentImageEndTime); } qsizetype index = 0; std::unique_ptr buffer; std::unique_ptr reader; int pastImageDelay = 0; QImage currentImage; bool currentImageIsValid = false; int m_currentImageEndTime = 0; inline void initCurrentImage(const DDciIconImagePrivate *d) { if (currentImageIsValid) return; // Ensure can get a valid QImageReader::nextImageDelay(), Because // using QImageReader::nextImageDelay() needs call QImageReader::read() before. currentImage = readImageData(*reader, d->imageScale, d->layers.at(index).isAlpha8Format); currentImageIsValid = true; m_currentImageEndTime = pastImageDelay + reader->nextImageDelay(); } inline bool jumpToNextImage(DDciIconImagePrivate *d) { Q_ASSERT(reader->supportsAnimation()); pastImageDelay += reader->nextImageDelay(); ++d->pastImageCount; if (!reader->canRead()) return false; currentImage = QImage(); currentImageIsValid = false; initCurrentImage(d); return true; } inline int currentImageEndTime() const { Q_ASSERT(currentImageIsValid); return m_currentImageEndTime; } inline bool currentImageIsEnd(const DDciIconImagePrivate *d) const { return d->currentPastImageDelay > 0 && d->currentPastImageDelay >= currentImageEndTime(); } }; QVector readers; bool supportsAnimation = false; int totalMaxImageCount = 0; int maxLoopCount = -2; ReaderData *readAnimationNextData(); ReaderData *animation = nullptr; int currentImageNumber = 0; int pastImageCount = 0; int currentPastImageDelay = 0; }; class DDciIconPrivate : public QSharedData { public: DDciIconPrivate() : dciFile(nullptr) { } DDciIconPrivate(const DDciIconPrivate &other) : QSharedData(other) , dciFile(other.dciFile) { } ~DDciIconPrivate(); DDciIconEntry *loadIcon(const QString &parentDir, const QString &imageDir); void loadIconList(); void ensureLoaded(); DDciIconEntry *tryMatchIcon(int iconSize, DDciIcon::Theme theme, DDciIcon::Mode mode, DDciIcon::IconMatchedFlags flags = DDciIcon::None) const; static void paint(QPainter *painter, const QRectF &rect, Qt::Alignment alignment, const QVector &layers, QVector *layerReaders, const DDciIconPalette &palette, qreal pixmapScale); static void paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, Qt::Alignment alignment, const DDciIconEntry *entry, const DDciIconPalette &palette, qreal pixmapScale); inline static bool hasPalette(const QVector &layers) { return std::any_of(layers.cbegin(), layers.cend(), [](const DDciIconEntry::ScalableLayer::Layer &layer) { return layer.role != DDciIconPalette::NoPalette; }); } bool hasPalette(DDciIconMatchResult result) const; static inline bool entryIsValid(const DDciIconEntry *entry) { return entry && !entry->isNull(); } QSharedPointer dciFile; EntryNodeList icons; }; // In Qt 6, registration of comparators, and QDebug and QDataStream streaming operators is // done automatically. Consequently, \c QMetaType::registerEqualsComparator(), // \c QMetaType::registerComparators(), \c qRegisterMetaTypeStreamOperators() and // \c QMetaType::registerDebugStreamOperator() do no longer exist. Calls to those methods // have to be removed when porting to Qt 6. #if !defined(QT_NO_DATASTREAM) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) __attribute__((constructor)) static void registerMetaType() { qRegisterMetaTypeStreamOperators("DDciIcon"); } #endif static inline bool toMode(const QStringView &name, DDciIcon::Mode *mode) { if (name == QLatin1String(MODE_NORMAL)) { *mode = DDciIcon::Normal; return true; } if (name == QLatin1String(MODE_DISABLED)) { *mode = DDciIcon::Disabled; return true; } if (name == QLatin1String(MODE_HOVER)) { *mode = DDciIcon::Hover; return true; } if (name == QLatin1String(MODE_PRESSED)) { *mode = DDciIcon::Pressed; return true; } return false; } static inline bool toTheme(const QStringView &name, DDciIcon::Theme *theme) { if (name == QLatin1String(THEME_LIGHT)) { *theme = DDciIcon::Light; return true; } if (name == QLatin1String(THEME_DARK)) { *theme = DDciIcon::Dark; return true; } return false; } // DCI 内部目录使用 '/' 作为路径分隔符 static inline QString joinPath(const QString &s1, const QString &s2) { return s1 + QLatin1Char('/') + s2; } static QImage readImageData(const QByteArray &data, const QByteArray &format, qreal pixmapScale, bool isAlpha8Format) { if (data.isEmpty()) return QImage(); QBuffer rawDataBuffer; rawDataBuffer.setData(data); rawDataBuffer.open(QBuffer::ReadOnly); QImageReader reader(&rawDataBuffer); if (!format.isEmpty()) reader.setFormat(format); return readImageData(reader, pixmapScale, isAlpha8Format); } static int findIconsByLowerBoundSize(const EntryNodeList &list, const int size, bool regardPaddingsAsSize) { const auto compFun1 = [] (const EntryNode &n1, const EntryNode &n2) { return n1.iconSize < n2.iconSize; }; const auto compFun2 = [] (const EntryNode &n1, const EntryNode &n2) { return n1.iconSize + n1.maxPaddings < n2.iconSize + n2.maxPaddings; }; EntryNode target; target.iconSize = size; target.maxPaddings = 0; auto neighbor = std::lower_bound(list.cbegin(), list.cend(), target, regardPaddingsAsSize ? compFun2 : compFun1); if (neighbor != list.cend()) return static_cast(neighbor - list.constBegin()); return -1; } static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSizeF &size, const QRectF &rect) { alignment = QGuiApplicationPrivate::visualAlignment(direction, alignment); qreal x = rect.x(); qreal y = rect.y(); qreal w = size.width(); qreal h = size.height(); if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) y += rect.size().height()/2 - h/2; else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) y += rect.size().height() - h; if ((alignment & Qt::AlignRight) == Qt::AlignRight) x += rect.size().width() - w; else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) x += rect.size().width()/2 - w/2; return QRectF(x, y, w, h); } DDciIconPrivate::~DDciIconPrivate() { for (auto icon : icons) qDeleteAll(icon.entries); } // Note that QStringView is a non-owning, read-only view of a QString // so we need to make sure that the original QString object stays alive // for as long as we're using the QStringView. static inline QVector fromQStringList(const QStringList &list) { QVector views; views.reserve(list.size()); std::copy(list.begin(), list.end(), std::back_inserter(views)); return views; } DDciIconEntry *DDciIconPrivate::loadIcon(const QString &parentDir, const QString &imageDir) { // Mode-Theme auto props = imageDir.split(QLatin1Char('.')); const QVector &iconProps = fromQStringList(props); if (iconProps.count() != 2) // Error file name. return nullptr; DDciIcon::Mode mode; DDciIcon::Theme theme; if (!toMode(iconProps[0], &mode)) return nullptr; if (!toTheme(iconProps[1], &theme)) return nullptr; DDciIconEntry *icon = new DDciIconEntry(); icon->mode = mode; icon->theme = theme; const QString &stateDir = joinPath(parentDir, imageDir); for (const QString &scaleString : dciFile->list(stateDir, true)) { bool ok = false; int scale = scaleString.toInt(&ok); // No restrictions on icons with scale ratio greater than 3. if (!ok) continue; DDciIconEntry::ScalableLayer scaleIcon; scaleIcon.imagePixelRatio = scale; const QString &path = joinPath(stateDir, scaleString); for (const QString &layerPath : dciFile->list(path, true)) { props = layerPath.split(QLatin1Char('.')); const QVector &layerProps = fromQStringList(props); DDciIconEntry::ScalableLayer::Layer layer; EntryPropertyParser::doParse(&layer, layerProps); layer.data = dciFile->dataRef(joinPath(path, layerPath)); // The sequence number starts with 1, convert it into index. scaleIcon.layers.insert(layer.prior - 1, layer); icon->maxPaddings = qMax(icon->maxPaddings, layer.padding); } icon->scalableLayers.append(scaleIcon); } return icon; } void DDciIconPrivate::loadIconList() { const QStringList &listOfSize = dciFile->list(QLatin1String("/"), true); for (const QString &dir : listOfSize) { bool ok = false; int size = dir.toInt(&ok); if (!ok) continue; EntryNode node; node.iconSize = size; node.maxPaddings = 0; const QString &dirPath = joinPath(QLatin1String(), dir); for (const QString &imageDir : dciFile->list(dirPath, true)) { auto icon = loadIcon(dirPath, imageDir); if (!icon || icon->isNull()) continue; icon->iconSize = size; node.entries << icon; node.maxPaddings = qMax(node.maxPaddings, icon->maxPaddings); } if (node.entries.isEmpty()) continue; icons << std::move(node); } } void DDciIconPrivate::ensureLoaded() { // TODO: Modified to resemble the addFile function in QIcon. if (!dciFile->isValid()) return; loadIconList(); } DDciIconEntry *DDciIconPrivate::tryMatchIcon(int iconSize, DDciIcon::Theme theme, DDciIcon::Mode mode, DDciIcon::IconMatchedFlags flags) const { if (icons.isEmpty()) return nullptr; auto neighborIndex = findIconsByLowerBoundSize(icons, iconSize, flags & DDciIcon::RegardPaddingsAsSize); if (neighborIndex < 0) { neighborIndex = static_cast(icons.size() - 1); } const auto &listOfSize = icons.at(neighborIndex); QVector iconWeight; iconWeight.resize(listOfSize.entries.size()); for (int i = 0; i < listOfSize.entries.size(); ++i) { qint8 weight = 0; const DDciIconEntry *icon = listOfSize.entries.at(i); if (icon->mode == mode) { weight += 2; } else if (flags.testFlag(DDciIcon::DontFallbackMode) || icon->mode != DDciIcon::Normal) { weight = -1; continue; } if (icon->theme == theme) { weight += 1; } else { weight = -1; continue; } iconWeight[i] = weight; } const auto targetIcon = std::max_element(iconWeight.constBegin(), iconWeight.constEnd()); if (targetIcon != iconWeight.constEnd() && *targetIcon > 0) return listOfSize.entries.at(targetIcon - iconWeight.constBegin()); return nullptr; } static const DDciIconEntry::ScalableLayer &findScalableLayer(const DDciIconEntry *entry, qreal devicePixelRatio) { const DDciIconEntry::ScalableLayer *maxLayer = nullptr; const int imagePixelRatio = qCeil(devicePixelRatio); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) for (const auto &i : std::as_const(entry->scalableLayers)) { #else for (const auto &i : qAsConst(entry->scalableLayers)) { #endif if (!maxLayer || i.imagePixelRatio > maxLayer->imagePixelRatio) maxLayer = &i; if (i.imagePixelRatio > imagePixelRatio) return i; } Q_ASSERT(maxLayer); return *maxLayer; } void DDciIconPrivate::paint(QPainter *painter, const QRectF &rect, Qt::Alignment alignment, const QVector &layers, QVector *layerReaders, const DDciIconPalette &palette, qreal pixmapScale) { const bool useImageReader = layerReaders && !layerReaders->isEmpty(); Q_ASSERT(!useImageReader || layerReaders->size() == layers.size()); for (auto layerIter = layers.begin(); layerIter != layers.end(); ++layerIter) { QImage layer; if (useImageReader) { const qsizetype index = layerIter - layers.begin(); auto &reader = layerReaders->operator [](index); if (reader->currentImageIsValid) { layer = reader->currentImage; } else { layer = readImageData(*reader->reader, pixmapScale, layerIter->isAlpha8Format); reader->currentImage = layer; reader->currentImageIsValid = true; } } else { if (layerIter->data.isEmpty()) continue; layer = readImageData(layerIter->data, layerIter->format, pixmapScale, layerIter->isAlpha8Format); } if (layer.isNull()) continue; QColor fillColor; switch (layerIter->role) { case DDciIconPalette::Foreground: fillColor = palette.foreground(); break; case DDciIconPalette::Background: fillColor = palette.background(); break; case DDciIconPalette::HighlightForeground: fillColor = palette.highlightForeground(); break; case DDciIconPalette::Highlight: fillColor = palette.highlight(); break; default: break; } // ###(Chen Bin) Can't compose image when this image's format is Format_Alpha8. if (layer.format() == QImage::Format_Alpha8) layer = layer.convertToFormat(QImage::Format_ARGB32_Premultiplied); if (fillColor.isValid()) { QPainter render(&layer); fillColor = DGuiApplicationHelper::adjustColor(fillColor, layerIter->hue, layerIter->saturation, layerIter->lightness, layerIter->red, layerIter->green, layerIter->blue, layerIter->alpha); render.setCompositionMode(QPainter::CompositionMode_SourceIn); render.fillRect(layer.rect(), fillColor); } QRectF targetRect =alignedRect(painter->layoutDirection(), alignment, layer.size(), rect); if (rect.width() < targetRect.width()) targetRect = rect; painter->drawImage(targetRect, layer); } } void DDciIconPrivate::paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, Qt::Alignment alignment, const DDciIconEntry *entry, const DDciIconPalette &palette, qreal pixmapScale) { qreal pixelRatio = devicePixelRatio; bool useHighDpiPixmaps = #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) true; #else qApp->testAttribute(Qt::AA_UseHighDpiPixmaps); #endif if (pixelRatio <= 0 && painter->device() && useHighDpiPixmaps) pixelRatio = painter->device()->devicePixelRatio(); if (pixelRatio <= 0) pixelRatio = 1.0; auto scalableLayer = findScalableLayer(entry, devicePixelRatio); paint(painter, rect, alignment, scalableLayer.layers, nullptr, palette, pixelRatio * pixmapScale / scalableLayer.imagePixelRatio); } bool DDciIconPrivate::hasPalette(DDciIconMatchResult result) const { auto entry = static_cast(result); if (!entryIsValid(entry)) return false; if (entry->scalableLayers.isEmpty()) return false; auto scaledLayer = entry->scalableLayers.first(); return hasPalette(scaledLayer.layers); } DDciIcon::DDciIcon() : d(new DDciIconPrivate()) { } DDciIcon::DDciIcon(const DDciFile *dciFile) : DDciIcon() { d->dciFile.reset(dciFile); d->ensureLoaded(); } DDciIcon::DDciIcon(const QString &fileName) : DDciIcon() { d->dciFile.reset(new DDciFile(fileName)); d->ensureLoaded(); } DDciIcon::DDciIcon(const QByteArray &data) : DDciIcon() { d->dciFile.reset(new DDciFile(data)); d->ensureLoaded(); } DDciIcon::DDciIcon(const DDciIcon &other) : d(other.d) { } DDciIcon &DDciIcon::operator=(const DDciIcon &other) noexcept { d = other.d; return *this; } DDciIcon::~DDciIcon() {} DDciIcon::DDciIcon(DDciIcon &&other) noexcept : d(other.d) { other.d = nullptr; } DDciIcon &DDciIcon::operator=(DDciIcon &&other) noexcept { swap(other); return *this; } bool DDciIcon::isNull() const { return d->icons.isEmpty(); } DDciIconMatchResult DDciIcon::matchIcon(int size, Theme theme, Mode mode, IconMatchedFlags flags) const { return d->tryMatchIcon(size, theme, mode, flags); } int DDciIcon::actualSize(DDciIconMatchResult result) const { auto entry = static_cast(result); if (!d->entryIsValid(entry)) return -1; return entry->iconSize; } int DDciIcon::actualSize(int size, DDciIcon::Theme theme, DDciIcon::Mode mode) const { auto entry = d->tryMatchIcon(size, theme, mode); return actualSize(entry); } QList DDciIcon::availableSizes(DDciIcon::Theme theme, DDciIcon::Mode mode) const { if (d->icons.isEmpty()) return {}; QList sizes; std::for_each(d->icons.begin(), d->icons.end(), [theme, mode, &sizes](const EntryNode &node) { auto it = std::find_if(node.entries.begin(), node.entries.end(), [theme, mode](const DDciIconEntry *entry) { if (entry->mode == mode && entry->theme == theme) return true; return false; }); if (it != node.entries.end()) sizes.append((*it)->iconSize); }); return sizes; } bool DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr) const { switch (attr) { case HasPalette: return d->hasPalette(result); default: break; } return false; } bool DDciIcon::isSupportedAttribute(const DDciIconImage &image, IconAttribute attr) { if (image.isNull()) return false; switch (attr) { case HasPalette: return DDciIconPrivate::hasPalette(image.d->layers); default: break; } return false; } QPixmap DDciIcon::pixmap(qreal devicePixelRatio, int iconSize, DDciIcon::Theme theme, DDciIcon::Mode mode, const DDciIconPalette &palette) const { auto entry = d->tryMatchIcon(iconSize, theme, mode); return pixmap(devicePixelRatio, iconSize, entry, palette); } QPixmap DDciIcon::pixmap(qreal devicePixelRatio, int iconSize, DDciIconMatchResult result, const DDciIconPalette &palette) const { auto image = this->image(result, iconSize, devicePixelRatio); if (image.isNull()) return QPixmap(); return QPixmap::fromImage(image.toImage(palette)); } void DDciIcon::paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, DDciIcon::Theme theme, DDciIcon::Mode mode, Qt::Alignment alignment, const DDciIconPalette &palette) const { int canvarsSize = qMax(rect.width(), rect.height()); auto entry = d->tryMatchIcon(canvarsSize, theme, mode, RegardPaddingsAsSize); return paint(painter, rect, devicePixelRatio, entry, alignment, palette); } void DDciIcon::paint(QPainter *painter, const QRect &rect, qreal devicePixelRatio, DDciIconMatchResult result, Qt::Alignment alignment, const DDciIconPalette &palette) const { auto entry = static_cast(result); if (!d->entryIsValid(entry)) return; qreal canvarsSize = qMax(rect.width(), rect.height()); const qreal pixmapScale = canvarsSize / (entry->iconSize + entry->maxPaddings * 2); d->paint(painter, rect, devicePixelRatio, alignment, entry, palette, pixmapScale); } DDciIconImage DDciIcon::image(DDciIconMatchResult result, int size, qreal devicePixelRatio) const { auto entry = static_cast(result); if (!d->entryIsValid(entry)) return DDciIconImage(); auto scalableLayer = findScalableLayer(entry, devicePixelRatio); int iconSize = size; if (iconSize <= 0) iconSize = entry->iconSize; Q_ASSERT_X((iconSize > 0), "DDciIcon::generatePixmap", "You must specify the icon size."); const qreal pixmapScale = qreal(iconSize) / entry->iconSize; const qreal imageSize = (entry->maxPaddings * 2 + entry->iconSize) * pixmapScale; const qreal imageScale = pixmapScale * devicePixelRatio / scalableLayer.imagePixelRatio; auto image = QSharedPointer(new DDciIconImagePrivate(imageSize, devicePixelRatio, imageScale, scalableLayer)); return DDciIconImage(image); } DDciIcon DDciIcon::fromTheme(const QString &name) { if (QDir::isAbsolutePath(name)) return DDciIcon(name); DDciIcon icon; QString iconName = name; // FIX uengine appname is empty, will cause qt_assert if (!QCoreApplication::applicationName().isEmpty() && !DSGApplication::id().isEmpty()) { // allow the icon theme to override the icon for a given application iconName.prepend(DSGApplication::id() + "/"); } QString iconPath; QString iconThemeName =DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName(); if (auto cached = DIconTheme::cached()) { iconPath = cached->findDciIconFile(iconName, iconThemeName); } else { iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName); } if (!iconPath.isEmpty()) icon = DDciIcon(iconPath); return icon; } DDciIcon DDciIcon::fromTheme(const QString &name, const DDciIcon &fallback) { DDciIcon icon = fromTheme(name); if (icon.isNull() || icon.availableSizes(Light).isEmpty() || icon.availableSizes(Dark).isEmpty()) return fallback; return icon; } #ifndef QT_NO_DATASTREAM QDataStream &operator<<(QDataStream &s, const DDciIcon &icon) { if (icon.isNull()) return s << QByteArray(); auto dciFile = icon.d->dciFile; const QByteArray &data = dciFile->toData(); s << data; return s; } QDataStream &operator>>(QDataStream &s, DDciIcon &icon) { QByteArray data; s >> data; icon = DDciIcon(data); return s; } DDciIconImage::DDciIconImage(const DDciIconImage &other) : d(other.d) { } DDciIconImage &DDciIconImage::operator=(const DDciIconImage &other) noexcept { d = other.d; return *this; } DDciIconImage::~DDciIconImage() { reset(); } DDciIconImage::DDciIconImage(DDciIconImage &&other) noexcept : d(other.d) { } DDciIconImage &DDciIconImage::operator=(DDciIconImage &&other) noexcept { swap(other); return *this; } void DDciIconImage::reset() { if (!d) return; qDeleteAll(d->readers); d->readers.clear(); d->supportsAnimation = false; d->totalMaxImageCount = 0; d->maxLoopCount = -2; d->animation = nullptr; d->currentImageNumber = 0; d->pastImageCount = 0; d->currentPastImageDelay = 0; } QImage DDciIconImage::toImage(const DDciIconPalette &palette) const { const int imageSize = qRound(d->imageSize * d->devicePixelRatio); QImage image(imageSize, imageSize, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter painter(&image); painter.setRenderHint(QPainter::SmoothPixmapTransform); paint(&painter, image.rect(), Qt::AlignCenter, palette); image.setDevicePixelRatio(d->devicePixelRatio); return image; } void DDciIconImage::paint(QPainter *painter, const QRectF &rect, Qt::Alignment alignment, const DDciIconPalette &palette) const { DDciIconPrivate::paint(painter, rect, alignment, d->layers, &d->readers, palette, d->imageScale); } bool DDciIconImage::hasPalette() const { return DDciIcon::isSupportedAttribute(*this, DDciIcon::HasPalette); } bool DDciIconImage::supportsAnimation() const { if (!d) return false; d->ensureLoad(); return d->supportsAnimation; } bool DDciIconImage::atBegin() const { return d && d->pastImageCount == 0; } bool DDciIconImage::atEnd() const { return d && d->supportsAnimation && d->pastImageCount >= d->totalMaxImageCount - 1; } bool DDciIconImage::jumpToNextImage() { d->ensureLoad(); if (!d->animation) return false; // Jump to next frame for current animation image d->animation->jumpToNextImage(d.get()); d->currentPastImageDelay = d->animation->pastImageDelay; d->animation = d->readAnimationNextData(); if (d->animation) { ++d->currentImageNumber; // Clear old images if icon animation is not last frame for (auto &reader : d->readers) { if (reader->currentImageIsEnd(d.get())) reader->currentImage = QImage(); } } return d->animation; } int DDciIconImage::loopCount() const { if (!d) return 0; d->ensureLoad(); return d->maxLoopCount; } int DDciIconImage::maxImageCount() const { if (!d) return 0; d->ensureLoad(); if (!d->supportsAnimation) return 0; return d->totalMaxImageCount; } int DDciIconImage::currentImageDuration() const { if (!d) return -1; d->ensureLoad(); if (!d->animation) return -1; return d->animation->pastImageDelay + d->animation->reader->nextImageDelay() - d->currentPastImageDelay; } int DDciIconImage::currentImageNumber() const { return d ? d->currentImageNumber : -1; } void DDciIconImagePrivate::init() { readers.reserve(layers.size()); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) for (const auto &layer : std::as_const(layers)) { #else for (const auto &layer : qAsConst(layers)) { #endif ReaderData *data = new ReaderData; Q_ASSERT(data); auto buffer = new QBuffer(); data->buffer.reset(buffer); auto reader = new QImageReader(); data->reader.reset(reader); readers.append(data); data->index = readers.size() - 1; buffer->setData(layer.data); buffer->open(QIODevice::ReadOnly); Q_ASSERT(buffer->isOpen()); reader->setDevice(buffer); reader->setFormat(layer.format); if (reader->supportsAnimation()) { supportsAnimation = true; totalMaxImageCount += reader->imageCount(); maxLoopCount = qMax(maxLoopCount, reader->loopCount()); } } if (supportsAnimation) animation = readAnimationNextData(); } DDciIconImagePrivate::ReaderData *DDciIconImagePrivate::readAnimationNextData() { const ReaderData *next = nullptr; for (auto &reader : readers) { if (!reader->reader->supportsAnimation()) continue; // Ensure can get a valid QImageReader::nextImageDelay(), Because // using QImageReader::nextImageDelay() needs call QImageReader::read() before. reader->initCurrentImage(this); if (reader->currentImageIsEnd(this) && !reader->jumpToNextImage(this)) continue; if (!next || reader->currentImageEndTime() < next->currentImageEndTime()) next = reader; } return const_cast(next); } #endif DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/ddciiconpalette.cpp000066400000000000000000000106701522615413000205130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "ddciiconpalette.h" #include #include #include #include DGUI_BEGIN_NAMESPACE DDciIconPalette::DDciIconPalette(QColor foreground, QColor background, QColor highlight, QColor highlightForeground) { colors.reserve(PaletteCount); colors.insert(Foreground, foreground); colors.insert(Background, background); colors.insert(HighlightForeground, highlightForeground); colors.insert(Highlight, highlight); } bool DDciIconPalette::operator==(const DDciIconPalette &other) const { for (int i = Foreground; i < PaletteCount; ++i) { if (colors.at(i) != other.colors.at(i)) return false; } return true; } bool DDciIconPalette::operator!=(const DDciIconPalette &other) const { return !(*this == other); } QColor DDciIconPalette::foreground() const { return colors.at(Foreground); } void DDciIconPalette::setForeground(const QColor &foreground) { colors[Foreground] = foreground; } QColor DDciIconPalette::background() const { return colors[Background]; } void DDciIconPalette::setBackground(const QColor &background) { colors[Background] = background; } QColor DDciIconPalette::highlightForeground() const { return colors[HighlightForeground]; } void DDciIconPalette::setHighlightForeground(const QColor &highlightForeground) { colors[HighlightForeground] = highlightForeground; } QColor DDciIconPalette::highlight() const { return colors[Highlight]; } void DDciIconPalette::setHighlight(const QColor &highlight) { colors[Highlight] = highlight; } static QString _d_dciIconPaletteHost() { return QLatin1String("dtk.dci.palette"); } QString DDciIconPalette::convertToString(const DDciIconPalette &palette) { QUrl url; url.setHost(_d_dciIconPaletteHost()); QUrlQuery query; if (palette.foreground().isValid()) query.addQueryItem(QLatin1String("foreground"), palette.foreground().name(QColor::HexArgb)); if (palette.background().isValid()) query.addQueryItem(QLatin1String("background"), palette.background().name(QColor::HexArgb)); if (palette.highlight().isValid()) query.addQueryItem(QLatin1String("highlight"), palette.highlight().name(QColor::HexArgb)); if (palette.highlightForeground().isValid()) query.addQueryItem(QLatin1String("highlightForeground"), palette.highlightForeground().name(QColor::HexArgb)); url.setQuery(query); return url.toString(); } DDciIconPalette DDciIconPalette::convertFromString(const QString &data) { QUrl url(data); if (url.host() != _d_dciIconPaletteHost()) return DDciIconPalette(); QUrlQuery query(url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1)); QColor foreground; if (query.hasQueryItem(QLatin1String("foreground"))) foreground = query.queryItemValue(QLatin1String("foreground")); QColor background; if (query.hasQueryItem(QLatin1String("background"))) background = query.queryItemValue(QLatin1String("background")); QColor highlight; if (query.hasQueryItem(QLatin1String("highlight"))) highlight = query.queryItemValue(QLatin1String("highlight")); QColor highlightForeground; if (query.hasQueryItem(QLatin1String("highlightForeground"))) highlightForeground = query.queryItemValue(QLatin1String("highlightForeground")); return DDciIconPalette(foreground, background, highlight, highlightForeground); } DDciIconPalette DDciIconPalette::fromQPalette(const QPalette &pa) { return DDciIconPalette(pa.windowText().color(), pa.window().color(), pa.highlight().color(), pa.highlightedText().color()); } DGUI_END_NAMESPACE QT_BEGIN_NAMESPACE DGUI_USE_NAMESPACE #ifndef QT_NO_DEBUG_STREAM static inline QString getColorName(QColor color) { if (color.isValid()) return color.name(QColor::HexArgb); return QLatin1String("InValid"); }; QDebug operator<<(QDebug dbg, const DDciIconPalette &pal) { QDebugStateSaver saver(dbg); QDebug nospace = dbg.nospace(); nospace << "DDciIconPalette(foreground: " << getColorName(pal.foreground()) << ",background: " << getColorName(pal.background()) << ",highlight: " << getColorName(pal.highlight()) << ",highlightForeground: " << getColorName(pal.highlightForeground()) << ")"; return dbg; } #endif QT_END_NAMESPACE dtkgui-6.7.46/src/util/ddciiconplayer.cpp000066400000000000000000001004011522615413000203410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "ddciiconplayer.h" #include "ddciicon.h" #include #include #include #include #include DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE #ifdef QT_DEBUG Q_LOGGING_CATEGORY(diPlayer, "dtk.dciicon.player") #else Q_LOGGING_CATEGORY(diPlayer, "dtk.dciicon.player", QtInfoMsg) #endif class DDciIconImagePlayerPrivate : DObjectPrivate { public: DDciIconImagePlayerPrivate(DDciIconImagePlayer *qq) : DObjectPrivate(qq) {} bool initCurrent(); bool ensureCurrent(); void clearCache(); void setState(DDciIconImagePlayer::State newState); inline bool reversed() const { return flags.testFlag(DDciIconImagePlayer::InvertedOrder); } inline bool hasCache(int imageIndex, int frameNumber) const { if (imageIndex < 0 || frameNumber < 0) return false; if (cachedFrames.size() <= imageIndex) return false; const auto &i = cachedFrames.at(imageIndex); if (i.size() <= frameNumber) return false; return true; } inline bool currentHasCache() const { return current >= 0 && currentFrameNumber >= 0 && hasCache(current, currentFrameNumber); } D_DECLARE_PUBLIC(DDciIconImagePlayer) QVector images; DDciIconPalette palette; inline DDciIconImage ¤tImage() { return images[current]; } DDciIconImagePlayer::State state = DDciIconImagePlayer::NotRunning; DDciIconImagePlayer::Flags flags; float speed = 1.0; // loop count for all images sequential animation int userLoopCount = 1; struct Frame { QImage image; int duration; }; QVector> cachedFrames; inline QVector ¤tCache() { return cachedFrames[current]; } int timerId = 0; // loop count for all images sequential animation, init from "userLoopCount" when start int loopCount = 1; int current = 0; int currentLoopCount = 0; int currentFrameNumber = 0; }; inline static bool jumpImageTo(DDciIconImage &image, int number) { if (number < 0) return false; if (image.currentImageNumber() > number) image.reset(); for (int i = image.currentImageNumber(); i < number; ++i) if (!image.jumpToNextImage()) return false;; return true; } bool DDciIconImagePlayerPrivate::initCurrent() { if (!currentImage().supportsAnimation()) return false; if (reversed()) { if (currentFrameNumber < 0) currentFrameNumber = currentCache().size() - 1; } else { if (currentFrameNumber < 0) currentFrameNumber = 0; } if (!currentHasCache()) { if (!jumpImageTo(currentImage(), currentFrameNumber)) return false; } if ((flags & DDciIconImagePlayer::CacheAll) && cachedFrames.size() <= current) { cachedFrames.append(QVector()); } if (current == images.size() - 1) { if (flags.testFlag(DDciIconImagePlayer::IgnoreLastImageLoop)) { currentLoopCount = 1; } else { currentLoopCount = currentImage().loopCount(); } } else if (flags.testFlag(DDciIconImagePlayer::AllowNonLastImageLoop)) { currentLoopCount = currentImage().loopCount(); } else { currentLoopCount = 1; } if (currentLoopCount == 0) currentLoopCount = 1; return true; } bool DDciIconImagePlayerPrivate::ensureCurrent() { while (current >= 0 && current < images.size()) { if (initCurrent()) return true; current += reversed() ? -1 : 1; currentFrameNumber = -1; } return false; } void DDciIconImagePlayerPrivate::clearCache() { cachedFrames.clear(); } void DDciIconImagePlayerPrivate::setState(DDciIconImagePlayer::State newState) { if (state == newState) return; state = newState; Q_EMIT q_func()->stateChanged(); } DDciIconImagePlayer::DDciIconImagePlayer(QObject *parent) : QObject(parent) , DObject(*new DDciIconImagePlayerPrivate(this)) { } void DDciIconImagePlayer::setImages(const QVector &images) { D_D(DDciIconImagePlayer); if (d->images == images) return; if (d->state != NotRunning) stop(); Q_ASSERT(d->state == NotRunning); d->images = images; d->current = -1; d->currentFrameNumber = -1; d->clearCache(); } QVector DDciIconImagePlayer::images() const { D_DC(DDciIconImagePlayer); return d->images; } const DDciIconImage &DDciIconImagePlayer::currentImage() const { D_DC(DDciIconImagePlayer); static DDciIconImage nullImage; if (d->state == NotRunning) return nullImage; return d->images.at(d->current); } bool DDciIconImagePlayer::currentLoopForever() const { D_DC(DDciIconImagePlayer); return d->state != NotRunning && d->currentLoopCount < 0; } bool DDciIconImagePlayer::setPalette(const DDciIconPalette &palette) { D_D(DDciIconImagePlayer); if (d->palette == palette) return false; d->palette = palette; bool hasPalette = false; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) for (const auto &i : std::as_const(d->images)) #else for (const auto &i : qAsConst(d->images)) #endif if (i.hasPalette()) hasPalette = true; if (!hasPalette) return true; if (d->state == NotRunning) { d->clearCache(); } else { d->flags |= ClearCacheOnStop; } return true; } DDciIconPalette DDciIconImagePlayer::palette() const { D_DC(DDciIconImagePlayer); return d->palette; } void DDciIconImagePlayer::setLoopCount(int count) { D_D(DDciIconImagePlayer); if (count <= 0) return; if (d->state != NotRunning) { d->loopCount += (count - d->userLoopCount); } d->userLoopCount = count; } int DDciIconImagePlayer::loopCount() const { D_DC(DDciIconImagePlayer); return d->userLoopCount; } void DDciIconImagePlayer::abortLoop() { D_D(DDciIconImagePlayer); if (d->state == NotRunning) return; d->flags = (d->flags | IgnoreLastImageLoop) & (~AllowNonLastImageLoop); d->currentLoopCount = 0; d->loopCount = 0; } QImage DDciIconImagePlayer::readImage() { D_D(DDciIconImagePlayer); if (d->state != WaitingRead) return QImage(); QImage image; int timerIntervel = 0; if (d->currentHasCache()) { image = d->currentCache().at(d->currentFrameNumber).image; timerIntervel = qRound(d->currentCache().at(d->currentFrameNumber).duration / d->speed); } else { Q_ASSERT(!d->reversed()); Q_ASSERT(d->currentImage().currentImageNumber() == d->currentFrameNumber); image = d->currentImage().toImage(d->palette); if (d->flags & CacheAll) { Q_ASSERT(d->currentImage().currentImageNumber() == d->currentFrameNumber); Q_ASSERT(d->currentCache().size() == d->currentFrameNumber); d->currentCache().append({image, d->currentImage().currentImageDuration()}); } timerIntervel = qRound(d->currentImage().currentImageDuration() / d->speed); } d->timerId = startTimer(timerIntervel < 0 ? 0 : timerIntervel); if (d->timerId == 0) { qCWarning(diPlayer, "Can't start timer, will abort the animations."); stop(); Q_EMIT finished(); return image; } d->setState(Running); return image; } DDciIconImagePlayer::State DDciIconImagePlayer::state() const { D_DC(DDciIconImagePlayer); return d->state; } void DDciIconImagePlayer::clearCache() { D_D(DDciIconImagePlayer); d->clearCache(); } bool DDciIconImagePlayer::start(float speed, Flags flags) { D_D(DDciIconImagePlayer); if (d->state != NotRunning) return false; if (d->images.isEmpty()) return false; d->flags = flags; if (!d->flags.testFlag(Continue) || d->current < 0) { d->current = d->reversed() ? d->images.size() - 1 : 0; } if (d->reversed()) { d->flags |= CacheAll; if (d->cachedFrames.isEmpty()) { d->cachedFrames.resize(d->images.size()); for (int i = 0; i <= d->current; ++i) { DDciIconImage &image = d->images[i]; if (!image.supportsAnimation()) continue; image.reset(); do { d->cachedFrames[i].append({image.toImage(d->palette), image.currentImageDuration()}); } while (image.jumpToNextImage()); } } else if (!flags.testFlag(Continue)) { auto &image = d->images[d->cachedFrames.size() - 1]; if (image.supportsAnimation() && jumpImageTo(image, d->cachedFrames.last().size())) { do { d->cachedFrames.last().append({image.toImage(d->palette), image.currentImageDuration()}); } while (image.jumpToNextImage()); } for (int i = d->cachedFrames.size(); i < d->images.size(); ++i) { d->cachedFrames.append(QVector()); auto &image = d->images[i]; if (!image.supportsAnimation()) continue; image.reset(); do { d->cachedFrames[i].append({image.toImage(d->palette), image.currentImageDuration()}); } while (image.jumpToNextImage()); } d->currentFrameNumber = d->currentCache().size() - 1; } } else { if (flags.testFlag(Continue)) { if (d->current < 0) d->current = 0; } else { d->current = 0; d->currentFrameNumber = 0; } // Init cache if (flags.testFlag(CacheAll) && d->cachedFrames.isEmpty() && (d->current > 0 || d->currentFrameNumber > 0)) { d->cachedFrames.resize(d->images.size()); DDciIconImage &image = d->images[d->current]; if (image.supportsAnimation()) { image.reset(); do { d->cachedFrames[d->current].append({image.toImage(d->palette), image.currentImageDuration()}); } while (image.jumpToNextImage()); } } } d->speed = speed > 0.0 ? speed : 1.0; d->loopCount = d->userLoopCount; if (!d->ensureCurrent()) return false; d->setState(WaitingRead); Q_EMIT started(); Q_EMIT updated(); return true; } void DDciIconImagePlayer::stop() { D_D(DDciIconImagePlayer); if (d->state == NotRunning) return; if (d->timerId > 0) { killTimer(d->timerId); d->timerId = 0; } if (d->flags & ClearCacheOnStop) d->clearCache(); d->setState(NotRunning); } void DDciIconImagePlayer::timerEvent(QTimerEvent *event) { D_D(DDciIconImagePlayer); if (event->timerId() != d->timerId) return QObject::timerEvent(event); killTimer(d->timerId); d->timerId = 0; bool finished = false; const int newFrameNumber = d->currentFrameNumber + (d->reversed() ? -1 : 1); if (!d->hasCache(d->current, newFrameNumber)) { if (d->reversed()) { finished = true; } else { finished = !jumpImageTo(d->currentImage(), newFrameNumber); } } #define IGNORE_LOOP qEnvironmentVariableIsSet("D_DTK_DCI_PLAYER_IGNORE_ANIMATION_LOOP") if (finished) { if (d->currentLoopCount != 0 && --d->currentLoopCount && !IGNORE_LOOP) { // reset value d->currentFrameNumber = -1; // replay current image bool ok = d->initCurrent(); Q_ASSERT(ok); finished = false; } else { const int newCurrent = d->current + (d->reversed() ? -1 : 1); if (newCurrent >= 0 && newCurrent < d->images.size()) { d->current = newCurrent; d->currentFrameNumber = -1; if (d->ensureCurrent()) finished = false; } } } else { d->currentFrameNumber = newFrameNumber; } if (finished && d->loopCount != 0 && (--d->loopCount) && !IGNORE_LOOP) { d->current = d->reversed() ? d->images.size() - 1 : 0; d->currentFrameNumber = -1; if (d->ensureCurrent()) finished = false; } if (finished) { stop(); Q_EMIT this->finished(); } else { d->setState(WaitingRead); Q_EMIT updated(); } } static QString iconModeToString(DDciIcon::Mode mode) { switch (mode) { case DDciIcon::Normal: return QStringLiteral("Normal"); case DDciIcon::Hover: return QStringLiteral("Hover"); case DDciIcon::Pressed: return QStringLiteral("Pressed"); case DDciIcon::Disabled: return QStringLiteral("Disabled"); default: break; } return nullptr; } class DDciIconPlayerPrivate : public DObjectPrivate { public: DDciIconPlayerPrivate(DDciIconPlayer *qq) : DObjectPrivate(qq) {} void ensureInit(); void initPlayer(); bool ensureHoverModeLastImage(); void play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags); bool play(DDciIcon::Mode fromMode, DDciIcon::Mode toMode, DDciIconImagePlayer::Flags extraflags = {}); inline void _q_playFromQueue(int extraflags = 0) { if (player && player->state() != DDciIconImagePlayer::NotRunning) return; if (animationJobs.isEmpty()) return; const auto &job = animationJobs.first(); bool ok = play(static_cast(job.from), static_cast(job.to), DDciIconImagePlayer::Flags(static_cast(extraflags))); if (!ok) { qCDebug(diPlayer, "Don't play any animations, from mode is \"%s\", to mode is \"%s\"", qPrintable(iconModeToString(job.from)), qPrintable(iconModeToString(job.to))); animationJobs.removeFirst(); } // else: the job will remove on animation finished } void playToQueue(); inline bool start(DDciIcon::Mode forMode, qreal speed = 1.0, DDciIconImagePlayer::Flags flags = {}) { qCDebug(diPlayer) << "Start animation for" << iconModeToString(forMode); const bool ok = player->start(speed, flags); if (ok && forMode == DDciIcon::Hover && !flags.testFlag(DDciIconImagePlayer::InvertedOrder)) { // When from Pressed mode to Hover mode, needs stop at the hover mode animation last frame. saveImageForHoverModeOnFinished = true; } if (ok) { setState(DDciIconPlayer::Busy); } else if (diPlayer().isDebugEnabled()) { qCDebug(diPlayer, "Failed on start animation for \"%s\"", qPrintable(iconModeToString(forMode))); } return ok; } inline void reset() { if (player && player->state() != DDciIconImagePlayer::NotRunning) { player->stop(); } normal = DDciIconImage(); hover = DDciIconImage(); pressed = DDciIconImage(); disabled = DDciIconImage(); hoverModeLastImage = QImage(); } inline bool isValid() const { return !normal.isNull(); } inline void setImage(const QImage &image) { this->image = image; Q_EMIT q_func()->updated(); } inline void setImage(DDciIcon::Mode mode) { auto &image = getImage(mode); if (image.atBegin()) { setImage(image.toImage(player->palette())); } else { setImage(icon.pixmap(devicePixelRatio, iconSize, theme, mode, player->palette()).toImage()); } } inline void setFinishedImage(DDciIcon::Mode mode) { finishedImage = icon.pixmap(devicePixelRatio, iconSize, theme, mode, player->palette()).toImage(); } inline const DDciIconImage &getImage(DDciIcon::Mode mode) const { if (mode == DDciIcon::Hover) { return hover; } else if (mode == DDciIcon::Pressed) { return pressed; } else if (mode == DDciIcon::Disabled) { return disabled; } Q_ASSERT(mode == DDciIcon::Normal); return normal; } inline void setState(DDciIconPlayer::State newState) { if (state == newState) return; state = newState; Q_EMIT q_func()->stateChanged(); } DDciIconPlayer::State state = DDciIconPlayer::Idle; DDciIcon icon; DDciIcon::Theme theme = DDciIcon::Light; DDciIcon::Mode mode = DDciIcon::Normal; DDciIcon::Mode lastMode = DDciIcon::Normal; int iconSize = -1; qreal devicePixelRatio = 1.0; DDciIconImage normal; DDciIconImage hover; DDciIconImage pressed; DDciIconImage disabled; DDciIconImagePlayer *player = nullptr; struct Animation { DDciIcon::Mode from; DDciIcon::Mode to; }; QVector animationJobs; bool saveImageForHoverModeOnFinished = false; QImage image; QImage finishedImage; QImage hoverModeLastImage; D_DECLARE_PUBLIC(DDciIconPlayer) }; void DDciIconPlayerPrivate::ensureInit() { initPlayer(); if (!normal.isNull()) return; if (icon.isNull()) return; normal = icon.image(icon.matchIcon(iconSize, theme, DDciIcon::Normal, DDciIcon::DontFallbackMode), iconSize, devicePixelRatio); hover = icon.image(icon.matchIcon(iconSize, theme, DDciIcon::Hover, DDciIcon::DontFallbackMode), iconSize, devicePixelRatio); pressed = icon.image(icon.matchIcon(iconSize, theme, DDciIcon::Pressed, DDciIcon::DontFallbackMode), iconSize, devicePixelRatio); disabled = icon.image(icon.matchIcon(iconSize, theme, DDciIcon::Disabled, DDciIcon::DontFallbackMode), iconSize, devicePixelRatio); } void DDciIconPlayerPrivate::initPlayer() { if (player) return; player = new DDciIconImagePlayer(q_func()); D_Q(DDciIconPlayer); QObject::connect(player, &DDciIconImagePlayer::updated, q, [this]() { setImage(player->readImage()); }); QObject::connect(player, &DDciIconImagePlayer::finished, q, [q, this]() { qCDebug(diPlayer, "Current animation finished!"); if (saveImageForHoverModeOnFinished) { saveImageForHoverModeOnFinished = false; hoverModeLastImage = image; } if (!animationJobs.isEmpty()) { // Remove the finished animation animationJobs.removeFirst(); qCDebug(diPlayer) << "Number of animations remaining is" << animationJobs.size(); if (!animationJobs.isEmpty()) { _q_playFromQueue(); return; } } if (!finishedImage.isNull()) { setImage(finishedImage); finishedImage = QImage(); } if (mode == DDciIcon::Normal || mode == DDciIcon::Disabled) { player->clearCache(); } setState(DDciIconPlayer::Idle); }); } bool DDciIconPlayerPrivate::ensureHoverModeLastImage() { if (!hoverModeLastImage.isNull()) return true; if (!hover.supportsAnimation()) return false; DDciIconImage image; const bool currentHoverImageIsUsable = hover.atEnd() || !player || player->state() != DDciIconImagePlayer::NotRunning; if (!currentHoverImageIsUsable) { if (icon.isNull()) return false; image = icon.image(icon.matchIcon(iconSize, theme, DDciIcon::Hover, DDciIcon::DontFallbackMode), iconSize, devicePixelRatio); } if (image.isNull()) return false; while (!image.atEnd()) { if (!image.jumpToNextImage()) break; } if (!image.atEnd()) return false; Q_ASSERT(player); hoverModeLastImage = image.toImage(player->palette()); return !hoverModeLastImage.isNull(); } void DDciIconPlayerPrivate::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags) { if (diPlayer().isDebugEnabled()) { qCDebug(diPlayer) << "Immediate play animation for" << iconModeToString(mode); } ensureInit(); if (normal.isNull()) return; // Ensure the old animations clean animationJobs.clear(); player->stop(); finishedImage = QImage(); const DDciIconImage &image = getImage(mode); if (!image.supportsAnimation()) return; player->setImages({image}); start(mode, 1.0, flags); } bool DDciIconPlayerPrivate::play(DDciIcon::Mode fromMode, DDciIcon::Mode toMode, DDciIconImagePlayer::Flags extraflags) { ensureInit(); finishedImage = QImage(); if (normal.isNull()) { setImage(QImage()); return false; } if (fromMode == DDciIcon::Normal) { if (toMode == DDciIcon::Normal) { setImage(DDciIcon::Normal); } else if (toMode == DDciIcon::Hover) { if (hover.isNull()) { return false; } if (hover.supportsAnimation()) { player->setImages({hover}); return start(toMode, 1.0, DDciIconImagePlayer::CacheAll | extraflags); } else { setImage(DDciIcon::Hover); } } else if (toMode == DDciIcon::Pressed) { if (pressed.isNull()) { return false; } if (pressed.supportsAnimation()) { if (hover.supportsAnimation()) { player->setImages({hover, pressed}); return start(toMode, 2.0, DDciIconImagePlayer::CacheAll | extraflags); } else { player->setImages({pressed}); return start(toMode, 1.0, DDciIconImagePlayer::CacheAll | extraflags); } } else { setImage(DDciIcon::Pressed); } } else if (toMode == DDciIcon::Disabled) { if (disabled.isNull()) return false; if (disabled.supportsAnimation()) { player->setImages({disabled}); return start(toMode, 1.0, DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Disabled); } } } else if (fromMode == DDciIcon::Hover) { Q_ASSERT(toMode != DDciIcon::Hover); if (toMode == DDciIcon::Normal) { if (hover.supportsAnimation()) { setFinishedImage(DDciIcon::Normal); player->setImages({hover}); return start(toMode, 1.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | DDciIconImagePlayer::ClearCacheOnStop | extraflags); } else { setImage(DDciIcon::Normal); } } else if (toMode == DDciIcon::Hover) { } else if (toMode == DDciIcon::Pressed) { if (pressed.isNull()) { if (hover.supportsAnimation()) { player->setImages({hover}); return start(toMode, 1.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Normal); } return false; } if (pressed.supportsAnimation()) { player->setImages({pressed}); return start(toMode, 1.0, DDciIconImagePlayer::CacheAll | extraflags); } else { setImage(DDciIcon::Pressed); } } else if (toMode == DDciIcon::Disabled) { if (disabled.isNull()) { setImage(DDciIcon::Normal); return false; } if (disabled.supportsAnimation()) { player->setImages({disabled}); return start(toMode, 1.0, DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Disabled); } } } else if (fromMode == DDciIcon::Pressed) { Q_ASSERT(toMode != DDciIcon::Pressed); if (toMode == DDciIcon::Normal) { if (!pressed.supportsAnimation()) { setImage(DDciIcon::Normal); return false; } setFinishedImage(DDciIcon::Normal); if (hover.supportsAnimation()) { player->setImages({hover, pressed}); return start(toMode, 2.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { player->setImages({pressed}); return start(toMode, 1.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } } else if (toMode == DDciIcon::Hover) { if (pressed.isNull()) { if (hover.supportsAnimation()) { player->setImages({hover}); return start(toMode, 1.0, DDciIconImagePlayer::CacheAll | extraflags); } else { setImage(DDciIcon::Hover); } return false; } if (pressed.supportsAnimation()) { ensureHoverModeLastImage(); finishedImage = hoverModeLastImage; player->setImages({pressed}); return start(toMode, 1.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Hover); } } else if (toMode == DDciIcon::Pressed) { } else if (toMode == DDciIcon::Disabled) { if (disabled.isNull()) { setImage(DDciIcon::Normal); return false; } if (disabled.supportsAnimation()) { player->setImages({disabled}); return start(toMode, 1.0, DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Disabled); } } } else if (fromMode == DDciIcon::Disabled) { Q_ASSERT(toMode != DDciIcon::Disabled); if (disabled.supportsAnimation()) { setFinishedImage(DDciIcon::Normal); player->setImages({disabled}); return start(toMode, 1.0, DDciIconImagePlayer::InvertedOrder | DDciIconImagePlayer::IgnoreLastImageLoop | extraflags); } else { setImage(DDciIcon::Normal); } } return false; } void DDciIconPlayerPrivate::playToQueue() { DDciIconImagePlayer::Flags extraFlags = {}; if (diPlayer().isDebugEnabled()) { qCDebug(diPlayer, "Request play animation in queue, from mode is \"%s\", to mode is \"%s\"", qPrintable(iconModeToString(lastMode)), qPrintable(iconModeToString(mode))); } if (!animationJobs.isEmpty()) { if (diPlayer().isDebugEnabled()) { qCDebug(diPlayer, "Old Animation Queue:"); for (int i = 0; i < animationJobs.count(); ++i) { const Animation &job = animationJobs.at(i); qCDebug(diPlayer, " %d. from mode is \"%s\", to mode is \"%s\"", i + 1, qPrintable(iconModeToString(job.from)), qPrintable(iconModeToString(job.to))); } } // Ignore the same request if (animationJobs.last().from == lastMode && animationJobs.last().to == mode) { qCDebug(diPlayer, "Same as the last animation, ignores this request"); return; } if (animationJobs.last().from == mode && animationJobs.last().to == lastMode) { if (animationJobs.size() > 1) { animationJobs.removeLast(); qCDebug(diPlayer, "Offsets the last unplayed animation, discards the animation, and ignores this request"); return; } else { if (player && player->state() != DDciIconImagePlayer::NotRunning) { extraFlags |= DDciIconImagePlayer::Continue; player->stop(); animationJobs.removeFirst(); } } } } else { if (player) player->stop(); qCDebug(diPlayer, "Old Animation queue is empty"); } animationJobs.append({lastMode, mode}); if (player && player->state() != DDciIconImagePlayer::NotRunning) { player->abortLoop(); Q_ASSERT(!player->currentLoopForever()); // Don't stop current animation, wating play to end. // Ensure the continuity of the animation when multiple states change continuously. // An example is changing from the Normal state to the Hover state and then to the // Pressed state in a short period of time. At this time, the animation in the // hover state may not have finished playing. qCDebug(diPlayer, "Wait the current animation finished to continue play the new animation."); return; } QMetaObject::invokeMethod(q_func(), "_q_playFromQueue", Qt::QueuedConnection, Q_ARG(int, extraFlags)); } DDciIconPlayer::DDciIconPlayer(QObject *parent) : QObject(parent) , DObject(*new DDciIconPlayerPrivate(this)) { } DDciIconPlayer::State DDciIconPlayer::state() const { D_DC(DDciIconPlayer); return d->state; } void DDciIconPlayer::setIcon(const DDciIcon &icon) { D_D(DDciIconPlayer); d->icon = icon; d->reset(); d->playToQueue(); } DDciIcon DDciIconPlayer::icon() const { D_DC(DDciIconPlayer); return d->icon; } void DDciIconPlayer::setTheme(DDciIcon::Theme theme) { D_D(DDciIconPlayer); if (d->theme == theme) return; d->theme = theme; d->reset(); d->playToQueue(); } DDciIcon::Theme DDciIconPlayer::theme() const { D_DC(DDciIconPlayer); return d->theme; } void DDciIconPlayer::setMode(DDciIcon::Mode mode) { D_D(DDciIconPlayer); if (d->mode == mode) return; d->lastMode = d->mode; d->mode = mode; Q_EMIT modeChanged(d->lastMode, mode); if (diPlayer().isDebugEnabled()) { qCDebug(diPlayer) << this << "Old Mode:" << iconModeToString(d->lastMode) << "New Mode" << iconModeToString(d->mode); } if (mode == DDciIcon::Disabled) abort(); d->playToQueue(); } DDciIcon::Mode DDciIconPlayer::mode() const { D_DC(DDciIconPlayer); return d->mode; } void DDciIconPlayer::setIconSize(int size) { D_D(DDciIconPlayer); if (d->iconSize == size) return; d->iconSize = size; d->reset(); d->playToQueue(); } int DDciIconPlayer::iconSize() const { D_DC(DDciIconPlayer); return d->iconSize; } void DDciIconPlayer::setDevicePixelRatio(qreal devicePixelRatio) { D_D(DDciIconPlayer); if (qFuzzyCompare(d->devicePixelRatio, devicePixelRatio)) return; d->devicePixelRatio = devicePixelRatio; d->reset(); d->playToQueue(); } qreal DDciIconPlayer::devicePixelRatio() const { D_DC(DDciIconPlayer); return d->devicePixelRatio; } void DDciIconPlayer::setPalette(const DDciIconPalette &palette) { D_D(DDciIconPlayer); d->initPlayer(); if (d->player->setPalette(palette)) { if (d->hover.hasPalette()) d->hoverModeLastImage = QImage(); const auto &image = d->getImage(d->mode); if (image.hasPalette()) d->playToQueue(); } } QImage DDciIconPlayer::currentImage() const { D_DC(DDciIconPlayer); return d->image; } void DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags) { D_D(DDciIconPlayer); d->play(mode, flags); } void DDciIconPlayer::play(DDciIcon::Mode mode) { play(mode, DDciIconImagePlayer::IgnoreLastImageLoop); } void DDciIconPlayer::stop() { D_D(DDciIconPlayer); if (d->player) d->player->stop(); d->setState(Idle); } void DDciIconPlayer::abort() { D_D(DDciIconPlayer); d->animationJobs.clear(); if (d->player) d->player->stop(); d->setState(Idle); } DGUI_END_NAMESPACE #include "moc_ddciiconplayer.cpp" dtkgui-6.7.46/src/util/ddesktopservices_linux.cpp000066400000000000000000000146321522615413000221620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "ddesktopservices.h" #include #include #include DGUI_BEGIN_NAMESPACE #define EASY_CALL_DBUS(name) \ QDBusInterface *interface = fileManager1DBusInterface(); \ return interface && \ interface->call(#name, urls2uris(urls), startupId).type() != \ QDBusMessage::ErrorMessage; static const QStringList SOUND_EFFECT_LIST { "message", "camera-shutter", "trash-empty", "x-deepin-app-sent-to-desktop", "desktop-login", "system-shutdown", "desktop-logout", "suspend-resume", "audio-volume-change", "power-unplug-battery-low", "power-plug", "power-unplug", "device-added", "device-removed", "dialog-error", }; static QDBusInterface *fileManager1DBusInterface() { static QDBusInterface interface(QStringLiteral("org.freedesktop.FileManager1"), QStringLiteral("/org/freedesktop/FileManager1"), QStringLiteral("org.freedesktop.FileManager1")); return &interface; } static QStringList urls2uris(const QList &urls) { QStringList list; list.reserve(urls.size()); for (const QUrl &url : urls) { list << url.toString(); } return list; } static QList path2urls(const QList &paths) { QList list; list.reserve(paths.size()); for (const QString &path : paths) { list << QUrl::fromLocalFile(path); } return list; } static QDBusInterface soundEffectInterface() { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) const auto& infc = QDBusConnection::sessionBus().interface(); QStringList activatableServiceNames = infc->activatableServiceNames(); bool isNewInterface = activatableServiceNames.contains(QLatin1String("org.deepin.dde.SoundEffect1")); #else bool isNewInterface = false; // Qt 5.14 以下就直接用旧的接å�£ #endif const QLatin1String service(isNewInterface ? "org.deepin.dde.SoundEffect1" :"com.deepin.daemon.SoundEffect"); const QLatin1String path(isNewInterface ? "/org/deepin/dde/SoundEffect1" : "/com/deepin/daemon/SoundEffect"); const QLatin1String interface(isNewInterface ? "org.deepin.dde.SoundEffect1" :"com.deepin.daemon.SoundEffect"); // 使用å�Žç«¯ dbus 接å�£æ’­æ”¾ç³»ç»ŸéŸ³é¢‘,音频存放目录: /usr/share/sounds/deepin/stereo/ return QDBusInterface(service, path, interface); } static bool systemSoundEffectEnabled(const QString &name) { auto soundEffect = soundEffectInterface(); if (!soundEffect.property("Enabled").toBool()) return false; QDBusReply reply = soundEffect.call("IsSoundEnabled", name); return reply.isValid() && reply.value(); } bool DDesktopServices::showFolder(const QString &localFilePath, const QString &startupId) { return showFolder(QUrl::fromLocalFile(localFilePath), startupId); } bool DDesktopServices::showFolders(const QList &localFilePaths, const QString &startupId) { return showFolders(path2urls(localFilePaths), startupId); } bool DDesktopServices::showFolder(const QUrl &url, const QString &startupId) { return showFolders(QList() << url, startupId); } bool DDesktopServices::showFolders(const QList &urls, const QString &startupId) { EASY_CALL_DBUS(ShowFolders) } bool DDesktopServices::showFileItemProperty(const QString &localFilePath, const QString &startupId) { return showFileItemProperty(QUrl::fromLocalFile(localFilePath), startupId); } bool DDesktopServices::showFileItemProperties(const QList &localFilePaths, const QString &startupId) { return showFileItemProperties(path2urls(localFilePaths), startupId); } bool DDesktopServices::showFileItemProperty(const QUrl &url, const QString &startupId) { return showFileItemProperties(QList() << url, startupId); } bool DDesktopServices::showFileItemProperties(const QList &urls, const QString &startupId) { EASY_CALL_DBUS(ShowItemProperties) } bool DDesktopServices::showFileItem(const QString &localFilePath, const QString &startupId) { return showFileItem(QUrl::fromLocalFile(localFilePath), startupId); } bool DDesktopServices::showFileItems(const QList &localFilePaths, const QString &startupId) { return showFileItems(path2urls(localFilePaths), startupId); } bool DDesktopServices::showFileItem(const QUrl &url, const QString &startupId) { return showFileItems(QList() << url, startupId); } bool DDesktopServices::showFileItems(const QList &urls, const QString &startupId) { EASY_CALL_DBUS(ShowItems) } bool DDesktopServices::trash(const QString &localFilePath) { return trash(QUrl::fromLocalFile(localFilePath)); } bool DDesktopServices::trash(const QList &localFilePaths) { return trash(path2urls(localFilePaths)); } bool DDesktopServices::trash(const QUrl &url) { return trash(QList() << url); } bool DDesktopServices::trash(const QList &urls) { QDBusInterface *interface = fileManager1DBusInterface(); return interface && interface->call("Trash", urls2uris(urls)).type() != QDBusMessage::ErrorMessage; } bool DDesktopServices::playSystemSoundEffect(const DDesktopServices::SystemSoundEffect &effect) { return playSystemSoundEffect(SOUND_EFFECT_LIST.at(static_cast(effect))); } bool DDesktopServices::playSystemSoundEffect(const QString &name) { if (!systemSoundEffectEnabled(name)) return false; return previewSystemSoundEffect(name); } bool DDesktopServices::previewSystemSoundEffect(const DDesktopServices::SystemSoundEffect &effect) { return previewSystemSoundEffect(SOUND_EFFECT_LIST.at(static_cast(effect))); } bool DDesktopServices::previewSystemSoundEffect(const QString &name) { if (name.isEmpty()) { return false; } // 使用å�Žç«¯ dbus 接å�£æ’­æ”¾ç³»ç»ŸéŸ³é¢‘,音频存放目录: /usr/share/sounds/deepin/stereo/ return soundEffectInterface().call("PlaySound", name).type() != QDBusMessage::ErrorMessage; } QString DDesktopServices::getNameByEffectType(const DDesktopServices::SystemSoundEffect &effect) { return SOUND_EFFECT_LIST.at(static_cast(effect)); } QString DDesktopServices::errorMessage() { return fileManager1DBusInterface()->lastError().message(); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dfontmanager.cpp000066400000000000000000000072751522615413000200340ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include "dfontmanager.h" #include "dfontmanager_p.h" #include "util/dprivateaccessor_p.h" #include #include D_DECLARE_PRIVATE_MEMBER(QFont_d_tag, QFont, d, QExplicitlySharedDataPointer); DGUI_BEGIN_NAMESPACE DFontManagerPrivate::DFontManagerPrivate(DFontManager *qq) : DTK_CORE_NAMESPACE::DObjectPrivate(qq) { baseFont.setPixelSize(fontPixelSize[baseFontSizeType]); } /*! \class Dtk::Gui::DFontManager \inmodule dtkgui \brief 字体大å°�设置的一个类,系统默认å�ªè®¾ç½®T6. */ DFontManager::DFontManager(QObject *parent) : QObject(parent) , DTK_CORE_NAMESPACE::DObject(*new DFontManagerPrivate(this)) { } DFontManager::~DFontManager() { } /*! \enum Dtk::Gui::DFontManager::SizeType DFontManager::SizeType 定义了 DFontManager 的系统字体的定义的大å°�; 而系统å�ªä¼šè®¾ç½® T6 为系统默认的字体 \value T1 系统级别为 T1 的字体大å°�, 默认是40 px \value T2 系统级别为 T2 的字体大å°�, 默认是30 px \value T3 系统级别为 T3 的字体大å°�, 默认是24 px \value T4 系统级别为 T4 的字体大å°�, 默认是20 px \value T5 系统级别为 T5 的字体大å°�, 默认是16 px \value T6 系统级别为 T6 的字体大å°�, 默认是14 px \value T7 系统级别为 T7 的字体大å°�, 默认是13 px \value T8 系统级别为 T8 的字体大å°�, 默认是12 px \value T9 系统级别为 T9 的字体大å°�, 默认是11 px \value T10 系统级别为 T10 的字体大å°�, 默认是10 px \value T11 系统级别为 T11 的字体大å°�, 默认是8 px \omitvalue NSizeTypes */ /*! \brief 获å�–字体åƒ�素的大å°�. \a type 字体枚举类型 \return 返回字体åƒ�素的大å°� */ int DFontManager::fontPixelSize(DFontManager::SizeType type) const { D_DC(DFontManager); if (type >= NSizeTypes) { return 0; } return d->fontPixelSize[type] + d->fontPixelSizeDiff; } /*! \brief 设置字体åƒ�素大å°�. \a type 字体枚举类型 \a size 字体大å°� */ void DFontManager::setFontPixelSize(DFontManager::SizeType type, int size) { D_D(DFontManager); if (type >= NSizeTypes) { return; } if (d->fontPixelSize[type] == size) { return; } d->fontPixelSize[type] = size; } /*! \brief 设置字体的通用åƒ�素大å°�. \a font 预设计的字体åƒ�素的大å°� */ void DFontManager::setBaseFont(const QFont &font) { D_D(DFontManager); if (d->baseFont == font) return; d->baseFont = font; d->fontPixelSizeDiff = fontPixelSize(font) - d->fontPixelSize[d->baseFontSizeType]; Q_EMIT fontChanged(); } QFont DFontManager::baseFont() const { D_DC(DFontManager); return d->baseFont; } void DFontManager::resetBaseFont() { D_DC(DFontManager); QFont font; font.setPixelSize(d->fontPixelSize[d->baseFontSizeType]); setBaseFont(font); } /*! \brief 获å�–字体. \a pixelSize 字体的åƒ�素大å°� \a base è¦�基于的字体 \return 返回设置字体大å°�å�Žçš„字体 */ QFont DFontManager::get(int pixelSize, const QFont &base) { QFont font = base; font.setPixelSize(pixelSize); // Ensure that the FamilyResolved flag is set in order for Qt to correctly set fonts font.setFamilies(base.families()); return font; } int DFontManager::fontPixelSize(const QFont &font) { int px = font.pixelSize(); if (px == -1) { px = qRound(std::floor(((font.pointSizeF() * D_PRIVATE_MEMBER(font, QFont_d_tag{})->dpi) / 72) * 100 + 0.5) / 100); } return px; } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dicon.cpp000066400000000000000000000053121522615413000164510ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dicon.h" #include #include #include DGUI_BEGIN_NAMESPACE DIcon::DIcon(const QIcon &other) : QIcon(other) { } DIcon::~DIcon() { } /*! Icon::pixmap * Returns a pixmap with the requested \a size, \a devicePixelRatio, \a mode, and \a state, generating one if necessary. * * \sa QIcon::actualsize(), QIcon::paint() */ QPixmap DIcon::pixmap(const QSize &size, qreal devicePixelRatio, QIcon::Mode mode, QIcon::State state) { DataPtr d = data_ptr(); if (!d) return QPixmap(); if (qFuzzyCompare(devicePixelRatio, -1)) devicePixelRatio = qApp->devicePixelRatio(); if (!(devicePixelRatio > 1.0)) { QPixmap pixmap = d->engine->pixmap(size, mode, state); pixmap.setDevicePixelRatio(1.0); return pixmap; } QPixmap pixmap = d->engine->scaledPixmap(size * devicePixelRatio, mode, state, devicePixelRatio); auto pixmapDevicePixelRatio = [](qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize)->qreal { QSize targetSize = requestedSize * displayDevicePixelRatio; if ((actualSize.width() == targetSize.width() && actualSize.height() <= targetSize.height()) || (actualSize.width() <= targetSize.width() && actualSize.height() == targetSize.height())) { return displayDevicePixelRatio; } qreal scale = 0.5 * (qreal(actualSize.width()) / qreal(targetSize.width()) + qreal(actualSize.height() / qreal(targetSize.height()))); return qMax(qreal(1.0), displayDevicePixelRatio * scale); }; pixmap.setDevicePixelRatio(pixmapDevicePixelRatio(devicePixelRatio, size, pixmap.size())); return pixmap; } /*! * @brief DIcon::loadNxPixmap loads the suitable @Nx image. * @param fileName is the original resource file name. * @return the hiDPI ready QPixmap. */ QPixmap DIcon::loadNxPixmap(const QString &fileName) { qreal sourceDevicePixelRatio = 1.0; qreal devicePixelRatio = qApp->devicePixelRatio(); QPixmap pixmap; if (!qFuzzyCompare(sourceDevicePixelRatio, devicePixelRatio)) { QImageReader reader; reader.setFileName(qt_findAtNxFile(fileName, devicePixelRatio, &sourceDevicePixelRatio)); if (reader.canRead()) { reader.setScaledSize(reader.size() * (devicePixelRatio / sourceDevicePixelRatio)); pixmap = QPixmap::fromImage(reader.read()); pixmap.setDevicePixelRatio(devicePixelRatio); } } else { pixmap.load(fileName); } return pixmap; } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dicontheme.cpp000066400000000000000000000212321522615413000174730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dicontheme.h" #include "private/dbuiltiniconengine_p.h" #include "private/dciiconengine_p.h" #include "private/diconproxyengine_p.h" #include #ifndef DTK_DISABLE_LIBXDG #include "private/xdgiconproxyengine_p.h" #else #include #include #include #endif #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE DCORE_USE_NAMESPACE static inline QString joinPath(const QString &basePath, const QString &path) { if (path.isEmpty()) return basePath; return basePath + QDir::separator() + path; } static inline QStringList systemDciThemePaths() { QStringList paths; const auto dataPaths = DStandardPaths::paths(DStandardPaths::DSG::DataDir); paths.reserve(dataPaths.size()); for (const auto &dataPath : dataPaths) { paths.push_back(joinPath(dataPath, QLatin1String("icons"))); } return paths; } static inline QString applicationDciThemePath() { return QLatin1String(":/dsg/icons"); } static inline QString applicationBuiltInIconPath() { return QLatin1String(":/dsg/built-in-icons"); } static QString findDciIconFromPath(const QString &iconName, const QString &themeName, const QString path) { if (path.isEmpty() || iconName.isEmpty()) return nullptr; QString themePath = joinPath(path, themeName); QFileInfo themeInfo(themePath); if (!themeInfo.exists() || !themeInfo.isDir()) return nullptr; /* * iconName has two types, like as: * 1. example.dci * 2. org.deepin.app/example.dci * * We do not need to consider the icon name, * just whether the file exists. */ QString iconNameWithSuffix(iconName); // Focus that the icon name can not contain the dci suffix. iconNameWithSuffix += QLatin1String(".dci"); QString iconPath = joinPath(themePath, iconNameWithSuffix); if (!QDir::cleanPath(iconPath).startsWith(QDir::cleanPath(themePath))) // Wrongful return nullptr; QFileInfo iconInfo(iconPath); if (iconInfo.exists() && iconInfo.isFile()) return iconPath; return nullptr; } QIconEngine *DIconTheme::createIconEngine(const QString &iconName, Options options) { return new DIconProxyEngine(iconName, options); } QIcon DIconTheme::findQIcon(const QString &iconName, Options options) { if (QDir::isAbsolutePath(iconName)) { return QIcon(iconName); } auto engine = createIconEngine(iconName, options); // fallback to QIcon::fromTheme if (!options.testFlag(DontFallbackToQIconFromTheme) && !engine) return QIcon::fromTheme(iconName); return QIcon(engine); } QIcon DIconTheme::findQIcon(const QString &iconName, const QIcon &fallback, Options options) { QIcon icon = findQIcon(iconName, options); return !icon.isNull() ? icon : fallback; } bool DIconTheme::isBuiltinIcon(const QIcon &icon) { if (icon.isNull()) return false; QIconEngine *engine = const_cast(icon).data_ptr()->engine; if (auto proxyEngine = dynamic_cast(engine)) return !proxyEngine->proxyKey().compare("DBuiltinIconEngine"); return dynamic_cast(engine); } bool DIconTheme::isXdgIcon(const QIcon &icon) { if (icon.isNull()) return false; #ifdef DTK_DISABLE_LIBXDG return false; #else QIconEngine *engine = const_cast(icon).data_ptr()->engine; if (auto proxyEngine = dynamic_cast(engine)) return !proxyEngine->proxyKey().compare("XdgIconProxyEngine"); return dynamic_cast(engine); #endif } class DIconTheme::CachedData { public: QCache cache; QCache dciIconPathCache; }; DIconTheme::Cached::Cached() : data(new CachedData()) { } DIconTheme::Cached::~Cached() { delete data; } int DIconTheme::Cached::maxCost() const { return data->cache.maxCost(); } void DIconTheme::Cached::setMaxCost(int cost) { data->cache.setMaxCost(cost); data->dciIconPathCache.setMaxCost(cost); } void DIconTheme::Cached::clear() { data->cache.clear(); data->dciIconPathCache.clear(); } QIcon DIconTheme::Cached::findQIcon(const QString &iconName, Options options, const QIcon &fallback) { const QString themeName = QIcon::themeName(); const QString cacheKey = themeName + QChar('/') + iconName + QChar('/') + QString::number(static_cast(options)); if (data->cache.contains(cacheKey)) { auto cacheIcon = data->cache.object(cacheKey); if (cacheIcon->isNull()) return fallback; return *cacheIcon; } auto newIcon = new QIcon(DIconTheme::findQIcon(iconName, options)); if (newIcon->isNull()) { return fallback; } else { data->cache.insert(cacheKey, newIcon); } return *newIcon; } QString DIconTheme::Cached::findDciIconFile(const QString &iconName, const QString &themeName, const QString &fallback) { const QString cacheKey = themeName + QLatin1Char('/') + iconName; if (data->dciIconPathCache.contains(cacheKey)) { const QString *cachePath = data->dciIconPathCache.object(cacheKey); if (cachePath->isEmpty()) return fallback; return *cachePath; } QString *path = new QString(DIconTheme::findDciIconFile(iconName, themeName)); data->dciIconPathCache.insert(cacheKey, path); if (path->isEmpty()) return fallback; return *path; } static inline QStringList getDciThemePaths() { QStringList paths = systemDciThemePaths(); paths.push_back(applicationDciThemePath()); return paths; } Q_GLOBAL_STATIC(DIconTheme::Cached, _globalCache) Q_GLOBAL_STATIC_WITH_ARGS(QStringList, _dciThemePath, (getDciThemePaths())) static void cleanGlobalCache() { if (_globalCache.exists()) _globalCache->clear(); } DIconTheme::Cached *DIconTheme::cached() { if (Q_UNLIKELY(!_globalCache.exists() && !_globalCache.isDestroyed())) { qAddPostRoutine(cleanGlobalCache); } return _globalCache(); } QString DIconTheme::findDciIconFile(const QString &iconName, const QString &themeName) { if (iconName.isEmpty()) return nullptr; const QString cleanIconName = QDir::cleanPath(iconName); if (iconName.startsWith('/') || iconName.endsWith('/') || cleanIconName.length() != iconName.length() || cleanIconName.startsWith("../")) // Wrongful return nullptr; const int splitCharPos = iconName.lastIndexOf('/'); QString effectiveIconName = iconName; // If the icon name syntax is "AAA/BBB", then the "AAA" is the icon group name, the "BBB" is the actual icon // name. eg: "org.deepin.app/accounts", hypothesis the icon search path is "/usr/share/dsg/icons" and // icon theme name is "theme_name", then the icon files list for find is: // "/usr/share/dsg/icons/theme_name/org.deepin.app/accounts.dci" // "qrc:/dsg/icons/theme_name/org.deepin.app/accounts.dci" // fallback to the qrc directory // "/usr/share/dsg/icons/theme_name/accounts.dci" // ignore the icon group name // "qrc:/dsg/icons/theme_name/accounts.dci" // ignore the icon group name // "/usr/share/dsg/icons/accounts.dci" // ignore the icon theme // "qrc:/dsg/icons/accounts.dci" // ignore the icon theme // "qrc:/dsg/built-in-icons/accounts.dci" // fallback to built-in icons const auto &searchPaths = DIconTheme::dciThemeSearchPaths(); for (const QString &themePath : searchPaths) { QString iconPath = findDciIconFromPath(effectiveIconName, themeName, themePath); if (!iconPath.isEmpty()) return iconPath; } if (splitCharPos > 0) { effectiveIconName = iconName.mid(splitCharPos + 1); Q_ASSERT(!effectiveIconName.isEmpty()); for (const QString &themePath : searchPaths) { QString iconPath = findDciIconFromPath(effectiveIconName, themeName, themePath); if (!iconPath.isEmpty()) return iconPath; } } // fallback to without theme directory for (const QString &themePath : searchPaths) { QString iconPath = findDciIconFromPath(effectiveIconName, nullptr, themePath); if (!iconPath.isEmpty()) return iconPath; } return findDciIconFromPath(effectiveIconName, nullptr, applicationBuiltInIconPath()); } QStringList DIconTheme::dciThemeSearchPaths() { return *_dciThemePath; } void DIconTheme::setDciThemeSearchPaths(const QStringList &path) { *_dciThemePath = path; } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dimagehandler.cpp000066400000000000000000001306011522615413000201410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dimagehandler.h" #include "private/dimagehandlerlibs_p.h" #include #include #include #include #include #include #include #include #define SAVE_QUAITY_VALUE 100 struct SupportFormats { QHash freeImageFormats; QHash movieFormats; QStringList libRawFormats; QStringList qtSupportFormats; QStringList saveableFormats; QStringList qtRotatableFormats; QStringList supportFormats; SupportFormats(); }; Q_GLOBAL_STATIC(SupportFormats, SupportFormatsInstance) #ifndef DTK_DISABLE_EX_IMAGE_FORMAT Q_GLOBAL_STATIC(DLibFreeImage, DLibFreeImageInstance) Q_GLOBAL_STATIC(DLibRaw, DLibRawInstance) #endif SupportFormats::SupportFormats() { #ifndef DTK_DISABLE_EX_IMAGE_FORMAT // LibFreeImage support formats freeImageFormats["BMP"] = FIF_BMP; freeImageFormats["ICO"] = FIF_ICO; freeImageFormats["JPG"] = FIF_JPEG; freeImageFormats["JPE"] = FIF_JPEG; freeImageFormats["JPS"] = FIF_JPEG; freeImageFormats["JPEG"] = FIF_JPEG; freeImageFormats["JNG"] = FIF_JNG; freeImageFormats["KOALA"] = FIF_KOALA; freeImageFormats["KOA"] = FIF_KOALA; freeImageFormats["LBM"] = FIF_LBM; freeImageFormats["IFF"] = FIF_LBM; freeImageFormats["MNG"] = FIF_MNG; freeImageFormats["PBM"] = FIF_PBM; freeImageFormats["PBMRAW"] = FIF_PBMRAW; freeImageFormats["PCD"] = FIF_PCD; freeImageFormats["PCX"] = FIF_PCX; freeImageFormats["PGM"] = FIF_PGM; freeImageFormats["PGMRAW"] = FIF_PGMRAW; freeImageFormats["PNG"] = FIF_PNG; freeImageFormats["PPM"] = FIF_PPM; freeImageFormats["PPMRAW"] = FIF_PPMRAW; freeImageFormats["RAS"] = FIF_RAS; freeImageFormats["TGA"] = FIF_TARGA; freeImageFormats["TARGA"] = FIF_TARGA; freeImageFormats["TIFF"] = FIF_TIFF; freeImageFormats["TIF"] = FIF_TIFF; freeImageFormats["WBMP"] = FIF_WBMP; freeImageFormats["PSD"] = FIF_PSD; freeImageFormats["CUT"] = FIF_CUT; freeImageFormats["XBM"] = FIF_XBM; freeImageFormats["XPM"] = FIF_XPM; freeImageFormats["DDS"] = FIF_DDS; freeImageFormats["GIF"] = FIF_GIF; // Warning: Build fails in arch linux. // In libfreeimage.h from arch linux freeimage3.18.0-15 package: // The G3 fax format plugin is deliberately disabled in the Fedora build of // FreeImage as it requires that FreeImage uses a private copy of libtiff // which is a no no because of security reasons. # if 0 freeImageFormats["FAX"] = FIF_FAXG3; freeImageFormats["G3"] = FIF_FAXG3; # endif freeImageFormats["SGI"] = FIF_SGI; freeImageFormats["EXR"] = FIF_EXR; freeImageFormats["PCT"] = FIF_PICT; freeImageFormats["PIC"] = FIF_PICT; freeImageFormats["PICT"] = FIF_PICT; freeImageFormats["PIC"] = FIF_PICT; freeImageFormats["WEBP"] = FIF_WEBP; freeImageFormats["JXR"] = FIF_JXR; movieFormats["MNG"] = FIF_MNG; movieFormats["GIF"] = FIF_GIF; movieFormats["WEBP"] = FIF_WEBP; // LibRaw support images libRawFormats << "CR2" << "CRW" << "DCR" << "KDC" << "MRW" << "NEF" << "ORF" << "PEF" << "RAF" << "SRF" << "DNG" << "RAW"; #endif // For some formats, Qt will support after loading image plugins. QList qtReadableFormats = QImageReader::supportedImageFormats(); for (QByteArray &format : qtReadableFormats) { qtSupportFormats << QString::fromUtf8(format).toUpper(); } // Qt support formats internal. qtSupportFormats << "PNM" << "MEF" << "PXM"; saveableFormats << "BMP" << "JPG" << "JPEG" << "JPS" << "JPE" << "PNG" << "PGM" << "PPM" << "PNM" << "TGA" << "XPM" << "ICO" << "JNG" #ifndef ISSW_64 << "WBMP" #endif << "RAS"; // For those formats, Qt process faster than FreeImage. qtRotatableFormats << "ICNS" << "JPG" << "JPEG" << "PNG" << "BMP"; QSet formats; #ifndef DTK_DISABLE_EX_IMAGE_FORMAT // Check libFreeImage load succeeded. if (DLibFreeImageInstance()->isValid()) { // Use FreeImage load .pcx image. qtSupportFormats.removeAll("PCX"); for (auto itr = freeImageFormats.begin(); itr != freeImageFormats.end(); ++itr) { formats.insert(itr.key()); } for (auto itr = movieFormats.begin(); itr != movieFormats.end(); ++itr) { formats.insert(itr.key()); } } // Add libRaw support formats. if (DLibRawInstance()->isValid()) { for (const QString &format : libRawFormats) { formats.insert(format); } } #endif if (formats.isEmpty()) { supportFormats = qtSupportFormats; } else { // Add qt default support formats. for (const QString &format : qtSupportFormats) { formats.insert(format); } supportFormats = formats.values(); } } DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE #ifndef DTK_DISABLE_EX_IMAGE_FORMAT QString detectImageFormatInternal(const QString &fileName, FREE_IMAGE_FORMAT &format); #else QString detectImageFormatInternal(const QString &fileName); #endif class DImageHandlerPrivate : public DObjectPrivate { D_DECLARE_PUBLIC(DImageHandler) public: enum ImageOption { Readable = 0x1, Wirteable = 0x2, Rotatable = 0x4, SupportFreeImage = 0x8 }; Q_DECLARE_FLAGS(ImageOptions, ImageOption); explicit DImageHandlerPrivate(DImageHandler *qq); bool formatReadable(const QString &fileFormat) const; bool formatWriteable(const QString &fileFormat) const; bool loadStaticImageFromFile(const QString &fileName, QImage &image); #ifndef DTK_DISABLE_EX_IMAGE_FORMAT bool loadImageWithFreeImage(const QString &fileName, QImage &image, FREE_IMAGE_FORMAT fifForamt, QString fileFormat); #endif bool rotateImageFile(const QString &fileName, int angle); bool rotateImage(QImage &image, int angle); void adjustImageToRealOrientation(QImage &image, ExifImageOrientation orientation); QString fileName; ImageOptions options; QImage cachedImage; QString cachedFormat; QString lastError; }; Q_DECLARE_OPERATORS_FOR_FLAGS(DImageHandlerPrivate::ImageOptions) DImageHandlerPrivate::DImageHandlerPrivate(DImageHandler *qq) : DObjectPrivate(qq) { } bool DImageHandlerPrivate::formatReadable(const QString &fileFormat) const { if (fileFormat.isEmpty()) { return false; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT if (DLibFreeImageInstance()->isValid()) { if (SupportFormatsInstance()->supportFormats.contains(fileFormat)) { return true; } } #endif return SupportFormatsInstance()->supportFormats.contains(fileFormat); } bool DImageHandlerPrivate::formatWriteable(const QString &fileFormat) const { if (fileFormat.isEmpty()) { return false; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT if (DLibFreeImageInstance()->isValid()) { if (SupportFormatsInstance()->saveableFormats.contains(fileFormat)) { return true; } } #endif return SupportFormatsInstance()->saveableFormats.contains(fileFormat); } bool DImageHandlerPrivate::loadStaticImageFromFile(const QString &fileName, QImage &image) { D_Q(DImageHandler); QFileInfo fileInfo(fileName); if (0 == fileInfo.size()) { lastError = QString("Error file!"); return false; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT FREE_IMAGE_FORMAT fifFormat = FIF_UNKNOWN; QString fileFormat = detectImageFormatInternal(fileName, fifFormat); if (DLibFreeImageInstance()->isValid()) { // Using free image meta type. QHash dataMap = DLibFreeImageInstance()->findAllMetaData(fileName); fileFormat = dataMap.value("FileFormat").toUpper(); } // For some formats, need use Qt image reader load, to aviod some errors on different hardware architectures. bool usingQImage = ((FIF_PICT == fifFormat) && ("PCT" != fileFormat)); if (usingQImage || SupportFormatsInstance()->qtSupportFormats.contains(fileFormat)) { #else QString fileFormat = detectImageFormatInternal(fileName); #endif QImageReader reader(fileName); reader.setAutoTransform(true); if (reader.imageCount() > 0 || "ICNS" != fileFormat) { image = reader.read(); if (!image.isNull()) { return true; } else { // Try loading image with a forced format. reader.setFormat(fileFormat.toLower().toUtf8()); image = reader.read(); if (!image.isNull()) { return true; #ifndef DTK_DISABLE_EX_IMAGE_FORMAT } else if (DLibFreeImageInstance()->isValid() && DLibFreeImageInstance()->FreeImage_FIFSupportsReading(fifFormat)) { // Try load with FreeImage. return loadImageWithFreeImage(fileName, image, fifFormat, fileFormat); #endif } else { lastError = QString("Load image by qt failed, %1, use format: %2").arg(reader.errorString()).arg(fileFormat); return false; } } } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT } else if (SupportFormatsInstance()->libRawFormats.contains(fileFormat) && DLibRawInstance()->isValid()) { // Use libRaw load. image = DLibRawInstance()->loadImage(fileName, lastError); return !image.isNull(); } else if (DLibFreeImageInstance()->isValid()) { // Use FreeImage load. return loadImageWithFreeImage(fileName, image, fifFormat, fileFormat); } #endif lastError = QString("Unsupport image format: %1").arg(fileFormat); return false; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT bool DImageHandlerPrivate::loadImageWithFreeImage(const QString &fileName, QImage &image, FREE_IMAGE_FORMAT fifFormat, QString fileFormat) { if (!DLibFreeImageInstance()->isValid()) { return false; } if (FIF_UNKNOWN != fifFormat || SupportFormatsInstance()->freeImageFormats.contains(fileFormat)) { if (FIF_UNKNOWN == fifFormat) { fifFormat = FREE_IMAGE_FORMAT(SupportFormatsInstance()->freeImageFormats.value(fileFormat, FIF_UNKNOWN)); } static const int MAX_JP2_SUPPORT_SIZE = 40960000; if (FIF_JP2 == fifFormat && QFileInfo(fileName).size() > MAX_JP2_SUPPORT_SIZE) { lastError = QString("Load image failed, JP2 image size to big, format: %1").arg(fileFormat); return false; } FIBITMAP *dib = DLibFreeImageInstance()->FreeImage_Load(fifFormat, fileName.toUtf8().data(), 0); if (!dib) { lastError = QString("Load image failed, format: %1").arg(fileFormat); return false; } image = DLibFreeImageInstance()->FIBITMAPToQImage(dib); if (image.isNull()) { DLibFreeImageInstance()->FreeImage_Unload(dib); lastError = QString("Convert to QImage failed: %1").arg(fileFormat); return false; } DLibFreeImageInstance()->FreeImage_Unload(dib); return true; } lastError = QString("Unsupport image format: %1").arg(fileFormat); return false; } #endif bool DImageHandlerPrivate::rotateImageFile(const QString &fileName, int angle) { D_Q(DImageHandler); if (0 != (angle % 90)) { lastError = QString("Unsupported angle."); return false; } QString format = q->detectImageFormat(fileName); if (SupportFormatsInstance()->qtRotatableFormats.contains(format)) { QImage image(fileName); #ifndef DTK_DISABLE_EX_IMAGE_FORMAT // Some image formats support use EXIF info store orientation info. if (DLibFreeImageInstance()->isValid()) { // Using libFreeImage to get EXIF information. ExifImageOrientation orientation = DLibFreeImageInstance()->imageOrientation(fileName); adjustImageToRealOrientation(image, orientation); } #endif if (rotateImage(image, angle)) { image.save(fileName, format.toLatin1().data(), SAVE_QUAITY_VALUE); return true; } return false; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT if (DLibFreeImageInstance()->isValid()) { return DLibFreeImageInstance()->rotateImageFile(fileName, angle, lastError); } #endif lastError = QString("Unsupported format: %1").arg(format); return false; } bool DImageHandlerPrivate::rotateImage(QImage &image, int angle) { if (image.isNull()) { lastError = QString("Image is null."); return false; } if (0 != (angle % 90)) { lastError = QString("Rotate angle not base of 90, angle: %1").arg(angle); return false; } QImage imageCopy(image); if (!imageCopy.isNull()) { QTransform rotateMatrix; rotateMatrix.rotate(angle); image = imageCopy.transformed(rotateMatrix, Qt::SmoothTransformation); return true; } lastError = QString("Image is null."); return false; } void DImageHandlerPrivate::adjustImageToRealOrientation(QImage &image, ExifImageOrientation orientation) { switch (orientation) { // TopLeft unnecessary rotate/flip case TopRight: // Horizontal flip image = image.mirrored(true, false); break; case BottomRight: rotateImage(image, 180); break; case BottomLeft: // Vertical flip image = image.mirrored(false, true); break; case LeftTop: // Clockwise 90 degrees and horizontal flip rotateImage(image, 90); image = image.mirrored(true, false); break; case RightTop: rotateImage(image, 90); break; case RightBottom: // Clockwise 90 degrees and vertical flip rotateImage(image, 90); image = image.mirrored(false, true); break; case LeftBottom: // Counterclockwise 90 degrees rotateImage(image, -90); break; default: break; } } DImageHandler::DImageHandler(QObject *parent) : QObject(parent) , DObject(*new DImageHandlerPrivate(this)) { } DImageHandler::~DImageHandler() {} void DImageHandler::setFileName(const QString &fileName) { D_D(DImageHandler); if (fileName == d->fileName) { return; } d->fileName = fileName; d->options &= 0; clearCache(); if (!d->fileName.isEmpty()) { d->cachedFormat = detectImageFormat(fileName); d->options.setFlag(DImageHandlerPrivate::Readable, d->formatReadable(d->cachedFormat)); if (d->formatWriteable(d->cachedFormat)) { d->options.setFlag(DImageHandlerPrivate::Wirteable); d->options.setFlag(DImageHandlerPrivate::Rotatable); } } } QString DImageHandler::fileName() const { D_DC(DImageHandler); return d->fileName; } QImage DImageHandler::readImage() { D_D(DImageHandler); if (!isReadable()) { d->lastError = QString("File is not readable"); return QImage(); } if (!d->cachedImage.isNull()) { return d->cachedImage; } d->loadStaticImageFromFile(d->fileName, d->cachedImage); return d->cachedImage; } QImage DImageHandler::thumbnail(const QSize &size, Qt::AspectRatioMode mode) { D_D(DImageHandler); if (d->cachedImage.isNull()) { d->loadStaticImageFromFile(d->fileName, d->cachedImage); } return d->cachedImage.scaled(size, mode); } QString DImageHandler::imageFormat() const { D_DC(DImageHandler); return d->cachedFormat; } QSize DImageHandler::imageSize() { D_D(DImageHandler); if (isReadable() && d->cachedImage.isNull()) { d->loadStaticImageFromFile(d->fileName, d->cachedImage); } return d->cachedImage.size(); } QHash DImageHandler::findAllMetaData() { D_D(DImageHandler); if (!isReadable()) { return {}; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT if (DLibFreeImageInstance()->isValid()) { return DLibFreeImageInstance()->findAllMetaData(d->fileName); } #endif return {}; } bool DImageHandler::saveImage(const QString &fileName, const QString &format) { D_D(DImageHandler); if (d->cachedImage.isNull()) { if (!d->loadStaticImageFromFile(d->fileName, d->cachedImage)) { return false; } } return saveImage(d->cachedImage, fileName, format); } bool DImageHandler::saveImage(const QImage &image, const QString &fileName, const QString &format) { D_D(DImageHandler); QString realFormat = format.toUpper(); if (realFormat.isEmpty()) { // Detect save file format. #ifndef DTK_DISABLE_EX_IMAGE_FORMAT FREE_IMAGE_FORMAT fifFormat = FIF_UNKNOWN; realFormat = detectImageFormatInternal(fileName, fifFormat); if (FIF_UNKNOWN != fifFormat) { realFormat = SupportFormatsInstance()->freeImageFormats.key(fifFormat); } #else realFormat = detectImageFormatInternal(fileName); #endif } if (!SupportFormatsInstance()->saveableFormats.contains(realFormat.toUpper())) { d->lastError = QString("Unsupport image save format: %1").arg(realFormat); return false; } if (!image.save(fileName, realFormat.toUtf8().data(), SAVE_QUAITY_VALUE)) { d->lastError = QString("Save image by qt failed, format: %1").arg(realFormat); return false; } return true; } bool DImageHandler::rotateImage(QImage &image, int angle) { D_D(DImageHandler); return d->rotateImage(image, angle); } bool DImageHandler::rotateImageFile(const QString &fileName, int angle) { D_D(DImageHandler); return d->rotateImageFile(fileName, angle); } bool DImageHandler::isReadable() const { D_DC(DImageHandler); return d->options.testFlag(DImageHandlerPrivate::Readable); } bool DImageHandler::isWriteable() const { D_DC(DImageHandler); return d->options.testFlag(DImageHandlerPrivate::Wirteable); } bool DImageHandler::isRotatable() const { D_DC(DImageHandler); return d->options.testFlag(DImageHandlerPrivate::Rotatable); } void DImageHandler::clearCache() { D_D(DImageHandler); d->cachedImage = QImage(); d->cachedFormat.clear(); d->lastError.clear(); } QString DImageHandler::lastError() const { return d_func()->lastError; } QStringList DImageHandler::supportFormats() { return SupportFormatsInstance()->supportFormats; } #ifndef DTK_DISABLE_EX_IMAGE_FORMAT QString detectImageFormatInternal(const QString &fileName, FREE_IMAGE_FORMAT &format) #else QString detectImageFormatInternal(const QString &fileName) #endif { QFileInfo info(fileName); QString fileSuffix = info.suffix().toUpper(); QByteArray tempPath = fileName.toUtf8(); #ifndef DTK_DISABLE_EX_IMAGE_FORMAT format = FIF_UNKNOWN; // Check load lib FreeImage succeeded. if (DLibFreeImageInstance()->isValid()) { format = DLibFreeImageInstance()->FreeImage_GetFileType(tempPath.data(), 0); if (FIF_UNKNOWN != format && format != SupportFormatsInstance()->freeImageFormats[fileSuffix]) { // Some format don't load with FreeImage. QString fifFileFormat = SupportFormatsInstance()->freeImageFormats.key(format); if (!fifFileFormat.isEmpty()) { fileSuffix = fifFileFormat; } } if (format == FIF_TIFF) { fileSuffix = "TIFF"; } } #endif if (fileSuffix.isEmpty()) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) { return QString(""); } const QByteArray data = file.read(64); // Check bmp file. if (data.startsWith("BM")) { return "BMP"; } // Check dds file. if (data.startsWith("DDS")) { return "DDS"; } // Check gif file. if (data.startsWith("GIF8")) { return "GIF"; } // Check Max OS icons file. if (data.startsWith("icns")) { return "ICNS"; } // Check jpeg file. if (data.startsWith("\xff\xd8")) { return "JPG"; } // Check mng file. if (data.startsWith("\x8a\x4d\x4e\x47\x0d\x0a\x1a\x0a")) { return "MNG"; } // Check net pbm file (BitMap). if (data.startsWith("P1") || data.startsWith("P4")) { return "PBM"; } // Check pgm file (GrayMap). if (data.startsWith("P2") || data.startsWith("P5")) { return "PGM"; } // Check ppm file (PixMap). if (data.startsWith("P3") || data.startsWith("P6")) { return "PPM"; } // Check png file. if (data.startsWith("\x89PNG\x0d\x0a\x1a\x0a")) { return "PNG"; } // Check svg file. if (data.indexOf(" -1) { return "SVG"; } // Check tiff file. if (data.startsWith("MM\x00\x2a") || data.startsWith("II\x2a\x00")) { // big-endian, little-endian. return "TIFF"; } // Check webp file. if (data.startsWith("RIFFr\x00\x00\x00WEBPVP")) { return "WEBP"; } // Check xbm file. if (data.indexOf("#define max_width ") > -1 && data.indexOf("#define max_height ") > -1) { return "XBM"; } // Check xpm file. if (data.startsWith("/* XPM */")) { return "XPM"; } return QString(""); } return fileSuffix; } QString DImageHandler::detectImageFormat(const QString &fileName) { #ifndef DTK_DISABLE_EX_IMAGE_FORMAT FREE_IMAGE_FORMAT format = FIF_UNKNOWN; return detectImageFormatInternal(fileName, format); #else return detectImageFormatInternal(fileName); #endif } QImage DImageHandler::oldColorFilter(const QImage &img) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { float r = 0.393 * rgb[i * 3] + 0.769 * rgb[i * 3 + 1] + 0.189 * rgb[i * 3 + 2]; float g = 0.349 * rgb[i * 3] + 0.686 * rgb[i * 3 + 1] + 0.168 * rgb[i * 3 + 2]; float b = 0.272 * rgb[i * 3] + 0.534 * rgb[i * 3 + 1] + 0.131 * rgb[i * 3 + 2]; r = qBound(0, r, 255.0); g = qBound(0, g, 255.0); b = qBound(0, b, 255.0); rgb[i * 3] = r; rgb[i * 3 + 1] = g; rgb[i * 3 + 2] = b; } return imgCopy; } QImage DImageHandler::warmColorFilter(const QImage &img, int intensity) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } QColor frontColor; int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int r = rgb[i * 3] + intensity; int g = rgb[i * 3 + 1] + intensity; int b = rgb[i * 3 + 2]; rgb[i * 3] = r > 255 ? 255 : r; rgb[i * 3 + 1] = g > 255 ? 255 : g; rgb[i * 3 + 2] = b > 255 ? 255 : b; } return imgCopy; } QImage DImageHandler::coolColorFilter(const QImage &img, int intensity) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } QColor frontColor; int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int r = rgb[i * 3]; int g = rgb[i * 3 + 1]; int b = rgb[i * 3 + 2] + intensity; rgb[i * 3] = r > 255 ? 255 : r; rgb[i * 3 + 1] = g > 255 ? 255 : g; rgb[i * 3 + 2] = b > 255 ? 255 : b; } return imgCopy; } QImage DImageHandler::grayScaleColorFilter(const QImage &img) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } QColor frontColor; int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int average = (rgb[i * 3] + rgb[i * 3 + 1] + rgb[i * 3 + 2]) / 3; rgb[i * 3] = average > 255 ? 255 : average; rgb[i * 3 + 1] = average > 255 ? 255 : average; rgb[i * 3 + 2] = average > 255 ? 255 : average; } return imgCopy; } QImage DImageHandler::antiColorFilter(const QImage &img) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { rgb[i * 3] = 255 - rgb[i * 3]; rgb[i * 3 + 1] = 255 - rgb[i * 3 + 1]; rgb[i * 3 + 2] = 255 - rgb[i * 3 + 2]; } return imgCopy; } QImage DImageHandler::metalColorFilter(const QImage &img) { QImage baseImage = QImage(img); QImage darkImage = DImageHandler::changeBrightness(img, -100); QImage greyImage = DImageHandler::grayScale(darkImage); QPainter painter; QImage newImage = baseImage.scaled(QSize(img.width(), img.height())); painter.begin(&newImage); painter.setOpacity(0.5); painter.drawImage(0, 0, greyImage); painter.end(); return newImage; } QImage DImageHandler::bilateralFilter(const QImage &img, double spatialDecay, double photometricStandardDeviation) { QImage imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); double c = -0.5 / (photometricStandardDeviation * photometricStandardDeviation); double mu = spatialDecay / (2 - spatialDecay); double *exptable = new double[256]; double *g_table = new double[256]; #pragma omp parallel for for (int i = 0; i <= 255; i++) { exptable[i] = (1 - spatialDecay) * exp(c * i * i); g_table[i] = mu * i; } int width = img.width(); int height = img.height(); int length = width * height; double *data2Red = new double[length]; double *data2Green = new double[length]; double *data2Blue = new double[length]; int size = imgCopy.width() * imgCopy.height(); uint8_t *rgb = imgCopy.bits(); #pragma omp parallel for for (int i = 0; i < size; i++) { data2Red[i] = rgb[i * 3]; data2Green[i] = rgb[i * 3 + 1]; data2Blue[i] = rgb[i * 3 + 2]; } double *gRed = new double[length]; double *pRed = new double[length]; double *rRed = new double[length]; double *gGreen = new double[length]; double *pGreen = new double[length]; double *rGreen = new double[length]; double *gBlue = new double[length]; double *pBlue = new double[length]; double *rBlue = new double[length]; memcpy(pRed, data2Red, sizeof(double) * length); memcpy(rRed, data2Red, sizeof(double) * length); memcpy(pGreen, data2Green, sizeof(double) * length); memcpy(rGreen, data2Green, sizeof(double) * length); memcpy(pBlue, data2Blue, sizeof(double) * length); memcpy(rBlue, data2Blue, sizeof(double) * length); double rho0 = 1.0 / (2 - spatialDecay); #pragma omp parallel for for (int k2 = 0; k2 < height; ++k2) { int startIndex = k2 * width; double mu2 = 0.0; for (int k = startIndex + 1, K = startIndex + width; k < K; ++k) { int div0Red = fabs(pRed[k] - pRed[k - 1]); mu2 = exptable[div0Red]; pRed[k] = pRed[k - 1] * mu2 + pRed[k] * (1.0 - mu2); int div0Green = fabs(pGreen[k] - pGreen[k - 1]); mu2 = exptable[div0Green]; pGreen[k] = pGreen[k - 1] * mu2 + pGreen[k] * (1.0 - mu2); int div0Blue = fabs(pBlue[k] - pBlue[k - 1]); mu2 = exptable[div0Blue]; pBlue[k] = pBlue[k - 1] * mu2 + pBlue[k] * (1.0 - mu2); } for (int k = startIndex + width - 2; startIndex <= k; --k) { int div0Red = fabs(rRed[k] - rRed[k + 1]); mu2 = exptable[div0Red]; rRed[k] = rRed[k + 1] * mu2 + rRed[k] * (1.0 - mu2); int div0Green = fabs(rGreen[k] - rGreen[k + 1]); mu2 = exptable[div0Green]; rGreen[k] = rGreen[k + 1] * mu2 + rGreen[k] * (1.0 - mu2); int div0Blue = fabs(rBlue[k] - rBlue[k + 1]); mu2 = exptable[div0Blue]; rBlue[k] = rBlue[k + 1] * mu2 + rBlue[k] * (1.0 - mu2); } for (int k = startIndex, K = startIndex + width; k < K; k++) { rRed[k] = (rRed[k] + pRed[k]) * rho0 - g_table[(int)data2Red[k]]; rGreen[k] = (rGreen[k] + pGreen[k]) * rho0 - g_table[(int)data2Green[k]]; rBlue[k] = (rBlue[k] + pBlue[k]) * rho0 - g_table[(int)data2Blue[k]]; } } int m = 0; for (int k2 = 0; k2 < height; k2++) { int n = k2; for (int k1 = 0; k1 < width; k1++) { gRed[n] = rRed[m]; gGreen[n] = rGreen[m]; gBlue[n] = rBlue[m]; m++; n += height; } } memcpy(pRed, gRed, sizeof(double) * height * width); memcpy(rRed, gRed, sizeof(double) * height * width); memcpy(pGreen, gGreen, sizeof(double) * height * width); memcpy(rGreen, gGreen, sizeof(double) * height * width); memcpy(pBlue, gBlue, sizeof(double) * height * width); memcpy(rBlue, gBlue, sizeof(double) * height * width); #pragma omp parallel for for (int k1 = 0; k1 < width; ++k1) { int startIndex = k1 * height; double mu1 = 0.0; for (int k = startIndex + 1, K = startIndex + height; k < K; ++k) { int div0Red = fabs(pRed[k] - pRed[k - 1]); mu1 = exptable[div0Red]; pRed[k] = pRed[k - 1] * mu1 + pRed[k] * (1.0 - mu1); int div0Green = fabs(pGreen[k] - pGreen[k - 1]); mu1 = exptable[div0Green]; pGreen[k] = pGreen[k - 1] * mu1 + pGreen[k] * (1.0 - mu1); int div0Blue = fabs(pBlue[k] - pBlue[k - 1]); mu1 = exptable[div0Blue]; pBlue[k] = pBlue[k - 1] * mu1 + pBlue[k] * (1.0 - mu1); } for (int k = startIndex + height - 2; startIndex <= k; --k) { int div0Red = fabs(rRed[k] - rRed[k + 1]); mu1 = exptable[div0Red]; rRed[k] = rRed[k + 1] * mu1 + rRed[k] * (1.0 - mu1); int div0Green = fabs(rGreen[k] - rGreen[k + 1]); mu1 = exptable[div0Green]; rGreen[k] = rGreen[k + 1] * mu1 + rGreen[k] * (1.0 - mu1); int div0Blue = fabs(rBlue[k] - rBlue[k + 1]); mu1 = exptable[div0Blue]; rBlue[k] = rBlue[k + 1] * mu1 + rBlue[k] * (1.0 - mu1); } } double init_gain_mu = spatialDecay / (2 - spatialDecay); #pragma omp parallel for for (int k = 0; k < length; ++k) { rRed[k] = (rRed[k] + pRed[k]) * rho0 - gRed[k] * init_gain_mu; rGreen[k] = (rGreen[k] + pGreen[k]) * rho0 - gGreen[k] * init_gain_mu; rBlue[k] = (rBlue[k] + pBlue[k]) * rho0 - gBlue[k] * init_gain_mu; } m = 0; int nRowBytes = (width * 24 + 31) / 32 * 4; int lineNum_24 = 0; for (int k1 = 0; k1 < width; ++k1) { int n = k1; for (int k2 = 0; k2 < height; ++k2) { data2Red[n] = rRed[m]; data2Green[n] = rGreen[m]; data2Blue[n] = rBlue[m]; lineNum_24 = k2 * nRowBytes; rgb[lineNum_24 + k1 * 3] = data2Red[n]; rgb[lineNum_24 + k1 * 3 + 1] = data2Green[n]; rgb[lineNum_24 + k1 * 3 + 2] = data2Blue[n]; m++; n += width; } } delete[] data2Red; data2Red = nullptr; delete[] data2Green; data2Green = nullptr; delete[] data2Blue; data2Blue = nullptr; delete[] pRed; pRed = nullptr; delete[] rRed; rRed = nullptr; delete[] gRed; gRed = nullptr; delete[] pGreen; pGreen = nullptr; delete[] rGreen; rGreen = nullptr; delete[] gGreen; gGreen = nullptr; delete[] pBlue; pBlue = nullptr; delete[] rBlue; rBlue = nullptr; delete[] gBlue; gBlue = nullptr; delete[] exptable; exptable = nullptr; delete[] g_table; g_table = nullptr; return imgCopy; } QImage DImageHandler::contourExtraction(const QImage &img) { int width = img.width(); int height = img.height(); QImage binImg = binaryzation(img); QImage newImg = QImage(width, height, QImage::Format_RGB888); newImg.fill(Qt::white); uint8_t *rgb = newImg.bits(); uint8_t *binrgb = binImg.bits(); int nRowBytes = (width * 24 + 31) / 32 * 4; #pragma omp parallel for for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { int pixel[8]; memset(pixel, 0, 8 * sizeof(int)); int lineNum_24 = y * nRowBytes; if (binrgb[lineNum_24 + x * 3] == 0) { rgb[lineNum_24 + x * 3] = 0; rgb[lineNum_24 + x * 3 + 1] = 0; rgb[lineNum_24 + x * 3 + 2] = 0; pixel[0] = binrgb[(y - 1) * nRowBytes + (x - 1) * 3]; pixel[1] = binrgb[(y)*nRowBytes + (x - 1) * 3]; pixel[2] = binrgb[(y + 1) * nRowBytes + (x - 1) * 3]; pixel[3] = binrgb[(y - 1) * nRowBytes + (x)*3]; pixel[4] = binrgb[(y + 1) * nRowBytes + (x)*3]; pixel[5] = binrgb[(y - 1) * nRowBytes + (x + 1) * 3]; pixel[6] = binrgb[(y)*nRowBytes + (x + 1) * 3]; pixel[7] = binrgb[(y + 1) * nRowBytes + (x + 1) * 3]; if (pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] + pixel[5] + pixel[6] + pixel[7] == 0) { rgb[lineNum_24 + x * 3] = 255; rgb[lineNum_24 + x * 3 + 1] = 255; rgb[lineNum_24 + x * 3 + 2] = 255; } } } } return newImg; } QImage DImageHandler::binaryzation(const QImage &img) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int gray = (rgb[i * 3] + rgb[i * 3 + 1] + rgb[i * 3 + 2]) / 3; int newGray = 0; if (gray > 128) newGray = 255; else newGray = 0; rgb[i * 3] = newGray; rgb[i * 3 + 1] = newGray; rgb[i * 3 + 2] = newGray; } return imgCopy; } QImage DImageHandler::grayScale(const QImage &img) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int average = (rgb[i * 3] * 299 + rgb[i * 3 + 1] * 587 + rgb[i * 3 + 1] * 114 + 500) / 1000; rgb[i * 3] = average; rgb[i * 3 + 1] = average; rgb[i * 3 + 2] = average; } return imgCopy; } QImage DImageHandler::laplaceSharpen(const QImage &img) { QImage imgCopy; int width = img.width(); int height = img.height(); int window[3][3] = {0, -1, 0, -1, 4, -1, 0, -1, 0}; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(width, height, QImage::Format_RGB888); } else { imgCopy = QImage(img); } QImage imgCopyrgbImg = QImage(img).convertToFormat(QImage::Format_RGB888); uint8_t *rgbImg = imgCopyrgbImg.bits(); uint8_t *rgb = imgCopy.bits(); int nRowBytes = (width * 24 + 31) / 32 * 4; #pragma omp parallel for for (int x = 1; x < img.width(); x++) { for (int y = 1; y < img.height(); y++) { int sumR = 0; int sumG = 0; int sumB = 0; int lineNum_24 = 0; for (int m = x - 1; m <= x + 1; m++) for (int n = y - 1; n <= y + 1; n++) { if (m >= 0 && m < width && n < height) { lineNum_24 = n * nRowBytes; sumR += rgbImg[lineNum_24 + m * 3] * window[n - y + 1][m - x + 1]; sumG += rgbImg[lineNum_24 + m * 3 + 1] * window[n - y + 1][m - x + 1]; sumB += rgbImg[lineNum_24 + m * 3 + 2] * window[n - y + 1][m - x + 1]; } } int old_r = rgbImg[lineNum_24 + x * 3]; sumR += old_r; sumR = qBound(0, sumR, 255); int old_g = rgbImg[lineNum_24 + x * 3 + 1]; sumG += old_g; sumG = qBound(0, sumG, 255); int old_b = rgbImg[lineNum_24 + x * 3 + 2]; sumB += old_b; sumB = qBound(0, sumB, 255); lineNum_24 = y * nRowBytes; rgb[lineNum_24 + x * 3] = sumR; rgb[lineNum_24 + x * 3 + 1] = sumG; rgb[lineNum_24 + x * 3 + 2] = sumB; } } return imgCopy; } QImage DImageHandler::sobelEdgeDetector(const QImage &img) { double *Gx = new double[9]; double *Gy = new double[9]; /* Sobel */ Gx[0] = 1.0; Gx[1] = 0.0; Gx[2] = -1.0; Gx[3] = 2.0; Gx[4] = 0.0; Gx[5] = -2.0; Gx[6] = 1.0; Gx[7] = 0.0; Gx[8] = -1.0; Gy[0] = -1.0; Gy[1] = -2.0; Gy[2] = -1.0; Gy[3] = 0.0; Gy[4] = 0.0; Gy[5] = 0.0; Gy[6] = 1.0; Gy[7] = 2.0; Gy[8] = 1.0; QImage grayImage = grayScale(img); int height = grayImage.height(); int width = grayImage.width(); QImage imgCopy = QImage(width, height, QImage::Format_RGB888); uint8_t *rgbImg = grayImage.bits(); uint8_t *rgb = imgCopy.bits(); int nRowBytes = (width * 24 + 31) / 32 * 4; float *sobel_norm = new float[width * height]; float max = 0.0; QColor my_color; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { double value_gx = 0.0; double value_gy = 0.0; for (int k = 0; k < 3; k++) { for (int p = 0; p < 3; p++) { if ((x + 1 + 1 - k < width) && (y + 1 + 1 - p < height)) { int lineNum_24 = (y + 1 + 1 - p) * nRowBytes; value_gx += Gx[p * 3 + k] * rgbImg[lineNum_24 + (x + 1 + 1 - k) * 3]; value_gy += Gy[p * 3 + k] * rgbImg[lineNum_24 + (x + 1 + 1 - k) * 3]; } } sobel_norm[x + y * width] = abs(value_gx) + abs(value_gy); max = sobel_norm[x + y * width] > max ? sobel_norm[x + y * width] : max; } } } for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { my_color.setHsv(0, 0, 255 - int(255.0 * sobel_norm[i + j * width] / max)); int lineNum_24 = j * nRowBytes; rgb[lineNum_24 + i * 3] = my_color.red(); rgb[lineNum_24 + i * 3 + 1] = my_color.green(); rgb[lineNum_24 + i * 3 + 2] = my_color.blue(); } } delete[] sobel_norm; return imgCopy; } QImage DImageHandler::changeLightAndContrast(const QImage &img, int light, int contrast) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int r; int g; int b; r = light * 0.01 * rgb[i * 3] - 150 + contrast; g = light * 0.01 * rgb[i * 3 + 1] - 150 + contrast; b = light * 0.01 * rgb[i * 3 + 2] - 150 + contrast; rgb[i * 3] = qBound(0, r, 255); rgb[i * 3 + 1] = qBound(0, g, 255); rgb[i * 3 + 2] = qBound(0, b, 255); } return imgCopy; } QImage DImageHandler::changeBrightness(const QImage &img, int brightness) { QImage imgCopy; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); int size = img.width() * img.height(); #pragma omp parallel for for (int i = 0; i < size; i++) { int r = rgb[i * 3] + brightness; int g = rgb[i * 3 + 1] + brightness; int b = rgb[i * 3 + 2] + brightness; r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); rgb[i * 3] = r; rgb[i * 3 + 1] = g; rgb[i * 3 + 2] = b; } return imgCopy; } QImage DImageHandler::changeTransparency(const QImage &img, int transparency) { QImage newImage(img.width(), img.height(), QImage::Format_ARGB32); QColor oldColor; int r, g, b; for (int x = 0; x < newImage.width(); x++) { for (int y = 0; y < newImage.height(); y++) { oldColor = QColor(img.pixel(x, y)); r = oldColor.red(); g = oldColor.green(); b = oldColor.blue(); newImage.setPixel(x, y, qRgba(r, g, b, transparency)); } } return newImage; } QImage DImageHandler::changeStauration(const QImage &img, int saturation) { int r, g, b, rgbMin, rgbMax; float k = saturation / 100.0f * 128; int alpha = 0; QImage newImage(img); QColor tmpColor; for (int x = 0; x < newImage.width(); x++) { for (int y = 0; y < newImage.height(); y++) { tmpColor = QColor(img.pixel(x, y)); r = tmpColor.red(); g = tmpColor.green(); b = tmpColor.blue(); rgbMin = qMin(qMin(r, g), b); rgbMax = qMax(qMax(r, g), b); int delta = (rgbMax - rgbMin); int value = (rgbMax + rgbMin); if (delta == 0) { continue; } int L = value >> 1; if (k >= 0) { int S = L < 128 ? (delta << 7) / value : (delta << 7) / (510 - value); alpha = k + S >= 128 ? S : 128 - k; alpha = 128 * 128 / alpha - 128; } else { alpha = k; } r = r + ((r - L) * alpha >> 7); g = g + ((g - L) * alpha >> 7); b = b + ((b - L) * alpha >> 7); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); newImage.setPixel(x, y, qRgb(r, g, b)); } } return newImage; } QImage DImageHandler::replacePointColor(const QImage &img, QColor oldColor, QColor newColor) { QImage imgCopy = img; if (img.format() != QImage::Format_RGB888) { imgCopy = QImage(img).convertToFormat(QImage::Format_RGB888); } else { imgCopy = QImage(img); } uint8_t *rgb = imgCopy.bits(); if (nullptr == rgb) { return QImage(); } QColor frontColor; for (int x = 0; x < img.width(); ++x) { for (int y = 0; y < img.height(); ++y) { if (imgCopy.pixelColor(x, y) == oldColor) { imgCopy.setPixelColor(x, y, newColor); } } } return imgCopy; } QImage DImageHandler::flipHorizontal(const QImage &img) { return img.mirrored(true, false); } QImage DImageHandler::flipVertical(const QImage &img) { return img.mirrored(false, true); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dimagehandlerlibs.cpp000066400000000000000000000445611522615413000210240ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "private/dimagehandlerlibs_p.h" #ifndef DTK_DISABLE_EX_IMAGE_FORMAT #include #include #include #include DLibFreeImage::DLibFreeImage() { freeImage = new QLibrary("freeimage", "3"); if (!freeImage->load()) { delete freeImage; freeImage = nullptr; return; } auto initFunctionError = [this]() { freeImage->unload(); delete freeImage; freeImage = nullptr; }; #define INIT_FUNCTION_FREEIMAGE(Name) \ Name = reinterpret_cast(freeImage->resolve(#Name)); \ if (!Name) { \ initFunctionError(); \ return; \ } INIT_FUNCTION_FREEIMAGE(FreeImage_Load); INIT_FUNCTION_FREEIMAGE(FreeImage_Unload); INIT_FUNCTION_FREEIMAGE(FreeImage_Save); INIT_FUNCTION_FREEIMAGE(FreeImage_FIFSupportsReading); INIT_FUNCTION_FREEIMAGE(FreeImage_GetFileType); INIT_FUNCTION_FREEIMAGE(FreeImage_GetFIFFromFilename); INIT_FUNCTION_FREEIMAGE(FreeImage_GetImageType); INIT_FUNCTION_FREEIMAGE(FreeImage_GetBPP); INIT_FUNCTION_FREEIMAGE(FreeImage_GetWidth); INIT_FUNCTION_FREEIMAGE(FreeImage_GetHeight); INIT_FUNCTION_FREEIMAGE(FreeImage_GetRedMask); INIT_FUNCTION_FREEIMAGE(FreeImage_GetGreenMask); INIT_FUNCTION_FREEIMAGE(FreeImage_GetBlueMask); INIT_FUNCTION_FREEIMAGE(FreeImage_GetThumbnail); INIT_FUNCTION_FREEIMAGE(FreeImage_SetThumbnail); INIT_FUNCTION_FREEIMAGE(FreeImage_ConvertToRawBits); INIT_FUNCTION_FREEIMAGE(FreeImage_GetMetadataCount); INIT_FUNCTION_FREEIMAGE(FreeImage_FindFirstMetadata); INIT_FUNCTION_FREEIMAGE(FreeImage_FindNextMetadata); INIT_FUNCTION_FREEIMAGE(FreeImage_FindCloseMetadata); INIT_FUNCTION_FREEIMAGE(FreeImage_GetTagKey); INIT_FUNCTION_FREEIMAGE(FreeImage_GetTagValue); INIT_FUNCTION_FREEIMAGE(FreeImage_TagToString); INIT_FUNCTION_FREEIMAGE(FreeImage_Rotate); } DLibFreeImage::~DLibFreeImage() { if (freeImage) { delete freeImage; } } bool DLibFreeImage::isValid() { return freeImage; } bool DLibFreeImage::findMetaData(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, QHash &data) { bool ret = false; if (freeImage) { if (FreeImage_GetMetadataCount(model, dib)) { FITAG *tag = nullptr; FIMETADATA *mdhandle = nullptr; mdhandle = FreeImage_FindFirstMetadata(model, dib, &tag); if (mdhandle) { do { QString value; // Warning: FreeImage_TagToString is not thread-safe, add mutex protection. apiMutex.lock(); value = QString(FreeImage_TagToString(model, tag, nullptr)); apiMutex.unlock(); data.insert(FreeImage_GetTagKey(tag), value); ret = true; } while (FreeImage_FindNextMetadata(mdhandle, &tag)); FreeImage_FindCloseMetadata(mdhandle); } } } return ret; } QHash DLibFreeImage::findAllMetaData(const QString &fileName) { FIBITMAP *dib = readFileToFIBITMAP(fileName, FIF_LOAD_NOPIXELS); QHash admMap; for (int i = FIMD_EXIF_MAIN; i <= FIMD_IPTC; ++i) { findMetaData(FREE_IMAGE_MDMODEL(i), dib, admMap); } QFileInfo info(fileName); if (admMap.contains("DateTime")) { // Get first DateTime. QDateTime time = QDateTime::fromString(admMap.value("DateTime"), "yyyy:MM:dd hh:mm:ss"); admMap.insert("DateTimeOriginal", time.toString("yyyy/MM/dd hh:mm")); } else { admMap.insert("DateTimeOriginal", info.lastModified().toString("yyyy/MM/dd HH:mm")); } admMap.insert("DateTimeDigitized", info.lastModified().toString("yyyy/MM/dd HH:mm")); // The value of width and height might incorrect QImageReader reader(fileName); int w = reader.size().width(); w = w > 0 ? w : static_cast(FreeImage_GetWidth(dib)); int h = reader.size().height(); h = h > 0 ? h : static_cast(FreeImage_GetHeight(dib)); admMap.insert("Dimension", QString::number(w) + "x" + QString::number(h)); admMap.insert("FileName", info.fileName()); admMap.insert("FileFormat", info.suffix()); static auto formatDataSize = [](qint64 size) -> QString { static const QStringList suffix = {"B", "KB", "MB", "GB", "TB", "PB"}; int level = 0; double bytes = size; while (bytes >= 1024 && level < (suffix.length() - 1)) { bytes /= 1024; ++level; } return QString("%1%2").arg(bytes, 0, 'f', 1).arg(suffix[level]); }; admMap.insert("FileSize", formatDataSize(info.size())); FreeImage_Unload(dib); return admMap; } FIBITMAP *DLibFreeImage::readFileToFIBITMAP(const QString &fileName, int flags, FREE_IMAGE_FORMAT fif) { QByteArray b = fileName.toUtf8(); const char *pc = b.data(); // Detect file format. if (FIF_UNKNOWN == fif) { fif = FreeImage_GetFileType(pc, 0); if (FIF_UNKNOWN == fif) { fif = FreeImage_GetFIFFromFilename(pc); } } if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { FIBITMAP *dib = FreeImage_Load(fif, pc, flags); return dib; } return nullptr; } bool DLibFreeImage::writeFIBITMAPToFile(FIBITMAP *dib, const QString &fileName, int flags) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; bool bSuccess = false; const QByteArray ba = fileName.toUtf8(); const char *pc = ba.data(); // Try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(pc); FREE_IMAGE_FORMAT realfif = FIF_UNKNOWN; if (fif == FIF_UNKNOWN) { realfif = FreeImage_GetFileType(pc, 0); } if (fif != FIF_UNKNOWN) { bSuccess = FreeImage_Save(fif, dib, pc, flags); } else if (realfif != FIF_UNKNOWN) { bSuccess = FreeImage_Save(realfif, dib, pc, flags); } return bSuccess; } QImage DLibFreeImage::FIBITMAPToQImage(FIBITMAP *dib) const { if (!dib || FreeImage_GetImageType(dib) == FIT_UNKNOWN) return QImage(0, 0, QImage::Format_Invalid); int width = static_cast(FreeImage_GetWidth(dib)); int height = static_cast(FreeImage_GetHeight(dib)); int depth = static_cast(FreeImage_GetBPP(dib)); switch (depth) { case 1: { QImage result(width, height, QImage::Format_Mono); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 1, 0, 0, 0, true); return result; } case 4: { // NOTE: QImage do not support 4-bit, convert it to 8-bit QImage result(width, height, QImage::Format_Indexed8); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 8, 0, 0, 0, true); return result; } case 8: { QImage result(width, height, QImage::Format_Indexed8); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 8, 0, 0, 0, true); return result; } case 16: if ((FreeImage_GetRedMask(dib) == FI16_555_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_555_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_555_BLUE_MASK)) { // 5-5-5 QImage result(width, height, QImage::Format_RGB555); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK, true); return result; } else { // 5-6-5 QImage result(width, height, QImage::Format_RGB16); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK, true); return result; } case 24: { QImage result(width, height, QImage::Format_RGB32); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true); return result; } case 32: { QImage result(width, height, QImage::Format_ARGB32); FreeImage_ConvertToRawBits(result.scanLine(0), dib, result.bytesPerLine(), 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true); return result; } case 48: case 64: case 96: case 128: default: break; } return QImage(0, 0, QImage::Format_Invalid); } ExifImageOrientation DLibFreeImage::imageOrientation(const QString &fileName) { ExifImageOrientation oreintation = Undefined; FIBITMAP *dib = readFileToFIBITMAP(fileName, FIF_LOAD_NOPIXELS); // Metadata may be null sometimes, check if metadata exist. if (0 == FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) { FreeImage_Unload(dib); return oreintation; } FITAG *tag = nullptr; FIMETADATA *mdhandle = nullptr; mdhandle = FreeImage_FindFirstMetadata(FIMD_EXIF_MAIN, dib, &tag); if (mdhandle) { do { if (qstrcmp(FreeImage_GetTagKey(tag), "Orientation") == 0) { oreintation = ExifImageOrientation(*static_cast(FreeImage_GetTagValue(tag))); break; } } while (FreeImage_FindNextMetadata(mdhandle, &tag)); FreeImage_FindCloseMetadata(mdhandle); } FreeImage_Unload(dib); return oreintation; } bool DLibFreeImage::rotateImageFile(const QString &fileName, int angle, QString &errorString) { FIBITMAP *dib = readFileToFIBITMAP(fileName); if (nullptr == dib) { errorString = "Unsupported format"; return false; } FIBITMAP *rotateRes = FreeImage_Rotate(dib, -angle, nullptr); if (rotateRes) { // Regenerate thumbnail if it's exits // Image formats that currently support thumbnail saving are // JPEG (JFIF formats), EXR, TGA and TIFF. if (FreeImage_GetThumbnail(dib)) { FIBITMAP *thumb = FreeImage_GetThumbnail(dib); FIBITMAP *rotateThumb = FreeImage_Rotate(thumb, -angle, nullptr); FreeImage_SetThumbnail(rotateRes, rotateThumb); FreeImage_Unload(rotateThumb); } } FREE_IMAGE_FORMAT f = FreeImage_GetFIFFromFilename(fileName.toUtf8().data()); if (f == FIF_UNKNOWN) { FreeImage_Unload(dib); FreeImage_Unload(rotateRes); errorString = "Rotate image format error"; return false; } if (!writeFIBITMAPToFile(rotateRes, fileName)) { FreeImage_Unload(dib); FreeImage_Unload(rotateRes); errorString = "Rotate image save failed, unknown format"; return false; } FreeImage_Unload(dib); FreeImage_Unload(rotateRes); return true; } DLibRaw::DLibRaw() { libraw = new QLibrary("libraw"); if (!libraw->load()) { delete libraw; libraw = nullptr; return; } auto initFunctionError = [this]() { libraw->unload(); delete libraw; libraw = nullptr; }; #define INIT_FUNCTION_LIBRAW(Name) \ Name = reinterpret_cast(libraw->resolve(#Name)); \ if (!Name) { \ initFunctionError(); \ return; \ } INIT_FUNCTION_LIBRAW(libraw_strerror); INIT_FUNCTION_LIBRAW(libraw_init); INIT_FUNCTION_LIBRAW(libraw_open_file); INIT_FUNCTION_LIBRAW(libraw_open_buffer); INIT_FUNCTION_LIBRAW(libraw_unpack); INIT_FUNCTION_LIBRAW(libraw_unpack_thumb); INIT_FUNCTION_LIBRAW(libraw_close); INIT_FUNCTION_LIBRAW(libraw_dcraw_process); INIT_FUNCTION_LIBRAW(libraw_dcraw_make_mem_image); INIT_FUNCTION_LIBRAW(libraw_dcraw_make_mem_thumb); INIT_FUNCTION_LIBRAW(libraw_dcraw_clear_mem); } DLibRaw::~DLibRaw() { if (libraw) { delete libraw; } } bool DLibRaw::isValid() { return libraw; } QImage DLibRaw::loadImage(const QString &fileName, QString &errString, QSize requestSize) { QImage image; libraw_data_t *rawData = libraw_init(0); if (!rawData) { errString = QStringLiteral("Create new libraw object failed!"); return image; } int ret = libraw_open_file(rawData, fileName.toUtf8().data()); if (LIBRAW_SUCCESS == ret) { ret = readImage(rawData, image, requestSize); } libraw_close(rawData); if (LIBRAW_SUCCESS != ret) { errString = errorString(ret); } return image; } QImage DLibRaw::loadImage(QByteArray &data, QString &errString, QSize requestSize) { QImage image; libraw_data_t *rawData = libraw_init(0); if (!rawData) { errString = QStringLiteral("Create new libraw object failed!"); return image; } int ret = libraw_open_buffer(rawData, reinterpret_cast(data.data()), static_cast(data.size())); if (LIBRAW_SUCCESS == ret) { ret = readImage(rawData, image, requestSize); } libraw_close(rawData); if (LIBRAW_SUCCESS != ret) { errString = errorString(ret); } return image; } int DLibRaw::readImage(libraw_data_t *rawData, QImage &image, QSize requestSize) { if (!rawData) { return LIBRAW_INPUT_CLOSED; } int ret = LIBRAW_UNSPECIFIED_ERROR; int errCode = LIBRAW_SUCCESS; libraw_processed_image_t *output = nullptr; // Try to read thumbnail image if possible. if (!requestSize.isEmpty() && (requestSize.width() < rawData->thumbnail.twidth || requestSize.height() < rawData->thumbnail.theight)) { ret = libraw_unpack_thumb(rawData); if (LIBRAW_SUCCESS == ret) { output = libraw_dcraw_make_mem_thumb(rawData, &errCode); if (LIBRAW_SUCCESS != errCode && output) { libraw_dcraw_clear_mem(output); } } } // Read default image if no thumbnail. if (!output) { ret = libraw_unpack(rawData); if (LIBRAW_SUCCESS != ret) { return ret; } ret = libraw_dcraw_process(rawData); if (LIBRAW_SUCCESS != ret) { return ret; } output = libraw_dcraw_make_mem_image(rawData, &errCode); if (LIBRAW_SUCCESS != errCode) { if (output) { libraw_dcraw_clear_mem(output); } // Can't read data, return. return errCode; } } if (LIBRAW_IMAGE_JPEG == output->type) { image.loadFromData(output->data, static_cast(output->data_size), "JPEG"); if (rawData->sizes.flip) { QTransform rotation; int angle = 0; // Image orientation (0 if does not require rotation; 3 if requires 180-deg rotation; // 5 if 90 deg counterclockwise, 6 if 90 deg clockwise). switch (rawData->sizes.flip) { case 3: angle = 180; break; case 5: angle = -90; break; case 6: angle = 90; break; default: break; } if (angle != 0) { rotation.rotate(angle); image = image.transformed(rotation); } } } else { int numPixels = output->width * output->height; int colorSize = output->bits / 8; int pixelSize = output->colors * colorSize; uchar *pixels = new uchar[numPixels * 4]; uchar *data = output->data; for (int i = 0; i < numPixels; i++, data += pixelSize) { if (output->colors == 3) { pixels[i * 4] = data[2 * colorSize]; pixels[i * 4 + 1] = data[1 * colorSize]; pixels[i * 4 + 2] = data[0]; } else { pixels[i * 4] = data[0]; pixels[i * 4 + 1] = data[0]; pixels[i * 4 + 2] = data[0]; } } // QImage::Format_RGB32 will cause window transparent image = QImage(pixels, output->width, output->height, QImage::Format_RGB32).convertToFormat(QImage::Format_ARGB32); delete[] pixels; } libraw_dcraw_clear_mem(output); return LIBRAW_SUCCESS; } QString DLibRaw::errorString(int errorCode) { return QString(libraw_strerror(errorCode)); } #endif dtkgui-6.7.46/src/util/dprivateaccessor_p.h000066400000000000000000000053661522615413000207130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once #include // Private member accessor using the explicit template instantiation technique. // // C++ Standard [temp.explicit]/12 states: // "The usual access checking rules do not apply to names used to // specify explicit instantiation definitions." // // This allows passing pointers to private/protected data members and // member functions as template arguments in explicit instantiations, // bypassing normal access control — without modifying the class definition // and without the UB caused by "#define private public". // // NOTE: These helper structs must be in the SAME namespace as the Tag structs // (global namespace, since the macros expand at file scope). If they were in a // sub-namespace, the friend definition would create a different function than // the friend declaration in the Tag struct, causing undefined-reference errors. QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wnon-template-friend") template struct DtkGuiPrivateAccessor { using MemberPtr = typename Tag::MemberPtr; friend MemberPtr get(Tag) noexcept; }; template struct DtkGuiPrivateAccessorImpl : DtkGuiPrivateAccessor { friend typename Tag::MemberPtr get(Tag) noexcept { return Ptr; } }; QT_WARNING_POP #define D_DECLARE_PRIVATE_MEMBER(TagName, ClassName, Member, MemberType) \ struct TagName { \ using MemberPtr = MemberType ClassName::*; \ friend MemberPtr get(TagName) noexcept; \ }; \ template struct DtkGuiPrivateAccessorImpl #define D_DECLARE_PRIVATE_METHOD(TagName, ClassName, MethodName, RetType, ...) \ struct TagName { \ using MemberPtr = RetType (ClassName::*)(__VA_ARGS__); \ friend MemberPtr get(TagName) noexcept; \ }; \ template struct DtkGuiPrivateAccessorImpl #define D_DECLARE_PRIVATE_CONST_METHOD(TagName, ClassName, MethodName, RetType, ...) \ struct TagName { \ using MemberPtr = RetType (ClassName::*)(__VA_ARGS__) const; \ friend MemberPtr get(TagName) noexcept; \ }; \ template struct DtkGuiPrivateAccessorImpl // Trampoline: ensures get(tag) is called from a context with no class-scope // get() member that might suppress ADL (C++ [basic.lookup.argdep] para 3). namespace dtk_private_detail { template inline typename Tag::MemberPtr access(Tag t) noexcept { return get(t); } } #define D_PRIVATE_MEMBER(obj, tag) ((obj).*dtk_private_detail::access(tag)) #define D_PRIVATE_CALL(obj, tag, ...) ((obj).*dtk_private_detail::access(tag))(__VA_ARGS__) dtkgui-6.7.46/src/util/dsvgrenderer.cpp000066400000000000000000000265721522615413000200620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DTK_DISABLE_LIBRSVG #include #else #include #endif #include "dsvgrenderer.h" #include "dobject_p.h" #include #include #include #include #include #include DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE #ifndef DTK_DISABLE_LIBRSVG class RSvg { public: RSvg() { // fix found lib was librsvg2-dev without version number rsvg = new QLibrary("rsvg-2", "2"); if (!rsvg->load()) { delete rsvg; rsvg = nullptr; return; } #define INIT_FUNCTION(Name) Name = reinterpret_cast(rsvg->resolve(#Name)); Q_ASSERT(Name) INIT_FUNCTION(cairo_image_surface_create_for_data); INIT_FUNCTION(cairo_create); INIT_FUNCTION(cairo_scale); INIT_FUNCTION(cairo_translate); INIT_FUNCTION(cairo_destroy); INIT_FUNCTION(cairo_surface_destroy); INIT_FUNCTION(g_object_unref); INIT_FUNCTION(rsvg_handle_render_cairo); INIT_FUNCTION(rsvg_handle_render_cairo_sub); INIT_FUNCTION(rsvg_handle_get_dimensions_sub); INIT_FUNCTION(rsvg_handle_get_position_sub); INIT_FUNCTION(rsvg_handle_has_sub); INIT_FUNCTION(rsvg_handle_new_from_data); INIT_FUNCTION(rsvg_handle_get_dimensions); } static RSvg *instance() { static RSvg *global = new RSvg(); return global; } bool isValid() const { return rsvg; } ~RSvg() { if (rsvg) delete rsvg; } cairo_surface_t *(*cairo_image_surface_create_for_data)(unsigned char *data, cairo_format_t format, int width, int height, int stride); cairo_t *(*cairo_create)(cairo_surface_t *target); void (*cairo_scale)(cairo_t *cr, double sx, double sy); void (*cairo_translate)(cairo_t *cr, double tx, double ty); void (*cairo_destroy)(cairo_t *cr); void (*cairo_surface_destroy)(cairo_surface_t *surface); void (*g_object_unref)(gpointer object); gboolean (*rsvg_handle_render_cairo)(RsvgHandle *handle, cairo_t *cr); gboolean (*rsvg_handle_render_cairo_sub)(RsvgHandle *handle, cairo_t *cr, const char *id); gboolean (*rsvg_handle_get_dimensions_sub)(RsvgHandle *handle, RsvgDimensionData *dimension_data, const char *id); gboolean (*rsvg_handle_get_position_sub)(RsvgHandle *handle, RsvgPositionData *position_data, const char *id); gboolean (*rsvg_handle_has_sub)(RsvgHandle *handle, const char *id); RsvgHandle *(*rsvg_handle_new_from_data)(const guint8 *data, gsize data_len, GError **error); void (*rsvg_handle_get_dimensions)(RsvgHandle *handle, RsvgDimensionData *dimension_data); private: QLibrary *rsvg = nullptr; }; #endif class DSvgRendererPrivate : public DObjectPrivate { public: explicit DSvgRendererPrivate(DSvgRenderer *qq); QImage getImage(const QSize &size, const QString &elementId) const; #ifndef DTK_DISABLE_LIBRSVG RsvgHandle *handle = nullptr; QSize defaultSize; mutable QRectF viewBox; #else QSvgRenderer *qRenderer = nullptr; #endif }; DSvgRendererPrivate::DSvgRendererPrivate(DSvgRenderer *qq) : DObjectPrivate(qq) // qq ==> DObject #ifdef DTK_DISABLE_LIBRSVG , qRenderer(new QSvgRenderer(qq)) // qq ==> QObject #endif { } QImage DSvgRendererPrivate::getImage(const QSize &size, const QString &elementId) const { #ifndef DTK_DISABLE_LIBRSVG if (!RSvg::instance()->isValid()) return QImage(); QImage image(size, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); cairo_surface_t *surface = RSvg::instance()->cairo_image_surface_create_for_data(image.bits(), CAIRO_FORMAT_ARGB32, image.width(), image.height(), image.bytesPerLine()); cairo_t *cairo = RSvg::instance()->cairo_create(surface); RSvg::instance()->cairo_scale(cairo, image.width() / viewBox.width(), image.height() / viewBox.height()); RSvg::instance()->cairo_translate(cairo, -viewBox.x(), -viewBox.y()); if (elementId.isEmpty()) RSvg::instance()->rsvg_handle_render_cairo(handle, cairo); else RSvg::instance()->rsvg_handle_render_cairo_sub(handle, cairo, elementId.toUtf8().constData()); RSvg::instance()->cairo_destroy(cairo); RSvg::instance()->cairo_surface_destroy(surface); return image; #else QImage image(size, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter pa(&image); if (elementId.isEmpty()) qRenderer->render(&pa); else qRenderer->render(&pa, elementId); return image; #endif } /*! \class Dtk::Gui::DSvgRenderer \inmodule dtkgui \brief æ��供了将SVG文件的内容绘制到绘制设备上的方法. SVG图形å�¯ä»¥åœ¨æž„造 DSvgRenderer 时加载,也å�¯ä»¥ç¨�å�Žä½¿ç”¨load()函数加载。 因为渲染是使用 QPainter 执行的,所以å�¯ä»¥åœ¨ QPaintDevice 的任何å­�类上渲染SVG图形。 如果加载了有效文件,则无论是在构造时还是以å�ŽæŸ�个时间,isValid()都将返回trueï¼›å�¦åˆ™å°†è¿”回false。 DSvgRendereræ��ä¾›render()æ�’槽,用于使用给定的 QPainter 渲染当å‰�文档或动画文档的当å‰�帧 \note 使用 DSvgRenderer 需è¦� librsvg库 */ DSvgRenderer::DSvgRenderer(QObject *parent) : QObject(parent) , DObject(*new DSvgRendererPrivate(this)) { } DSvgRenderer::DSvgRenderer(const QString &filename, QObject *parent) : DSvgRenderer(parent) { load(filename); } DSvgRenderer::DSvgRenderer(const QByteArray &contents, QObject *parent) : DSvgRenderer(parent) { load(contents); } DSvgRenderer::~DSvgRenderer() { #ifndef DTK_DISABLE_LIBRSVG D_D(DSvgRenderer); if (d->handle) { Q_ASSERT(RSvg::instance()->isValid()); RSvg::instance()->g_object_unref(d->handle); } #endif } bool DSvgRenderer::isValid() const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG return d->handle; #else return d->qRenderer->isValid(); #endif } QSize DSvgRenderer::defaultSize() const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG return d->defaultSize; #else return d->qRenderer->defaultSize(); #endif } QRect DSvgRenderer::viewBox() const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG return d->handle ? d->viewBox.toRect() : QRect(); #else return d->qRenderer->viewBox(); #endif } QRectF DSvgRenderer::viewBoxF() const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG return d->handle ? d->viewBox : QRectF(); #else return d->qRenderer->viewBoxF(); #endif } void DSvgRenderer::setViewBox(const QRect &viewbox) { setViewBox(QRectF(viewbox)); } void DSvgRenderer::setViewBox(const QRectF &viewbox) { D_D(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG if (d->handle) d->viewBox = viewbox; #else return d->qRenderer->setViewBox(viewbox); #endif } QRectF DSvgRenderer::boundsOnElement(const QString &id) const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG if (!d->handle) return QRectF(); const QByteArray &id_data = id.toUtf8(); RsvgDimensionData dimension_data; if (!RSvg::instance()->rsvg_handle_get_dimensions_sub(d->handle, &dimension_data, id_data.constData())) return QRectF(); RsvgPositionData pos_data; if (!RSvg::instance()->rsvg_handle_get_position_sub(d->handle, &pos_data, id_data.constData())) return QRectF(); return QRectF(pos_data.x, pos_data.y, dimension_data.width, dimension_data.height); #else return d->qRenderer->boundsOnElement(id); #endif } bool DSvgRenderer::elementExists(const QString &id) const { D_DC(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG if (!d->handle) return false; return RSvg::instance()->rsvg_handle_has_sub(d->handle, id.toUtf8().constData()); #else return d->qRenderer->elementExists(id); #endif } QImage DSvgRenderer::toImage(const QSize sz, const QString &elementId) const { Q_D(const DSvgRenderer); return d->getImage(sz, elementId); } #ifndef DTK_DISABLE_LIBRSVG static QByteArray updateXmlAttribute(const QString &contents) { QByteArray data; QXmlStreamWriter writer(&data); QXmlStreamReader reader(contents); while(reader.readNext() != QXmlStreamReader::Invalid && !reader.atEnd()) { if (reader.tokenType() != QXmlStreamReader::StartElement || !reader.attributes().hasAttribute("href")) { writer.writeCurrentToken(reader); continue; } for (const auto &nd : reader.namespaceDeclarations()) writer.writeNamespace(nd.namespaceUri().toString(), nd.prefix().toString()); writer.writeStartElement(reader.namespaceUri().toString(), reader.name().toString()); for (const auto &attr : reader.attributes()) { if (attr.name() == QStringLiteral("href")) { writer.writeAttribute("xlink:href", attr.value().toString()); continue; } writer.writeAttribute(attr); } } return data; } static QByteArray format(const QByteArray &contents) { QXmlStreamReader reader(contents); while (reader.readNextStartElement()) { if (reader.attributes().hasAttribute("href")) return updateXmlAttribute(contents); } return contents; } #endif bool DSvgRenderer::load(const QString &filename) { #ifndef DTK_DISABLE_LIBRSVG QFile file(filename); if (file.open(QIODevice::ReadOnly)) { // TODO: if `href` attribute is adapted after librsvg upgrade revert me return load(format(file.readAll())); } return false; #else D_D(DSvgRenderer); return d->qRenderer->load(filename); #endif } bool DSvgRenderer::load(const QByteArray &contents) { D_D(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG if (!RSvg::instance()->isValid()) return false; if (d->handle) { RSvg::instance()->g_object_unref(d->handle); d->handle = nullptr; } GError *error = nullptr; d->handle = RSvg::instance()->rsvg_handle_new_from_data((const guint8*)contents.constData(), contents.length(), &error); if (error) { qWarning("DSvgRenderer::load: %s", error->message); g_error_free(error); return false; } RsvgDimensionData rsvg_data; RSvg::instance()->rsvg_handle_get_dimensions(d->handle, &rsvg_data); d->defaultSize.setWidth(rsvg_data.width); d->defaultSize.setHeight(rsvg_data.height); d->viewBox = QRectF(QPointF(0, 0), d->defaultSize); return true; #else return d->qRenderer->load(contents); #endif } void DSvgRenderer::render(QPainter *p) { #ifndef DTK_DISABLE_LIBRSVG render(p, QString(), QRectF()); #else D_D(DSvgRenderer); d->qRenderer->render(p); #endif } void DSvgRenderer::render(QPainter *p, const QRectF &bounds) { #ifndef DTK_DISABLE_LIBRSVG render(p, QString(), bounds); #else D_D(DSvgRenderer); d->qRenderer->render(p, bounds); #endif } void DSvgRenderer::render(QPainter *p, const QString &elementId, const QRectF &bounds) { D_D(DSvgRenderer); #ifndef DTK_DISABLE_LIBRSVG if (!d->handle) return; p->save(); const QImage image = d->getImage(QSize(p->device()->width(), p->device()->height()), elementId); if (bounds.isEmpty()) p->drawImage(0, 0, image); else p->drawImage(bounds, image); p->restore(); #else d->qRenderer->render(p, elementId, bounds); #endif } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dtaskbarcontrol.cpp000066400000000000000000000104111522615413000205450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dtaskbarcontrol.h" #include #include #include #include #include #include "private/dtaskbarcontrol_p.h" DCORE_USE_NAMESPACE DGUI_BEGIN_NAMESPACE DTaskbarControlPrivate::DTaskbarControlPrivate(DTaskbarControl *q) : DObjectPrivate(q) , m_counter(0) , m_counterVisible(true) , m_progress(0) , m_progressVisible(true) { } DTaskbarControlPrivate::~DTaskbarControlPrivate() { } /*! \class Dtk::Gui::DTaskbarControl \inmodule dtkgui \brief DTaskbarControlæ��供了一个Launcher API接å�£ï¼Œç”¨äºŽæ–¹ä¾¿åº”用程åº�控制taskbar进度æ�¡,设置当å‰�任务数é‡�. 如果想éš�è—�或者ä¸�使用进度æ�¡å’Œä»»åŠ¡æ•°çš„æ˜¾ç¤ºï¼Œå�¯ä»¥ä½¿ç”¨setProgress,setCounter 传递falseéš�è—�相关显示. */ DTaskbarControl::DTaskbarControl(QObject *parent) : QObject(parent) , DObject(*new DTaskbarControlPrivate(this)) { } DTaskbarControl::~DTaskbarControl() { } /*! \brief DTaskbarControl::setProgress 设置当å‰�进度和进度æ�¡æ˜¯å�¦å�¯è§� \a progressVisible trueå�¯è§� falseä¸�å�¯è§� \a progress 当å‰�进度值 0-1(æ�¢ç®—æˆ�百分比) */ void DTaskbarControl::setProgress(bool progressVisible, double progress) { if (!qFuzzyCompare(d_func()->m_progress, progress)) { d_func()->m_progress = progress; Q_EMIT progressChanged(progress); } if (d_func()->m_progressVisible != progressVisible) { d_func()->m_progressVisible = progressVisible; Q_EMIT progressVisibleChanged(progressVisible); } QVariantMap properties; properties.insert("progress-visible", progressVisible); properties.insert("progress", progress); sendMessage(properties); } /*! \brief DTaskbarControl::setCounter 设置当å‰�任务数é‡� \a counterVisible true任务数å�¯è§� false任务数ä¸�å�¯è§� \a counter */ void DTaskbarControl::setCounter(bool counterVisible, int counter) { if (counter != d_func()->m_counter) { d_func()->m_counter = counter; Q_EMIT counterChanged(counter); } if (d_func()->m_counterVisible != counterVisible) { d_func()->m_counterVisible = counterVisible; Q_EMIT counterVisibleChanged(counterVisible); } QVariantMap properties; properties.insert("count-visible", counterVisible); properties.insert("count", counter); sendMessage(properties); } /*! brief DTaskbarControl::counter 获å�–当å‰�任务数 return 任务数é‡� */ int DTaskbarControl::counter() const { return d_func()->m_counter; } /*! \brief DTaskbarControl::setCounterVisible 设置任务数是å�¦å�¯è§� \a counterVisible trueå�¯è§� falseä¸�å�¯è§� 如果需è¦�éš�è—�,建议设置counter的值为0并且设置为false,å�ªè®¾ç½®false,有å�¯èƒ½ä¼šæ˜¾ç¤º */ void DTaskbarControl::setCounterVisible(bool counterVisible) { if (d_func()->m_counterVisible != counterVisible) { d_func()->m_counterVisible = counterVisible; Q_EMIT counterVisibleChanged(counterVisible); } QVariantMap properties; properties.insert("count-visible", counterVisible); sendMessage(properties); } /*! \brief DTaskbarControl::counterVisible 返回任务数是å�¦å�¯è§� \return trueå�¯è§� falseä¸�å�¯è§� */ bool DTaskbarControl::counterVisible() const { return d_func()->m_counterVisible; } /*! \brief DTaskbarControl::setUrgency 设置任务的紧急程度 \a val true 任务紧急 false普通任务 */ void DTaskbarControl::setUrgency(bool val) { QVariantMap properties; properties.insert("urgent", val); sendMessage(properties); } void DTaskbarControl::sendMessage(const QVariantMap ¶ms) { if (QGuiApplication::desktopFileName().isEmpty()) { qWarning() << "You need to set the desktop file name before you can use DTaskbarControl!"; return; } auto message = QDBusMessage::createSignal("/com/deepin/dtkgui/DTaskbarControl", "com.canonical.Unity.LauncherEntry", "Update"); message << "application://" + QGuiApplication::desktopFileName() << params; QDBusConnection::sessionBus().send(message); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/dthumbnailprovider.cpp000066400000000000000000000305001522615413000212540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dthumbnailprovider.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE #define FORMAT ".png" #define THUMBNAIL_PATH \ DCORE_NAMESPACE::DStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/thumbnails" #define THUMBNAIL_FAIL_PATH THUMBNAIL_PATH"/fail" #define THUMBNAIL_LARGE_PATH THUMBNAIL_PATH"/large" #define THUMBNAIL_NORMAL_PATH THUMBNAIL_PATH"/normal" #define THUMBNAIL_SMALL_PATH THUMBNAIL_PATH"/small" inline QByteArray dataToMd5Hex(const QByteArray &data) { return QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex(); } #ifndef UT_DThumbnailProviderPrivate class DThumbnailProviderPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate { public: explicit DThumbnailProviderPrivate(DThumbnailProvider *qq); void init(); QString sizeToFilePath(DThumbnailProvider::Size size) const; QString errorString; // MAX qint64 defaultSizeLimit = INT64_MAX; QHash sizeLimitHash; QMimeDatabase mimeDatabase; static QSet hasThumbnailMimeHash; struct ProduceInfo { QFileInfo fileInfo; DThumbnailProvider::Size size; DThumbnailProvider::CallBack callback; }; QQueue produceQueue; QSet> discardedProduceInfos; bool running = true; QWaitCondition waitCondition; QReadWriteLock dataReadWriteLock; D_DECLARE_PUBLIC(DThumbnailProvider) }; #endif QSet DThumbnailProviderPrivate::hasThumbnailMimeHash; DThumbnailProviderPrivate::DThumbnailProviderPrivate(DThumbnailProvider *qq) : DObjectPrivate(qq) { } void DThumbnailProviderPrivate::init() { } QString DThumbnailProviderPrivate::sizeToFilePath(DThumbnailProvider::Size size) const { switch (size) { case DThumbnailProvider::Small: return THUMBNAIL_SMALL_PATH; case DThumbnailProvider::Normal: return THUMBNAIL_NORMAL_PATH; case DThumbnailProvider::Large: return THUMBNAIL_LARGE_PATH; } return QString(); } class DFileThumbnailProviderPrivate : public DThumbnailProvider {}; Q_GLOBAL_STATIC(DFileThumbnailProviderPrivate, ftpGlobal) DThumbnailProvider *DThumbnailProvider::instance() { return ftpGlobal; } /*! \brief DThumbnailProvider::hasThumbnail缩略图是å�¦å­˜åœ¨ \a info 文件信æ�¯ \return true 存在 false ä¸�存在 */ bool DThumbnailProvider::hasThumbnail(const QFileInfo &info) const { Q_D(const DThumbnailProvider); if (!info.isReadable() || !info.isFile()) { return false; } qint64 fileSize = info.size(); if (fileSize <= 0) { return false; } const QMimeType &mime = d->mimeDatabase.mimeTypeForFile(info); if (fileSize > sizeLimit(mime)) { return false; } return hasThumbnail(mime); } bool DThumbnailProvider::hasThumbnail(const QMimeType &mimeType) const { const QString &mime = mimeType.name(); if (DThumbnailProviderPrivate::hasThumbnailMimeHash.isEmpty()) { const QList &mimeTypes = QImageReader::supportedMimeTypes(); if (mimeTypes.isEmpty()) { DThumbnailProviderPrivate::hasThumbnailMimeHash.insert(""); return false; } DThumbnailProviderPrivate::hasThumbnailMimeHash.reserve(mimeTypes.size()); for (const QByteArray &t : mimeTypes) { DThumbnailProviderPrivate::hasThumbnailMimeHash.insert(QString::fromLocal8Bit(t)); } } return DThumbnailProviderPrivate::hasThumbnailMimeHash.contains(mime); } /*! \brief DThumbnailProvider::thumbnailFilePath返回文件缩略图文件路径 \a info 文件信æ�¯ \a size 图片大å°� \return 路径信æ�¯ */ QString DThumbnailProvider::thumbnailFilePath(const QFileInfo &info, Size size) const { Q_D(const DThumbnailProvider); const QString &absolutePath = info.absolutePath(); const QString &absoluteFilePath = info.absoluteFilePath(); if (absolutePath == d->sizeToFilePath(Small) || absolutePath == d->sizeToFilePath(Normal) || absolutePath == d->sizeToFilePath(Large) || absolutePath == THUMBNAIL_FAIL_PATH) { return absoluteFilePath; } const QString thumbnailName = dataToMd5Hex(QUrl::fromLocalFile(absoluteFilePath).toString(QUrl::FullyEncoded).toLocal8Bit()) + FORMAT; QString thumbnail = d->sizeToFilePath(size) + QDir::separator() + thumbnailName; if (!QFile::exists(thumbnail)) { return QString(); } QImage image(thumbnail); if (image.text(QT_STRINGIFY(Thumb::MTime)) != info.lastModified().toString(Qt::ISODate)) { QFile::remove(thumbnail); Q_EMIT thumbnailChanged(absoluteFilePath, QString()); return QString(); } return thumbnail; } /*! \brief DThumbnailProvider::createThumbnail创建缩略图 \a info 文件信æ�¯ \a size 图片大å°� \return æˆ�功返回ç»�对路径信æ�¯ï¼Œå¤±è´¥åˆ™è¿”回空 */ QString DThumbnailProvider::createThumbnail(const QFileInfo &info, DThumbnailProvider::Size size) { Q_D(DThumbnailProvider); d->errorString.clear(); const QString &absolutePath = info.absolutePath(); const QString &absoluteFilePath = info.absoluteFilePath(); if (absolutePath == d->sizeToFilePath(Small) || absolutePath == d->sizeToFilePath(Normal) || absolutePath == d->sizeToFilePath(Large) || absolutePath == THUMBNAIL_FAIL_PATH) { return absoluteFilePath; } if (!hasThumbnail(info)) { d->errorString = QStringLiteral("This file has not support thumbnail: ") + absoluteFilePath; //!Warnning: Do not store thumbnails to the fail path return QString(); } const QString fileUrl = QUrl::fromLocalFile(absoluteFilePath).toString(QUrl::FullyEncoded); const QString thumbnailName = dataToMd5Hex(fileUrl.toLocal8Bit()) + FORMAT; // the file is in fail path QString thumbnail = THUMBNAIL_FAIL_PATH + QDir::separator() + thumbnailName; if (QFile::exists(thumbnail)) { QImage image(thumbnail); if (image.text(QT_STRINGIFY(Thumb::MTime)) != info.lastModified().toString(Qt::ISODate)) { QFile::remove(thumbnail); } else { return QString(); } }// end QScopedPointer image(new QImage(QSize(size, size), QImage::Format_ARGB32_Premultiplied)); QImageReader reader(absoluteFilePath); if (!reader.canRead()) { reader.setFormat(d->mimeDatabase.mimeTypeForFile(info).name().toLocal8Bit()); if (!reader.canRead()) { d->errorString = reader.errorString(); } } if (d->errorString.isEmpty()) { const QSize &imageSize = reader.size(); if (imageSize.isValid()) { if (imageSize.width() >= size || imageSize.height() >= size) { reader.setScaledSize(reader.size().scaled(size, size, Qt::KeepAspectRatio)); } if (!reader.read(image.data())) { d->errorString = reader.errorString(); } } else { d->errorString = "Fail to read image file attribute data:" + info.absoluteFilePath(); } } // successful if (d->errorString.isEmpty()) { thumbnail = d->sizeToFilePath(size) + QDir::separator() + thumbnailName; } else { //fail image.reset(new QImage(1, 1, QImage::Format_Mono)); } image->setText(QT_STRINGIFY(Thumb::URL), fileUrl); image->setText(QT_STRINGIFY(Thumb::MTime), info.lastModified().toString(Qt::ISODate)); // create path QFileInfo(thumbnail).absoluteDir().mkpath("."); if (!image->save(thumbnail, Q_NULLPTR, 80)) { d->errorString = QStringLiteral("Can not save image to ") + thumbnail; } if (d->errorString.isEmpty()) { Q_EMIT createThumbnailFinished(absoluteFilePath, thumbnail); Q_EMIT thumbnailChanged(absoluteFilePath, thumbnail); return thumbnail; } // fail Q_EMIT createThumbnailFailed(absoluteFilePath); return QString(); } void DThumbnailProvider::appendToProduceQueue(const QFileInfo &info, DThumbnailProvider::Size size, DThumbnailProvider::CallBack callback) { DThumbnailProviderPrivate::ProduceInfo produceInfo; produceInfo.fileInfo = info; produceInfo.size = size; produceInfo.callback = callback; Q_D(DThumbnailProvider); if (isRunning()) { QWriteLocker locker(&d->dataReadWriteLock); d->produceQueue.append(std::move(produceInfo)); locker.unlock(); d->waitCondition.wakeAll(); } else { d->produceQueue.append(std::move(produceInfo)); start(); } } /*! \brief DThumbnailProvider::removeInProduceQueue将缩略图从列表中删除 \a info 缩略图文件 \a size 缩略图大å°� */ void DThumbnailProvider::removeInProduceQueue(const QFileInfo &info, DThumbnailProvider::Size size) { Q_D(DThumbnailProvider); if (isRunning()) { QWriteLocker locker(&d->dataReadWriteLock); Q_UNUSED(locker) } d->discardedProduceInfos.insert(qMakePair(info.absoluteFilePath(), size)); } /*! \brief DThumbnailProvider::errorString返回错误信æ�¯ \return 错误信æ�¯ */ QString DThumbnailProvider::errorString() const { Q_D(const DThumbnailProvider); return d->errorString; } /*! \brief DThumbnailProvider::defaultSizeLimit返回缩略图默认大å°� \return 默认的大å°� */ qint64 DThumbnailProvider::defaultSizeLimit() const { Q_D(const DThumbnailProvider); return d->defaultSizeLimit; } /*! \brief DThumbnailProvider::setDefaultSizeLimit设置缩略图的默认大å°� \a size 大å°� */ void DThumbnailProvider::setDefaultSizeLimit(qint64 size) { Q_D(DThumbnailProvider); d->defaultSizeLimit = size; } /*! \brief DThumbnailProvider::sizeLimit 返回文件大å°� \a mimeType ç”±MIME类型字符串表示的文件或数æ�®ç±»åž‹ \return */ qint64 DThumbnailProvider::sizeLimit(const QMimeType &mimeType) const { Q_D(const DThumbnailProvider); return d->sizeLimitHash.value(mimeType, d->defaultSizeLimit); } /*! \brief DThumbnailProvider::setSizeLimit 设置文件的大å°� \a mimeType ç”±MIME类型字符串表示的文件或数æ�®ç±»åž‹ \a size 范围 */ void DThumbnailProvider::setSizeLimit(const QMimeType &mimeType, qint64 size) { Q_D(DThumbnailProvider); d->sizeLimitHash[mimeType] = size; } /*! \class Dtk::Gui::DThumbnailProvider \inmodule dtkgui \brief 缩略图生æˆ�ç±».  \note 缩略图创建失败 该文件格å¼�未知,无法由程åº�加载。 文件格å¼�是已知的,但是文件已被æ�Ÿå��,因此无法读å�–。 由于文件很大,缩略图的生æˆ�将花费很长时间 */ DThumbnailProvider::DThumbnailProvider(QObject *parent) : QThread(parent) , DObject(*new DThumbnailProviderPrivate(this)) { d_func()->init(); } DThumbnailProvider::~DThumbnailProvider() { Q_D(DThumbnailProvider); d->running = false; d->waitCondition.wakeAll(); wait(); } void DThumbnailProvider::run() { Q_D(DThumbnailProvider); Q_FOREVER { QWriteLocker locker(&d->dataReadWriteLock); if (d->produceQueue.isEmpty()) { d->waitCondition.wait(&d->dataReadWriteLock); } if (!d->running) { return; } const DThumbnailProviderPrivate::ProduceInfo &task = d->produceQueue.dequeue(); const QPair &tmpKey = qMakePair(task.fileInfo.absoluteFilePath(), task.size); if (d->discardedProduceInfos.contains(tmpKey)) { d->discardedProduceInfos.remove(tmpKey); locker.unlock(); continue; } locker.unlock(); const QString &thumbnail = createThumbnail(task.fileInfo, task.size); if (task.callback) { task.callback(thumbnail); } } } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/icons/000077500000000000000000000000001522615413000157635ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/actions/000077500000000000000000000000001522615413000174235ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/actions/edit-copy_16px.svg000066400000000000000000000023571522615413000227260ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-cut_16px.svg000066400000000000000000000030221522615413000225350ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-delete_16px.svg000066400000000000000000000031551522615413000232130ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-paste_16px.svg000066400000000000000000000065451522615413000230730ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-redo_16px.svg000066400000000000000000000015641522615413000227040ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-select-all_16px.svg000066400000000000000000000027141522615413000237760ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/actions/edit-undo_16px.svg000066400000000000000000000007271522615413000227200ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/dci/000077500000000000000000000000001522615413000165225ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/dci/sp_alert.dci000066400000000000000000000044201522615413000210140ustar00rootroot00000000000000DCI20Ànormal.dark®3f1.5p.webp../../normal.light/3/1.5p.webpnormal.light‚3:1.5p.webpòRIFFêWEBPVP8LÝ/Y@M(h#IÉ?ø7Ì"ú?|•EU³Mc6Ìí1†§,-| ï£wºÇÄ˃ôáU ‹YSÀ2Àw·JÛ6Ò¥7º�Ƕm›«YyfoïÎ5C»YqeÛ¶mÛöÌוq]§""#«Îr!Û¶coÎ/©mÛ¶mlæÎÕ¶±¶SÆÚ¶mÛnã´1_‡’lSޛދsl*Ÿ€(þÁ"éâ‚°|�-_CéÝa| -W—Y¡w¥Ô5QžË¥#øÞãa¹uDÎò¡‘q]Í…Ó0†zrq“a”GwæŽt{ŽMÒÀà/–T+eÜ4p:�G"¶·‚"Œ0±AÁätÙvø-„ái¬tã�É:îÓÀ×»•Ç\‡ñvº®M/}˜Ð0|añ ŒvÏÍ;.Ƙ”Ü™FfXPß%"�ÆÓŽ97<9mÝ•+X¸Æl ¹�Œ¡y~ nÏ1, (*j.´»´øà؆ѬW+X!xèÊŸŴÂÀà§ÿ¢Ôc \"Ø«íz úè»Ðý�!åì¼ÙÖKµx…`ƹ*tNÊÀ�u¯0QêAÔLŠ¡S°(ø¥E¼Uè ?³P ©±�l >ò*fGGE…³7M–ØÖþòéJ£0|"ˆØÔ„àcG§'‡ôŸŸ5¢jÞiËÙ>Ctì*…^…�„ `Ý™³â ÚMòwœ`¬;Ö× z½Åj>$‚^1×d‚ÂO¸Vn Ç æ"÷*"l´§õ^-ðÍão´ ˆ$ŽðçŠBœyƒ=� ¢Ø¨“ÀÐàÂþšºÈ<õ:ŸaÐÚ1gÈ´3?ÎA”éERèe~>ƒ ˜™R•˜ÉY�Þ‘JôÐdäù5¥äîò¯EE„†™©É¬ X%Ú*R]±Õ&û1õ¸ Ø2LÓ„ >F„hŒ Ýòb\ZyÁ@§‹ÁÚ±­ž!ôD¯@Ï¥eŒ—« ÈØº¯LÞÂð�V1:’G¡bÊ�\bË>’¹O2#§]¬°200sø-b~WD ºîZ°(˜œ"i�Je†Åhán)R à &ÛZÅÂŒ�ˆ–Ü€Z€¯›ªŸTSÀQ˜+DØU¡fÔ-Ž š=q÷V�rúž289«0Š¥sÝ’YÊW:ö6•-¤§V¡aR…f¿YA¯§v©øÒ¢’n,39Ýáa£zÛn "™ùv´s‚ÓÝw¡â¢b>_®úµà±Ž°ðÎ`�ˆ¢Mæ>Cœ”T\+ÊÐ(>-B¢k§ø¢ôû“VzÞéooc¡Ê4ó& plÃòá»�Â}ÙÝ=É©¡ãæ¬ö}~IÑ©ž£Nµ"ÁäWê¸xÏžsKÿÔmüÁºÖ}Ôe¢YÓnñ-Yü{~¹aEÓ²¯e-¸�â>hMÙ|æŸqÑ¥Âï¦_ß|:ÕÑã_f¯8b0�ÈÛæ—Uç\ˆð*§z›Ib�ÜGLᄄbüëáþøiFÈÒ¨¬ZùvÞì5 QQᯫßÊ—deɆ«0¦ôó{Îl/ø÷ÍŒ ®@„ÆZ%SEÄû/þ¾ÔZæ=·ò®‘ßF\ÝË¥Gýöøovv&Ý!Â;�ï|±ù¢;�"ã”ć’ç<¼ûŒ~kΞ ¦X—:Ì.}µý’Ô@5ˆ¡ŒÈJÚ+dV}Ûñ+ŒžvAñ ÁI^÷ð·Ó¯y¨&j :²t1r1Û¬sr™¼w™]z®ÐaaÓI3ªAe¦å Ë@f‰ï>ýýñ—g�ß#P¥Âu¸u²’I™:~æ5ö%7èz½{%ĤªdB_Òq`æø¯ƒôas §�$•’�`”áÝްÉ'퉶EqØfå&6¬KÅDõ#D�ð‰ ÅU¹]4õ¢˜+ŽÖ¥¢bÔ£~´Å t`U;ãÒAYÌEÈ*`W&2’jÚ* óƃ#ݱ†¹Õp¶ȨC#�dtkgui-6.7.46/src/util/icons/dci/sp_ok.dci000066400000000000000000000146661522615413000203330ustar00rootroot00000000000000DCI20fnormal.dark®3f1.5p.webp../../normal.light/3/1.5p.webpnormal.light(3à1.5p.webp˜RIFF�WEBPVP8L„/Y@ m9J{¿Ÿ?á !¢ÿÀW-ö&âNh`‚„4`Æ.&»YY‡„¢Æb "JÛÁº#–uá&¶mWYŸœ9óª_^øW� ÊØýd�m#IŠêîÞf´?ÿ�.ˆ5ŸÅ´�$Icµ¨áæÑâÿîÐÁþO–†ô¦@€0¢"C€àÔ@Q¼�6) §ò…=­Ÿõ8h½ê«ùo-@ƒF|�CO¯<á`<Ápã ý¦Àè…ÿ×ÿ´ûa4À ³Ã˜»´m«Ü:z¿ï[Ý­ÂÌÌœüê“Ð9år: ý (ÌÌÉ3Hê^k½¥ÖZ«—äý33s3�Ké*O8Ùä GU.ojP.—Ë¥A í¿¤ =f•ÊÑ€†½)ÌÌàÊ0óŒÒÞa)¤*Kض¯©=ß/�pü ôrww睊»ëÖÝmå6>;w÷•»Ô½«ñ™º·ÌpBà ¿�ü¾�Òm[ké¾÷¾OR"…™š»¨™™y†#¦¿ÀÌÌ0ê!sÏ™™É½jqU;X'ŠõYú¾çé¶mÓ¶µm˵ÏuÎeÛ¾B¶m_!ãضm„lÛ¶mû:6מ£Uˆ¶­•âM ’^I‘É?$=ÄÔ ÷:@h‡ ½ÝðU�ŒÕýF;ÿ¢“4r@8 |�ÎG�¥hç�ƪF6 4B-|ß�]w¹õünû/oÝ£¸±�øÚ½¶ .#Ð…½¢8]N7�� ÀŸBÓ?58ûÓà­#¿{õµ‹Îê|ô ‡"ÒH³„MDê –v “FZÝ»í—êŽó‡Õ¬àf ŽV Àp�ᚌàPÀ�B5ŸXÚ¦ï_ûΥǯyi[-?þíðÈ cQE!?“”S¹Þ6oÜÖïTO0†»‰à@ ��§ ¦P;®ÆébØ«àK^c^uµw¯ø¶ GûÒC8rH·œÖÖš]>ºƒÄþÙ¡†[£Æ Š1¦e¨ ꯡþš)„@`ŸŠ`qÂß• Ïkyåüo^jóC楇"ÜŸÁ(·#y#RnÈ�F_¾;]z™‰üƒžj„% Ùxz¬›R¢æËާ\q~Þÿd¸­üƒKs|}ß{ÍûŬÞéó{HÞ¥†‹<µúTªO­òÔªD¼ß_u\í8€~Fpª~dëëg}¡«<3�¤ùzæõG!ßÏ-§µ•­×rðž¿?V¤|qà ÄgÌh¢ 1 ÃÁXµOÏÖËÉûFî?¨šßø¾®!;øï¼l¶çM<\ ¢è§f§˜M|,Š#Ú”Œ¯#›-œ‡÷ß ZýÖŠ$\$\[üpèôæµá@Ä'@ä*«ý7 „øZ¯ù-•–þµvZSÁÍ+Œ$yÉ#­ «’…Ç~ƒGWÈ®wj ¿ˆ’$³S•=³ oHLϼå1¼ˆ�Ò]PÄYô[16SÁ/ï�ªÀhÜ*qö/b|ÁXôÛež�‡¯‡g'©1üÁ"³°›tžOõ¾ÇwOï¶Æã ø’äзs(Ðè“_©™ÓEYýÙ£‘õ]™F«•ñ<[1�<»*fNÿuàÐDÆ€+·µ˜ô÷nÀYŸþù1ú²Q#[N%âíøz��$‚#†'æÃ-[¶Ÿº]ajôåŸþõb’õÑSýÛWrNÒØoßÝO`Œ¨¨cxô1�f`$A©21±[”ížžþÄ¿ü5_ùoiÁ�ðí;´»×S·Ù–ˆ»è©­ß–€L÷Seä÷cè~C‰H$b¹MƒJ‹Â•0- ÓÓÏã,zjôÛ/>üû}XJÕëGæ„ËI¾Aþ·+ôíÁ䑵öÐ¹Û | @„‰ûøšý_“ Ù¸��m‡¹8•ÛDüîú[çÞOѬ:´¼]] /›•÷S‘¼¡–¹Ôá¶“F å‰ßÜ•»3¥4¦ƒ`�%jÄ|];FT ˆlÜ·‘üÎìü׃‹¸Ù·æU/ OÐåGu�‹Ýrd5þ�–”ÒÉ!IÏ ù�½ýÏž[‹iw.Ƹ­piUsgÁºbjßæ„$`Ø·ybäô-&"¹›p�Gƒ»üª²%†kÿf{g·U¸tZËÀºý<^?a©x¡,xêüçvYÇêéã�ÚÊ�q°0‰À„`{$J+`Pý"» laÿæýç½Ú€»üîñG(ã‰ùT”zúòÀî,Ý�‡�ñ^î‹”SIÉæ:¸Üuò;ûËopŒ9[Ѻè>£f 5†2ñ¼¢Æ*ĪHá8ƒh9ÈkÝ? X‘~â¥uP!£*Y jüd¶X^+^eÖÁ–ÌU–9B; e=ežKq^«t#1`OÄb8né`ÏØÆö¼€1ÛWº« nÿcqೂÍû¿&‚éÑǨ 1¾Q¸ ] Ÿµó.R_q6Ï.Gä`úò;Ëw¼y`r4ýQ1© LÖ'#õÉ:Æ©…?`ᘬ‹óPeº«ËþfÝæk/Qc|ügc+ÁÀ:zí¤û–}Ìc9·ô#IUœ.×rè5zŸþB€±j,që™Fç®g̈GºH +$ÒMKä=îœy6g9¹`€b)nü±—ù u?Nß²�ÚX�±Ú;ßiœ¿A7]k혗#O¶^HË¡#)§ y/wfÉÊj¼2¸HtÍqj³ivšáÚ1œ:{*³§>vÍë¿)ùep˯±òé`Ód¬n €ùwöG_àо Ò”oéçã‘Çáâæ.ÞæXbr Q�(ˆƒ vMìŠø¦<+b¢ÈE™8U,Ö½S÷þ Üñãpª2Åg¦>ÃÔgÔßû�2åÃ7=ñ«;ISQóH:¨¥�_,[¯ÆQÄM�n¢Õ»‘-ƒ¹ôÿ2\¦:\Mާ‘wh”¨£uÊ([þï/@Ûn'»ñÅ7 kÒ??�±ê1lÝÊèÖQÞÿo›ÐaÓ û,äûé©lØt•õmqY«ñj£JSUEL.ðÎþH‰*;gvV@¶ÇÀö@~¶ “ M[l°öo50¦¨NUQSÕ?¢úGF¿YO¸Ýoè~­{¹O$4n½A.£Qr?ŒSªbU2¹ÁuÔßœ|&ÿšFâ9\èDoƱÁœ)*Ö:ä¶ëp¡{OÔrà€ž·VÝ峿ZõÌ”¨Á(ÕQÛ‡‹]ö9#ÀõRm»Oþ|b{¿�"ï|û§¢žu*§¾j†}š¤§�çVY™3mÕ[„ANøóÈ쎬!ÓaWüÝ“¶eмKдƒúówþùŸ�«ê@€cÞ|‘O´€e¿wnsã½Ø4Yˆ`œØ5@Ì ¶@lÕ—3WY•Ÿ¡�†�ë�SúûxŒ¡Å¹q©¯>`²a+gŒ?Ö ÞiŒð泞cH§êF§ßÇ_‡lÉù„Sþ{®§"ÐSÐ/E[ÒFÿqb”ÅDZK}åA�Û\ÙØ3~Y±jä¶fç¹Í€[\ú°•O”HIÚàñ¤%ªßŠŠ˜wÅ)¦m Wúý}rÛÈN—²wŽ‹2.úÅWÀ½¾S¹ãƒÎô.¦wMT0pÁÿ6u{gD[ʾ»ðSAŽ8* KÓ^p©oß#»9€Ì¦Àë³ñÚ¹®'°þu“ÓÖl×4»¦wU.àHöÝ•Ÿ& ­ ×Cžâl«üëºQ"’Ü6p©oߥqwׇìüÿ«³^ rÓsŸ´îo�:�°­üúi½žD § ÎG�{mbb¦‹ 3n/à–ÕWJIòd€Zlå¹!\âËwˆÁrI° îö q÷ÏAÒØþYÍÏœWû¯ôa††éBM5xxÚ·Ð ¤ø“¬3[a¹‚›…k>šýœ`ö}°ÉvƒÞÿEb°²[«Ÿa«žŠýAŠœ§ü@¹JïÍG�Ͻ9W˜òËÁ,)ÅaVÒÐÙIzE>Ù(Ãí¶™H’3kù¡v{®©-¯?×VhËÞû^˜\ˆìeç¹Î'I‚æ/Ô�O¸IÏ›ÊDŠ…ï^"¸"ë~óÂfD¶¡ïåâõ5iUá6Ȇ árvn©À@¥W¸³W†ŠŒræÝ‚�QÒZo–��(b¯òƒ0"¶nMBtÖóÕE>{/Û…8„ÛÞ|»ƒ~ê@Ü ¯Þ©À;©!™Uñ.o‘LMH³áF£Áˆ`êõR½žhÅ?áÞ ÷§ ¸2°”å(ý¬©ÒÞ^‘ ~yõü±A”^yÛc»í±ªóÅ&h=Z]ê›wò2€ƒÜæª;Õ'ëìT!;bûÁ0å/ò³éŸxðh�š¥s>w)mežo¯œ¤^{Ø×Ûoù5ûò1ZÝrï¡ñR§aIõ=–³4J�³—›Œ‰G#`~¸ÔoÓ°SÐû¾ºÑ1÷ðçDv$€ê1UŽ©ŽQ«2–“…·8âé¡h ­Y—æ]ÅJ›]2!¶þn“½òp´ÿV9Mmç�v>úa®µï±u5È,ÑLÞ°¿Bß•i4fXDêÆ1JÛÑ1cÄ0"î'@Ý8R�Ãò&êRß¿Eëa„5Üâ’û­~ZÅGy`o}o›‰H}F‹/eË­? ùx˜-[˜ÉõËÉM0ãØÛÎG¿ð0FÒUèËC 6E Wñ2�$«å¯Cìe¶mÛcµ±„�Ûtȹ®*,>!ð ¸ÇÄš‘ŒÊÔf©ÍÖp‰ŠÚŸ zFójÛk\„-\$Œh|0þ”¦\s©Þù­\0ùÝj=ëËõF»5¦3 ë�L«Ñ.Etõ™ßXµnÔˆìQO'“1¦¢¢{sŒbA'³œ{¶ SLJ3÷ æ­É¤åV‚¦èVf1�ãï6Ù.¾”Fî­ðž5/ý"·ï¨··­g X²¶ÚÄ´&’€Q�3/ç¦ÿ£ÁÿEÕäÏ£ÞÞ[ŸL@V�dU›©oŽîB“ “‘Âý†<ÞØœüô]éæ‚n~ÒÚ¾pRµN¬œ|•‹…üLeÖâ}¥É¸&Ô�¸ +Œ·’øZò³­[=ËJõ��oß>>~?Œ‚Fd/S{5‚„+’YŲ¦­£ÖªÿXVÏ2hÂÊ.$ Tq#Y®*×—.)Ê”ù;²ÉÊIËà²r\кÍëÕ­Jøp­¦R_M„õ#™ØýÍ´f â��IÊvÌï(· -T¸Ó1qãm?ìcbR“Ç—°ËÍ«åÑZvóé¬'ZkÇëëÈ“ª¯FR²B·ô‹ñÈ“óÝmíEí©ˆ«²ìؤªc_#!FÖƒÆù?Uäl Æ‹#XÂ-FýÑ]Ð33kÛ^Ð,_~ϰCÈû,!& 1DqÓÎÕM¹–Z�®*álcz¶J8ÉD­ÿxmóß�?çøû×–ås„Ð0–Ñ£è8âÑã�yZˆ4›” 3îzàûàÿôÖA-À¿Ò*¶(¼£Ajð,hivýÓ¡„jc[Ï* â@×h±7ÔÿïA4ÿ/ÀÁõ�üƒ£1Wñu-�&$í`ÂJçk‹m?ZKsÚ€tÝpÿ ¼bš$'^àì$EXø²E ƒ¥”õG1-¥©t¹.¨@•MÑ aB‹Õ¸VÁƨ�Ä€`ZИ‹BõÕUx×�x\*[Ð`sèvíØ…Ýz0 FÑŒ)Ò�ù†¬WXÄ—ð"¢º�Sd'®MKt5ÂÛÜ5œÙ¾Ü&¨®P/° Ël@ƒFÙ4ÔbkT 54óñ‰`|…*T¡ÿ ´×¡#mØÁ„ÆA[Ð�7·Ò-$ŒK°ó0>Ñ›çó–fLC±�Lº`–MJÜæŒÌÒ~:HQç[ 2g¡�Ø�«·Jª ú� ÅÊ4¿£1 h‡ë5ÜRÇs�ÂUÂ8Ì„ƒÖ„‹x,´· ïý5Ú<¤ñ„Ó‘æ‰'Ìâ3[Ÿåþ:ƒLÅ$kó´Ë**âã®ç–øæØ†ÐÛœ¯*¾ä¥#®«CýS¸PÖ¬l ³BЮô#Ú õ4!Ü?Ø‚Q2~�Í+ü–!Ù2UºeYÝq³L\’–ˆ{NÒ>{P5´C-�÷ÊCjßWÓ†—³µœå•#YÝïä­"ÙÎ¥Ó«Tµï<ÊUÌ’åL–ñUÕ2µM‘CrDè¥%i®&eÌh�ˆŸlQ���Lº¶ÕødYÛ|ZSÌÚ&_„­—b–Ð5þn³åÊÃÑö}¨\�ò—ÞÆ¿§kóë<¸¬$Y/Ë««›hepËÛ«w#[MU•"­e‰cðéÍBl’ëðÂ0ãæ ®" qÍͺ”›ë¯Œ?�¦DiýÝf[L²–¿¨¶JÂ)À-ý|²õj¼—;óÄ?µ¸,£+oâí«¬ÌbX´‰m0³å›—²Ü�¸ýšKõz9øöÁ?�øÉEË¡ÇäÊ@YÁ ç¸'ÀÙIê“–²¦ ˆ�\l˜—¨@�Wò‹u•õ¼è«ùpB¾k~Oä´eƒI QbŽòãtÒÈ!ë„á�zª©ÜàÔdtkgui-6.7.46/src/util/icons/dci/sp_waiting.dci000066400000000000000000000042521522615413000213520ustar00rootroot00000000000000DCI20Znormal.dark®3f1.5p.webp../../normal.light/3/1.5p.webpnormal.light3Ô1.5p.webpŒRIFF„WEBPVP8Lw/Y@M0lÛ6d'ýrû/ÜöîFˆèÿð«6Û[ÄaR“!yµªìÚfË¢V�-h%”#³gV Æoxl€è òôVA×Ö&E’Ù½¼–M¶XzY,ùÌ /Á’' -ff&�™™™iº2Ï™ŠˆŒÌZSðGL„Ú¶MíY¿mÛ¶mwfÏÖ¶¢6©þ2¶mÛ¶“ßøÌ Q’”JÌC¡töîÈÿ`á0a!±)�mjCaõâÓ Bp£åÆì’”BS¹‘M±!’„$ô¯| �ô8ß9H¹ihnq[ÛL•)­˜¨ˆ…¤N÷–Ž û_–‚î––wäÍ»K�Q€ñ„3 ÒÎÎæÞ!@¢#K·ΦKf:º9Œv“˜ÎÓ-ž©%g˜†²F€†#áiïR÷ Ä“( ©¸AÝ Z/͇]è/óˆÁ:ãnÓ#,ºÒ;…楦%¦ºgˆLEͤ@ÑW›t—íhGÁ£ZÆÁq(¢„Îm; ?Ý@övð%è3¬7BpdܵŠÊÃ&zò¹êŧ‚»{@-Ÿ™D†!"”}•qbøtŒ¦C $¤lxS€³‡CË% Da‰&ãŽòZÞÊžÞ}†Ã—†œó`ó zvDVH·x׉í/ÏIR€šÇ:;*ÙÁ‘äç�RóNøŸÏ�µÖÑ"Ÿ< G†ðáÜ) ì&þ{ž!æ�Š@} <ç,Í7BBÈ�º‘ï²…eÈyíUØáЧ�« 'Êí#oµHÉ€ËýÏÑ Ûó ~YƒbÕ2D"3úué—ùtò½®&A`—,^¼m äê래A¾ú�Y)¦;erä6Ž@Ì•´ Är‚B¢W_7÷ÕIdÖ57(ÔÙ‘ÈHê�3©y”ˆ)ÔÜK˜BµUphCPœ�²¯œ¯&Â] …­¢É�‰ªwí‘™Â3.0œÆ²; {r�›]@ÖòœªcÕ<ײ´Òö‰�È6z§âÁ4£ŠWÌb‘ç*¢׋Ó³Ñ@D‰W,(D3QùE•aä~Z±Ÿ…K‘²‡}Ñá ½9/ÆdeTOq*d´1,>1¬ò³`ˆNªà�#Èm¼ôi Dµ�5xYú„Fþó9ß¡Î-4¸³eé÷g­ð¿7žÞŠ¡Ê4“†~^Å“÷o�(†L¦VLðüh…DëõÇ.6�ñ5û´?N7ÜÐËE««ˆ i?<$à7¨_i^VlY ÍFD¢تjÍÆMOÚÇÞÿR7Ü™=±ñЧ›‚uª/Ó3¿Ö5‰î™•áÞ5gGÔ­{4öþ™¼û¶Äog?Ù$Ñø3Õ�ˆg~®6c�ê>j­ÑÅá‹î(?uÛ~°nõ�¼ú‹iãù%Š&³Àkò5ɤ7%Ýw-·,4ïNq‘Á³ßoŠA/§Í/ã]ei•9’€ü©‡´À电%�8 ìb“¬º]uî­*ÒËô*K—…9l¥îº(_4'òìqj…#‡c^ºŠÝ` \J$@PJ4mNPd�”#Ir$Ij™eŸ+Kï² îºœÒ¶íicçù^Yq<Ì�îz133¯º<ðoæš_Sæ®hÅÌ=X†L¹�ku,é£CÛ¶±íYë>¿cÛ¶m;©Œ*µmõvgW¶mç·mãÕ÷ÜíP¶]0’Ù éÖS$Oý�€ü=Qê°„ù¸É¾ð¾–Ó® g‘¿¦KÛúÇà¹Né gáà4gíE«˜Gí¦ßû¨+d�1_¯—3;®(&iO—ï)•-…°�R6@Òj!¯VÂG™¤0)«ú=/þø6:%Ós� ì3?¢æj÷¯¯=×)Ç í5ÞjÚáåŠ_$q¤Àp1A+@2GR_àg9Þîû³üFÞÜ’ƒŒº"Ïð4+eåNæXîÔ´µÓ®tï”]ÿÜ'M›Þ,p†�à 2Äœ]Þ´û&vå|ÈegÔ•‡wF]‘Ñ@΃¶‡@ù#¯ž:cú�Çø Q�Ô‘3TÎ5c$Pœcß ½¿ÚÃß–Ž˜KñÌ?>ù—>ÛÖרÙ1j† 0 ÆÓ KhCfA^Ϩoÿ ÷/øës\yÄǸ0®ãt…ƒeé,A˜HÍa?Ù'Ù·Ä1ñ†?>™­p²«?ßµŸ{gcÎ+G œð¾’ï£Æú‰IL­èd´Nºkñ s*ëÏuÊᢑŇýÕ¬l ÍÅVÐòi@1$'åÞTæ°ùÙMîM݇}ûíŽ`Ìнõ¹T§n,c÷Òmj¢$ÚPë‰ - áÐnÑñìËž7k7ZdNEè¯/¡ò#5Ä€§'�Ö@J ©·•t³ø@?V1wò5n„Aó}y”’ýDëEm’ìoбS˜’µ5 VñzŸ?ð1œ3ÖÁ8w`Ü98×.³ìË€ö^´Þ]»ìr� •hó3ÞØ4fS²±µ»¯`Ð|ÔÂxY¨îŒà‚7½9Ò‹˜øÞ{’otüŽ7yöëqŠ� AhɃÉ!â4VY«VMÔ ×TSr?£®Ðs×ÿXmŒA›ƒ Fó(š7ù¾{à›º‡^ Ïy{ÜàÍ�j8t<�;pÁUÁVÞÞ¿À¨+Rƒg\xdØ­¡(/Tø\ ’FW˜á°Ë7¹ €'®ÒºÚBÆ»‘H45ú,cm![�ÔVõ O',gÀ\zôŸ71ë™sÖÔ“Î*'[ï¢7`›$ñyÞ/«Ö¶Äþʨ+2f˜ ïgÈBŽÝío%ý-'ŠHdÀyD¸ N"¤®êw…û’åvÒŽ$!ÒOÇîÎ÷—[ï}ÙJ•UÛÜdßµç:啬ËÊê­ß¿Ÿ¨ØÑ R€8•�Ö“@dÚ@g†b\'½Þ0�D°ë™7¿NX}Å•½¿ðµGUûĽSv]ÍeêsÚåëˆ@K±âÄÆcvM ¼ÊBÚ¦œÌ.z²¡ûòk§L›·¯~òcÕçü¹ʘaq¨L~�¶Ù©‘š�b4€ˆzT×z! $aêrÂ;B2;}ÊtËÅ�ý£®°šlIˇÝêqKΘ5ÓF» 36º¨A7a7Ø5’aâ8èzÛT ä •q�ô^cb› N÷aXþßßqÜ’á'÷€*ÒÑz9—¬ßìüGËk$5†V£E° cˆ¼n<ðñWc𬳠¹ìüN9[¯.FœqŒr>­]OŒCQ#BåDÞ¸e0`|F&`Á`¼É,lh]öþr¶wVSwàm]ìÌþëŽQc ûZ„ŒŒ• kº>2žÙ/ £€$À€æÇlhÄlÄô¿öèÎâû¯íUU^3tÂûž°lÇ¡RÀÁûv»¿©yôZS·ÞKŠdØ[­¡ÇâýDÖ¥C;­ ï¬UUüà°[]ítœ•ÝA,X´· xZ±~ciX1ÐÆUÇ fà,í.Q¦áê°‹<…¶ M+çMœÖÚ)>ìù ôú*³`¼üFKAËǦŴ®šÓåz7¡øT»µÛy8‹¡qX¹( ë\(˜Ó¡ÒQǶ´ZÝëýUÓ§¦!Ö¨ îІÜÑvP ÀЄod�;+þ{ÌÐa·:iä­þ+=zÎêëéoÙØJ¾Ê†*ð¹4iÖå@cT~É [oöÀ[Q² »È`¯’ÆMö-ÅÆ! öé;«³£°ž�·°><Çû ¡â‚}­§¾|bÅÖ“(+}°>ÈQu–=s¢‚ˆ°û~ÜðÄ™àV‡œ´ °m‰lDiŒÊwÜ!ÊÁøÉ †j çŒeÆÌ¼I)HŠi­à›hã§‚°š¸ðëÞã;z “†)¤ u?l�\™�œƒÕhLxߦL=n в™ÃZÁ AJ+mUÚ�g÷ ßï1¾¥[á×½ÏýMßøF ™“ÖáÊq0G@•¤çã{`ºOX"fTðÖ ýZªÇuâº=ýÇÞ‡Ï_y§ƒÞÅ�SƒšnLjÒ4MÑÖI¼WˆeͰIØ *$[þ�ÅI3RÍ[›Øø¿im–tmW3y8ƒ¦0�iך2•±AÐÔŒ†Ñ� €YÆ/<ÆŸ0¼ã øb{uïMä�ÛÁë­*~ö‚‹ýp{da¡Òæ²þô|…bêÖÖºI×VÃð“?GœLðCçý¬±ÖÚ€®íÛµ6²Qd"5­zïþ+€èEèP…Œ‚aÂmº(èP)°%Šv’„˜X–‰Hfté¢ýA¿¯Èø‰['[â‹»�F³Ñ¨7ê]Ó5†®ÑD#Où8w|U™ yÕ Ò‡œ²›—Uü�µ—‹¿%̃óð¨•ÚÂIM侀�Ðl>œ¾õ~ð àT[DbEÞ E6²6’³¿†¾øZð¸j”’òŽóHü��©‚ ÿ"üÏ)ß8¤¡ìd•¢ª+BQñb¶µ±Æ`$��ã�|Å?q0îObÇ"‹‰‰c÷¾é¹ÌéV9BJ‘Èú¤o1HEººÄsò\02àå)™¹[idÛØÆI7QÀZ´Bö1~ú×'3¸uG¼`?‚$ "R�CD­8jE‘�¬U—O†âw‰8¨.â ³È 2­ÉqkpÚ•©Ì°” Ÿ ß+õUyqÔfӿ˸z5U ¶ql[ú^CeÜ£Nà+üÈ�\xï/=O“÷?ËÑò²`,×Ë\Ò°kŒ˜ab¶úDÕcÎêVñHu <í»��>äRÙ¿ GÀïÁ›}C¯† #ÅåÊ]Q+ ÃŒ 0’ðp¯<=8s�/ÌàÅÄ3çOvžÈ‚pAd¢]ƒÑ«Ý r�µ=—ûú±X5«ŽR…‰ú@9÷ ®¡Š_^¤†wNkÀÑ¿gWá�n�Þës䩦n§2ÐI.Æg-y¹„A÷ï‚@cWÖØ=}âØ�Å£Ö™Ú,ê–‹¬}ð¿žb-7žëTª î% UâÖ3f�C¥¼| ™ŒÌÀûì?5[Ö£(Š¢Ô¨9>qͻ֓njSkM`ÂÀ¨±»DÉèÍ †¹JÓ«nï(ñëµ*™ês�²ÌTg�W–„˜pð³ü,³^Ó&6I‚† ¼ü�³àcŠ7$a�5MÛŒb÷±$F¬J±´sh R³[fªåý¹@ª`:œv¥eªzãÊËÉ(9E¥Í½•ïÄc–_ô®iva�VP ¡‚†©7êI#ÿšß €"t%‹fÕESÊãð“£T®zGЋ̂¡NÕEr§túçëä±9©IÓFS‚ ^t욆H4Ì£�G�£Ùýw¼.%ÊN[ªËjAjúôõ쪔½RFrP�âJ‘ÿý [±xò «L—©6$ÃîP™«¥&m•µÎÊ …!Þ5ƒ"´e¥v:ž ÁRµÙµ÷"瑼Yäõ.ò„¢8“àÐ 1:ͦÁG|"¢ÖŠiJFÓHÖqÞ˜�ßpxÿNJ”I£2­uÈ‚ïw ¶¨Z.0ì>°6 —Œ^î¨"ä:ð}oÝç–ßL£‚§ö©n5LÓ6eü2X™ ˜pøÎ�YØkÁ>˜7±Ä¬Ï8FÕ[ÜíòCF °Æ4èGf‘»{�×KTÀ­„³%ýÊû[|ØÏ绊šã‰˜ fHB¦âýÌé–±ðÎ\™†Ÿ4rØ­j›ÅoJ½½ æá|ó f\© �£¢ç=/8ö•?v§……Å�ÕÂÖ’—ÀÈ„š!s<_CºZ‚#R›)ýÚ÷Å['>'™´rRÞ¸R(ˆýà¾7?Äûa¯zÛcpÂ7ò4ðIVG‰¹TPh+ `Ï»/ì{«…Å…QªjS1Š(àåo*q§<>wó÷Ç})�íqÞâÉ·ÙÞ¿=+‘SñnÇ$À,„!È…: –œ#ž ˜�9Ä�"J–ÚáÒ¥û­sJwà#�ëù ßdžq´ @"í5…ÚN$Z "JÇõ‘)µmrð¾óHØ5Ëøk0Œ¬å�èÕKFNp_pCÈ1®ÌÒR}í ¸�ŒJŠRhë¹#¶¯ÉépÅdáå^-RÍmFn½na®å£KJ/[Ý­»“+.°BÉRŒ”SD•(¼A»¬¡PÛB¬JW“ÃŒ˜ð¶æÁ PÈ#̹ »(Wr yo5¸{Ë�PGJqÁÒí"taF€¢.í…šZ¡®E­¶ì2Ρ< !'�ç´† ŸnF "P³.+o¿à6%+‹©éåf±#õ‹Ð–¢lî¼€ ƒ½¨u”¶º¨´‡Y´;‡=hwþ{Âûá‘—­0·ò\§3tÄÀÕ1ÃrÜ’e¥ÓéÌêìäD Ð/æ�ÃÃCõ•‡;·##¨É˜a˜k9k/¥3… ÷ϽP†ÝjIét¦µ.öè™7)ƒæÉ£pÀ ÂêÃ9äá�-…ZÖ&|“/wQG^ö O3燞/êÞ7¼Í¡',»š7qÀœ·ú¯ôé;­õâqp€äv°¾u9‰šG�ä6ä?J£ÈÊ\`,ù(Ÿw`¹bÒÈ! Æ<ôq>Ö�puBJ5žBJÚs‘ù8½XÚŽÊ�3ôkÜH©‚÷Ÿƒ#é<y‘oxð¡?#ÈkJg.g‘y:qÑÖØ£dbÂ7z×%¯áæMØ®í„èÿçùøii‰êNµÎÚËüŸ™UëàæÎdtkgui-6.7.46/src/util/icons/deepin-theme-plugin-icons.qrc000066400000000000000000000123541522615413000234500ustar00rootroot00000000000000 texts/caps_lock_16px.svg texts/password_hide_24px.svg texts/password_show_24px.svg texts/edit_12px.svg icons/button_voice_active_30px.svg icons/button_voice_active_press_30px.svg icons/icon_fail_128px.svg icons/icon_success_128px.svg icons/icon_ok_32px.svg icons/icon_info_32px.svg icons/icon_warning_32px.svg texts/button_add_20px.svg texts/button_reduce_12px.svg texts/combobox_arrow_12px.svg texts/audio-volume-left_24px.svg texts/audio-volume-low_24px.svg texts/audio-volume-medium_24px.svg texts/audio-volume-muted_24px.svg texts/audio-volume-right_24px.svg texts/go-down_12px.svg texts/go-next_12px.svg texts/go-previous_12px.svg texts/go-up_12px.svg texts/media-playback-pause_24px.svg texts/media-playback-start_24px.svg texts/media-skip-backward_24px.svg texts/media-skip-forward_24px.svg texts/mark_indicator_12px.svg texts/fork_indicator_24px.svg texts/lock_indicator_24px.svg texts/selected_indicator_16px.svg texts/selected_checked_indicator_16px.svg texts/selected_indicator_16px.svg.background texts/unlock_indicator_24px.svg texts/unselected_indicator_16px.svg texts/window-close_round_30px.svg texts/unchecked_20px.svg texts/checked_20px.svg texts/next_indicator_24px.svg texts/prev_indicator_24px.svg actions/edit-select-all_16px.svg actions/edit-copy_16px.svg actions/edit-cut_16px.svg actions/edit-delete_16px.svg actions/edit-paste_16px.svg actions/edit-redo_16px.svg actions/edit-undo_16px.svg icons/light/edit-clear_30px.svg icons/light/edit-clear_active_30px.svg icons/light/edit-clear_press_30px.svg icons/light/button_voice_30px.svg icons/light/button_voice_press_30px.svg icons/light/list_delete_16px.svg icons/light/list_add_16px.svg icons/light/window-close_round_30px.svg icons/light/window-close_round_press_30px.svg icons/light/search_indicator_20px.svg icons/dark/edit-clear_30px.svg icons/dark/edit-clear_active_30px.svg icons/dark/edit-clear_press_30px.svg icons/dark/button_voice_30px.svg icons/dark/button_voice_press_30px.svg icons/dark/list_delete_16px.svg icons/dark/list_add_16px.svg icons/dark/window-close_round_30px.svg icons/dark/window-close_round_press_30px.svg icons/dark/search_indicator_20px.svg dci/sp_ok.dci dci/sp_alert.dci dci/sp_waiting.dci dci/sp_warning.dci dtkgui-6.7.46/src/util/icons/icons/000077500000000000000000000000001522615413000170765ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/icons/button_voice_active_30px.svg000066400000000000000000000033151522615413000245260ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/button_voice_active_press_30px.svg000066400000000000000000000033531522615413000257440ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/000077500000000000000000000000001522615413000200175ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/icons/dark/button_voice_30px.svg000066400000000000000000000041601522615413000241130ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/button_voice_press_30px.svg000066400000000000000000000042321522615413000253270ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/edit-clear_30px.svg000066400000000000000000000042261522615413000234270ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/edit-clear_active_30px.svg000066400000000000000000000043001522615413000247530ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/edit-clear_press_30px.svg000066400000000000000000000043001522615413000246340ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/list_add_16px.svg000066400000000000000000000005671522615413000232110ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/list_delete_16px.svg000066400000000000000000000003621522615413000237140ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/search_indicator_20px.svg000066400000000000000000000022001522615413000247040ustar00rootroot00000000000000 ç”»æ�¿ dtkgui-6.7.46/src/util/icons/icons/dark/window-close_round_30px.svg000066400000000000000000000042261522615413000252370ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dark/window-close_round_press_30px.svg000066400000000000000000000043001522615413000264440ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dialog-right_30px.svg000066400000000000000000000021511522615413000230420ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/dialog-warning_30px.svg000066400000000000000000000024341522615413000233760ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/icon_fail_128px.svg000066400000000000000000000035001522615413000225020ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/icon_info_32px.svg000066400000000000000000000034421522615413000224410ustar00rootroot00000000000000 info dtkgui-6.7.46/src/util/icons/icons/icon_ok_32px.svg000066400000000000000000000031271522615413000221170ustar00rootroot00000000000000 ok dtkgui-6.7.46/src/util/icons/icons/icon_success_128px.svg000066400000000000000000000032641522615413000232460ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/icon_warning_32px.svg000066400000000000000000000033401522615413000231500ustar00rootroot00000000000000 warning dtkgui-6.7.46/src/util/icons/icons/light/000077500000000000000000000000001522615413000202055ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/icons/light/button_voice_30px.svg000066400000000000000000000035761522615413000243130ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/button_voice_press_30px.svg000066400000000000000000000040521522615413000255150ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/edit-clear_30px.svg000066400000000000000000000036441522615413000236200ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/edit-clear_active_30px.svg000066400000000000000000000056411522615413000251520ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/edit-clear_press_30px.svg000066400000000000000000000056411522615413000250330ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/list_add_16px.svg000066400000000000000000000006551522615413000233750ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/list_delete_16px.svg000066400000000000000000000003621522615413000241020ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/search_indicator_20px.svg000066400000000000000000000021771522615413000251070ustar00rootroot00000000000000 ç”»æ�¿ dtkgui-6.7.46/src/util/icons/icons/light/window-close_round_30px.svg000066400000000000000000000036441522615413000254300ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/icons/light/window-close_round_press_30px.svg000066400000000000000000000056411522615413000266430ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/000077500000000000000000000000001522615413000171325ustar00rootroot00000000000000dtkgui-6.7.46/src/util/icons/texts/audio-volume-left_24px.svg000066400000000000000000000014141522615413000240660ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/audio-volume-low_24px.svg000066400000000000000000000011521522615413000237340ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/audio-volume-medium_24px.svg000066400000000000000000000021401522615413000244110ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/audio-volume-muted_24px.svg000066400000000000000000000021161522615413000242520ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/audio-volume-right_24px.svg000066400000000000000000000022441522615413000242530ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/button_add_20px.svg000066400000000000000000000004051522615413000226460ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/button_reduce_12px.svg000066400000000000000000000003011522615413000233610ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/caps_lock_16px.svg000066400000000000000000000007061522615413000224720ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/checked_20px.svg000066400000000000000000000032101522615413000221060ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/combobox_arrow_12px.svg000066400000000000000000000002721522615413000235500ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/edit_12px.svg000066400000000000000000000010171522615413000214510ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/fork_indicator_24px.svg000066400000000000000000000005721522615413000235310ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/go-down_12px.svg000066400000000000000000000003371522615413000221020ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/go-next_12px.svg000066400000000000000000000002721522615413000221070ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/go-previous_12px.svg000066400000000000000000000002631522615413000230050ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/go-up_12px.svg000066400000000000000000000003261522615413000215550ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/lock_indicator_24px.svg000066400000000000000000000017351522615413000235220ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/mark_indicator_12px.svg000066400000000000000000000003301522615413000235070ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/media-playback-pause_24px.svg000066400000000000000000000004631522615413000245110ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/media-playback-start_24px.svg000066400000000000000000000005531522615413000245310ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/media-skip-backward_24px.svg000066400000000000000000000015551522615413000243350ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/media-skip-forward_24px.svg000066400000000000000000000015131522615413000242150ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/next_indicator_24px.svg000066400000000000000000000004741522615413000235470ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/password_hide_24px.svg000066400000000000000000000024271522615413000233700ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/password_show_24px.svg000066400000000000000000000014301522615413000234300ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/prev_indicator_24px.svg000066400000000000000000000005511522615413000235410ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/selected_checked_indicator_16px.svg000066400000000000000000000013071522615413000260240ustar00rootroot00000000000000 selected_foreground dtkgui-6.7.46/src/util/icons/texts/selected_indicator_16px.svg000066400000000000000000000013071522615413000243560ustar00rootroot00000000000000 selected_foreground dtkgui-6.7.46/src/util/icons/texts/selected_indicator_16px.svg.background000066400000000000000000000010241522615413000264700ustar00rootroot00000000000000 selected_background dtkgui-6.7.46/src/util/icons/texts/unchecked_20px.svg000066400000000000000000000013241522615413000224550ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/unlock_indicator_24px.svg000066400000000000000000000020201522615413000240510ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/unselected_indicator_16px.svg000066400000000000000000000007301522615413000247200ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/icons/texts/window-close_round_30px.svg000066400000000000000000000010251522615413000243440ustar00rootroot00000000000000 dtkgui-6.7.46/src/util/private/000077500000000000000000000000001522615413000163225ustar00rootroot00000000000000dtkgui-6.7.46/src/util/private/dbuiltiniconengine.cpp000066400000000000000000000374141522615413000227100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dbuiltiniconengine_p.h" #include #include #include #include #include #include #include #include #include #include #define BUILTIN_ICON_PATH ":/icons/deepin/builtin" DGUI_BEGIN_NAMESPACE static qreal devicePixelRatio(QPainter *painter) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (qApp->testAttribute(Qt::AA_UseHighDpiPixmaps)) return (painter && painter->device()) ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio(); return 1.0; #else return (painter && painter->device()) ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio(); #endif } class Q_DECL_HIDDEN ImageEntry : public QIconLoaderEngineEntry { public: enum Type { TextType, // 完全跟éš�画笔å‰�景色å�˜åŒ– ActionType, // å�ªåœ¨é�žnormal状æ€�下跟éš�画笔å‰�景色 IconType // 任务状æ€�都ä¸�è·Ÿéš�画笔颜色 }; ImageEntry(Type t) : type(t) { } QString pmcKey(const QSize &size, QIcon::Mode mode, QIcon::State state) { return QLatin1String("$qt_icon_") + filename + QLatin1String("_") + QString::number((((((qint64(size.width()) << 11) | size.height()) << 11) | mode) << 4) | state, 16); } void genIconTypeIcon(QPixmap &pm, QIcon::Mode mode) { if (type == IconType && qobject_cast(QCoreApplication::instance())) { const QPixmap generated = QGuiApplicationPrivate::instance()->applyQIconStyleHelper(mode, pm); if (!generated.isNull()) pm = generated; } } #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override { #else QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override { #endif Q_UNUSED(state) #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) const QSize pixmapSize = size * scale; #else const QSize pixmapSize(size); #endif QPixmap pm; QString pmckey(pmcKey(pixmapSize, mode, state)); if (QPixmapCache::find(pmckey, &pm)) { genIconTypeIcon(pm, mode); return pm; } // png 会读å�–å‰�8个 bit 对比,需è¦�关闭é‡�新打开,å�¦åˆ™å�Œä¸€ä¸ª icon ä¸�å�Œ state/mode 会å†�次读å�–时报错导致 pixmap 为空。 // 所以此处å�ªå¯¹ DirImageEntry(isdir==true) 进行判断ä¸�å†�é‡�新调用 setFileName if (Q_UNLIKELY(!reader.device()) || !QFileInfo(filename).isDir()) { reader.setFileName(filename); } if (dir.type == QIconDirInfo::Scalable) reader.setScaledSize(pixmapSize); pm = QPixmap::fromImageReader(&reader); if (!pm.isNull()) QPixmapCache::insert(pmckey, pm); genIconTypeIcon(pm, mode); return pm; } Type type; QImageReader reader; }; static QPixmap compositedPixmap(QIcon::Mode mode, QPixmap &pm, QIconLoaderEngineEntry *entry, QPainter *painter = nullptr) { ImageEntry::Type type = static_cast(entry)->type; if (type == ImageEntry::TextType || (type == ImageEntry::ActionType && mode != QIcon::Normal)) { QPainter pa(&pm); QColor color; pa.setCompositionMode(QPainter::CompositionMode_SourceIn); if (painter) { color = painter->pen().brush().color(); } else { auto palette = qApp->palette(); color = (mode == QIcon::Selected) ? palette.highlightedText().color() : palette.windowText().color(); } pa.fillRect(pm.rect(), color); } return pm; } class Q_DECL_HIDDEN DirImageEntry : public ImageEntry { public: using ImageEntry::ImageEntry; static QString getIconFile(const QString &key, const QDir &dir, const QString &suffix) { if (dir.exists(key + "." + suffix)) { return dir.filePath(key + "." + suffix); } int _index = key.indexOf('_'); if (_index > 0) { const QString &mode = key.left(_index); if (dir.exists(mode + "." + suffix)) { return dir.filePath(mode + "." + suffix); } const QString &state = key.mid(_index); if (dir.exists("normal" + state + "." + suffix)) { return dir.filePath("normal" + state + "." + suffix); } } return dir.filePath("normal." + suffix); } #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override { #else QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override { #endif if (iconFileMap.isEmpty()) { const QString &suffix = QFileInfo(filename).suffix(); QDir dir(filename); iconFileMap[QIcon::Disabled << 8 | QIcon::On] = getIconFile("disabled_on", dir, suffix); iconFileMap[QIcon::Disabled << 8 | QIcon::Off] = getIconFile("disabled_off", dir, suffix); iconFileMap[QIcon::Active << 8 | QIcon::On] = getIconFile("active_on", dir, suffix); iconFileMap[QIcon::Active << 8 | QIcon::Off] = getIconFile("active_off", dir, suffix); iconFileMap[QIcon::Selected << 8 | QIcon::On] = getIconFile("selected_on", dir, suffix); iconFileMap[QIcon::Selected << 8 | QIcon::Off] = getIconFile("selected_off", dir, suffix); iconFileMap[QIcon::Normal << 8 | QIcon::On] = getIconFile("normal_on", dir, suffix); iconFileMap[QIcon::Normal << 8 | QIcon::Off] = getIconFile("normal_off", dir, suffix); } reader.setFileName(iconFileMap.value(mode << 8 | state)); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) return ImageEntry::pixmap(size, mode, state, scale); #else return ImageEntry::pixmap(size, mode, state); #endif } QMap iconFileMap; }; DBuiltinIconEngine::DBuiltinIconEngine(const QString &iconName) : m_iconName(iconName) , m_initialized(false) // 当主题å��称中包å�«'/'æ—¶, '/'å‰�é�¢çš„部分å�³ä¸ºæŒ‡å®šçš„图标类型, 此时ä¸�需è¦�å†� // è·Ÿéš�系统中的主题类型改å�˜ , m_followSystemTheme(iconName.indexOf('/') < 0) { // åˆ�始化图标类型 m_key = iconName.startsWith("dark/") ? DGuiApplicationHelper::DarkType : DGuiApplicationHelper::LightType; } DBuiltinIconEngine::DBuiltinIconEngine(const DBuiltinIconEngine &other) : QIconEngine(other) , m_iconName(other.m_iconName) , m_key(other.m_key) , m_initialized(other.m_initialized) , m_followSystemTheme(other.m_initialized) { } DBuiltinIconEngine::~DBuiltinIconEngine() { #if QT_VERSION <= QT_VERSION_CHECK(6, 2, 4) if (hasIcon()) qDeleteAll(m_info.entries); #endif } QSize DBuiltinIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) { Q_UNUSED(mode); Q_UNUSED(state); ensureLoaded(); QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, size); if (entry) { const QIconDirInfo &dir = entry->dir; if (dir.type == QIconDirInfo::Scalable) { return size; } else { int result = qMin(dir.size, qMin(size.width(), size.height())); return QSize(result, result); } } return QSize(0, 0); } QPixmap DBuiltinIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) { ensureLoaded(); QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, size); if (entry) { #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) auto pm = entry->pixmap(size, mode, state, devicePixelRatio(nullptr)); #else auto pm = entry->pixmap(size, mode, state); #endif return compositedPixmap(mode, pm, entry); } return QPixmap(); } static QIconLoaderEngineEntry *perfectEntryForSize(const QThemeIconInfo &info, const QSize &size, qreal scale = 1) { const int numEntries = info.entries.size(); const int iconsize = qMin(size.width(), size.height()); for (int i = 0; i < numEntries; ++i) { const auto &entry = info.entries.at(i); if (static_cast(entry->dir.size * scale) == iconsize) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) return entry.get(); #else return info.entries.at(i); #endif } return nullptr; } void DBuiltinIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { ensureLoaded(); const qreal scale = devicePixelRatio(painter); QSize pixmapSize = rect.size() * scale; // Search perfect entry first QIconLoaderEngineEntry *entry = perfectEntryForSize(m_info, pixmapSize, scale); if (!entry) { entry = QIconLoaderEngine::entryForSize(m_info, pixmapSize); if (!entry) return; } // 如果有 background 则绘制背景图先 QString bgFileName = entry->filename + QStringLiteral(".background"); if (QFile::exists(bgFileName)) { QIcon(bgFileName).paint(painter, rect, Qt::AlignCenter, mode, state); } #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) QPixmap pm = entry->pixmap(pixmapSize, mode, state, 1.0); #else QPixmap pm = entry->pixmap(pixmapSize, mode, state); #endif pm = compositedPixmap(mode, pm, entry, painter); pm.setDevicePixelRatio(scale); painter->drawPixmap(rect, pm); } QString DBuiltinIconEngine::key() const { return QLatin1String("DBuiltinIconEngine"); } QIconEngine *DBuiltinIconEngine::clone() const { return new DBuiltinIconEngine(*this); } bool DBuiltinIconEngine::read(QDataStream &in) { // QDataStreamä¸�支æŒ�ä½�æ•°æ�®, 此处先将内容转为正常类型 uint key = m_key; bool followSystemTheme = m_followSystemTheme; in >> m_iconName >> key >> followSystemTheme; m_key = key; m_followSystemTheme = followSystemTheme; return true; } bool DBuiltinIconEngine::write(QDataStream &out) const { out << m_iconName << m_key << m_followSystemTheme; return true; } QString DBuiltinIconEngine::iconName() #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) const #endif { return m_iconName; } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QList DBuiltinIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state) { Q_UNUSED(mode); Q_UNUSED(state); ensureLoaded(); QList sizes; const int N = m_info.entries.size(); sizes.reserve(N); // Gets all sizes from the DirectoryInfo entries for (int i = 0; i < N; ++i) { const auto& entry = m_info.entries.at(i); int size = entry->dir.size; sizes.append(QSize(size, size)); } return sizes; } #endif QThemeIconInfo DBuiltinIconEngine::loadIcon(const QString &iconName, uint key) { QThemeIconInfo info; info.iconName = iconName; QString theme_name = (key == DGuiApplicationHelper::DarkType ? "dark" : "light"); QStringList iconDirList { QString("%1/%2/texts").arg(BUILTIN_ICON_PATH, theme_name), QString("%1/%2/actions").arg(BUILTIN_ICON_PATH, theme_name), QString("%1/%2/icons").arg(BUILTIN_ICON_PATH, theme_name), QString("%1/texts").arg(BUILTIN_ICON_PATH), QString("%1/actions").arg(BUILTIN_ICON_PATH), QString("%1/icons").arg(BUILTIN_ICON_PATH) }; QDir dir; dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); for (int i = 0; i < iconDirList.count(); ++i) { dir.setPath(iconDirList.at(i)); if (!dir.exists()) { continue; } ImageEntry::Type type = static_cast(i % 3); for (const QFileInfo &icon_file_info : dir.entryInfoList()) { const QString &file_name = icon_file_info.fileName(); // do not load background file if (!file_name.startsWith(iconName) || file_name.endsWith(QStringLiteral(".background"))) continue; // 先找到px所在ä½�ç½® int size_str_pos = iconName.length() + 1; int px_str_pos = file_name.indexOf("px.", size_str_pos + 1); if (px_str_pos < 0) continue; bool ok = false; int size = file_name.mid(size_str_pos, px_str_pos - size_str_pos).toInt(&ok); if (Q_UNLIKELY(!ok || size <= 0)) { continue; } ImageEntry *entry = icon_file_info.isDir() ? new DirImageEntry(type) : new ImageEntry(type); entry->filename = icon_file_info.absoluteFilePath(); entry->dir.path = icon_file_info.absolutePath(); entry->dir.size = size; entry->dir.type = icon_file_info.suffix().startsWith("svg") ? QIconDirInfo::Scalable : QIconDirInfo::Fixed; #if QT_VERSION <= QT_VERSION_CHECK(6, 2, 4) info.entries.append(entry); #else info.entries.push_back(std::unique_ptr(entry)); #endif } // å·²ç»�找到图标时ä¸�å†�ç»§ç»­ if (info.entries.size() > 0) { break; } } return info; } bool DBuiltinIconEngine::hasIcon() const { return m_info.entries.size() > 0; } void DBuiltinIconEngine::virtual_hook(int id, void *data) { ensureLoaded(); switch (id) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) case QIconEngine::AvailableSizesHook: { QIconEngine::AvailableSizesArgument &arg = *reinterpret_cast(data); const int N = m_info.entries.size(); QList sizes; sizes.reserve(N); // Gets all sizes from the DirectoryInfo entries for (int i = 0; i < N; ++i) { const QIconLoaderEngineEntry *entry = m_info.entries.at(i); int size = entry->dir.size; sizes.append(QSize(size, size)); } arg.sizes.swap(sizes); // commit } break; case QIconEngine::IconNameHook: { QString &name = *reinterpret_cast(data); name = m_info.iconName; } break; #endif case QIconEngine::IsNullHook: { *reinterpret_cast(data) = !hasIcon(); } break; case QIconEngine::ScaledPixmapHook: { QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast(data); // QIcon::pixmap() multiplies size by the device pixel ratio. const int integerScale = qCeil(arg.scale); QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, arg.size / integerScale, integerScale); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state, arg.scale) : QPixmap(); #else arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap(); if (!arg.pixmap.isNull()) { arg.pixmap = compositedPixmap(arg.mode, arg.pixmap, entry); } #endif } break; default: QIconEngine::virtual_hook(id, data); } } void DBuiltinIconEngine::ensureLoaded() { if (Q_LIKELY(m_followSystemTheme) && Q_UNLIKELY(DGuiApplicationHelper::instance()->themeType() != m_key)) { m_initialized = false; // 记录当å‰�使用的主题类型 m_key = DGuiApplicationHelper::instance()->themeType(); } if (Q_LIKELY(m_initialized)) { return; } // 标记为已åˆ�始化 m_initialized = true; #if QT_VERSION <= QT_VERSION_CHECK(6, 2, 4) qDeleteAll(m_info.entries); #endif m_info.entries.clear(); m_info.iconName.clear(); Q_ASSERT(m_info.entries.size() == 0); m_info = loadIcon(m_iconName, m_key); } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/private/dbuiltiniconengine_p.h000066400000000000000000000035411522615413000226660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DBUILTINICONENGINE_H #define DBUILTINICONENGINE_H #include #include #include DGUI_BEGIN_NAMESPACE // 内置的主题引擎,会从Qt资æº�文件中查找图标 class DBuiltinIconEnginePrivate; class Q_DECL_HIDDEN DBuiltinIconEngine : public QIconEngine { public: explicit DBuiltinIconEngine(const QString &iconName); ~DBuiltinIconEngine() override; void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QString key() const override; QIconEngine *clone() const override; bool read(QDataStream &in) override; bool write(QDataStream &out) const override; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QString iconName() override; QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override; #else QString iconName() const override; #endif static QThemeIconInfo loadIcon(const QString &iconName, uint key); private: bool hasIcon() const; void ensureLoaded(); void virtual_hook(int id, void *data) override; DBuiltinIconEngine(const DBuiltinIconEngine &other); QThemeIconInfo m_info; QString m_iconName; // 图标的类型(Dark/Light) uint m_key:2; // 记录是å�¦å·²ç»�åˆ�始化 bool m_initialized:1; // 控制是å�¦è·Ÿéš�系统级别的主题色æ�¥æ”¹å�˜å›¾æ ‡ç±»åž‹ bool m_followSystemTheme:1; friend class QIconLoader; }; DGUI_END_NAMESPACE #endif // DBUILTINICONENGINE_H dtkgui-6.7.46/src/util/private/dciiconengine.cpp000066400000000000000000000145671522615413000216410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dciiconengine_p.h" #include "dguiapplicationhelper.h" #include "dplatformtheme.h" #include #include #include #include #include DGUI_BEGIN_NAMESPACE static inline DDciIcon::Theme dciTheme() { auto theme = DGuiApplicationHelper::instance()->themeType(); return theme == DGuiApplicationHelper::DarkType ? DDciIcon::Dark : DDciIcon::Light; } static inline DDciIcon::Mode dciMode(QIcon::Mode mode) { // QIcon only support DDciIcon::Disabled and DDciIcon::Normal return mode == QIcon::Disabled ? DDciIcon::Disabled : DDciIcon::Normal; } static inline DDciIconPalette dciPalettle(QPaintDevice *paintDevice = nullptr) { QPalette pa; if (!paintDevice || paintDevice->devType() != QInternal::Widget) { pa = qApp->palette(); } else if (QObject *obj = dynamic_cast(paintDevice)) { pa = qvariant_cast(obj->property("palette")); } else { pa = qApp->palette(); } return DDciIconPalette(pa.windowText().color(), pa.window().color(), pa.highlight().color(), pa.highlightedText().color()); } static inline qreal deviceRadio(QPaintDevice *paintDevice = nullptr) { qreal scale = 1.0; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (qApp->testAttribute(Qt::AA_UseHighDpiPixmaps)) scale = paintDevice ? paintDevice->devicePixelRatioF() : qApp->devicePixelRatio(); #else scale = paintDevice ? paintDevice->devicePixelRatioF() : qApp->devicePixelRatio(); #endif return scale; } DDciIconEngine::DDciIconEngine(const QString &iconName) : m_iconName(iconName) , m_iconThemeName(DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName()) , m_dciIcon(DDciIcon::fromTheme(iconName)) { } DDciIconEngine::DDciIconEngine(const DDciIconEngine &other) : QIconEngine(other) , m_iconName(other.m_iconName) , m_iconThemeName(other.m_iconThemeName) , m_dciIcon(other.m_dciIcon) { } DDciIconEngine::~DDciIconEngine() { } QSize DDciIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) { Q_UNUSED(state); ensureIconTheme(); int s = m_dciIcon.actualSize(qMin(size.width(), size.height()), dciTheme(), dciMode(mode)); return QSize(s, s).boundedTo(size); } QPixmap DDciIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) { // QIcon::pixmap has already been multiplied by the screen scaling factor // so there is no need to do it again here. set radio 1.0 . return pixmap(size, mode, state, 1.0); } QPixmap DDciIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal radio) { Q_UNUSED(state); const int s = qMin(size.width(), size.height()); const DDciIcon::Theme theme = dciTheme(); const DDciIconPalette pa = dciPalettle(); QString key = QLatin1String("dci_") + m_iconName + m_iconThemeName + DDciIconPalette::convertToString(pa) % HexString(mode) % HexString(theme) % HexString(s) % HexString(uint(radio * 100)); QPixmap pix; if (QPixmapCache::find(key, &pix)) return pix; ensureIconTheme(); pix = m_dciIcon.pixmap(radio, s, theme, dciMode(mode), pa); if (!pix.isNull()) QPixmapCache::insert(key, pix); return pix; } void DDciIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { Q_UNUSED(state); ensureIconTheme(); m_dciIcon.paint(painter, rect, deviceRadio(painter->device()), dciTheme(), dciMode(mode), Qt::AlignCenter, dciPalettle(painter->device())); } QString DDciIconEngine::key() const { return QLatin1String("DDciIconEngine"); } QIconEngine *DDciIconEngine::clone() const { return new DDciIconEngine(*this); } bool DDciIconEngine::read(QDataStream &in) { ensureIconTheme(); in >> m_iconThemeName >> m_iconName >> m_dciIcon; return true; } bool DDciIconEngine::write(QDataStream &out) const { const_cast(this)->ensureIconTheme(); out << m_iconThemeName << m_iconName << m_dciIcon; return true; } QString DDciIconEngine::iconName() #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) const #endif { return m_iconName; } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QList DDciIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state) { Q_UNUSED(state); ensureIconTheme(); const auto availableSizes = m_dciIcon.availableSizes(dciTheme(), dciMode(mode)); QList sizes; sizes.reserve(availableSizes.size()); for (int size : availableSizes) sizes.append(QSize(size, size)); return sizes; } #endif void DDciIconEngine::virtual_hook(int id, void *data) { ensureIconTheme(); switch (id) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) case QIconEngine::AvailableSizesHook: { auto &arg = *reinterpret_cast(data); auto availableSizes = m_dciIcon.availableSizes(dciTheme(), DDciIcon::Normal); QList sizes; sizes.reserve(availableSizes.size()); for (int size : availableSizes) sizes.append(QSize(size, size)); arg.sizes.swap(sizes); // commit } break; case QIconEngine::IconNameHook: { QString &name = *reinterpret_cast(data); name = iconName(); } break; #endif case QIconEngine::IsNullHook: { *reinterpret_cast(data) = m_dciIcon.isNull(); } break; case QIconEngine::ScaledPixmapHook: { QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast(data); arg.pixmap = pixmap(arg.size, arg.mode, arg.state); } break; default: QIconEngine::virtual_hook(id, data); } } void DDciIconEngine::ensureIconTheme() { QString iconThemeName = DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName(); if (m_iconThemeName != iconThemeName) { m_iconThemeName = iconThemeName; // update dci icon when icon theme name changed. m_dciIcon = DDciIcon::fromTheme(m_iconName); } } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/private/dciiconengine_p.h000066400000000000000000000027021522615413000216110ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DDCIICONENGINE_H #define DDCIICONENGINE_H #include #include "ddciicon.h" #include DGUI_BEGIN_NAMESPACE class Q_DECL_HIDDEN DDciIconEngine : public QIconEngine { public: explicit DDciIconEngine(const QString &iconName); virtual ~DDciIconEngine() override; void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal radio); QString key() const override; QIconEngine *clone() const override; bool read(QDataStream &in) override; bool write(QDataStream &out) const override; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QString iconName() override; QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override; #else QString iconName() const override; #endif private: void virtual_hook(int id, void *data) override; void ensureIconTheme(); DDciIconEngine(const DDciIconEngine &other); QString m_iconName; QString m_iconThemeName; DDciIcon m_dciIcon; }; DGUI_END_NAMESPACE #endif // DDCIICONENGINE_H dtkgui-6.7.46/src/util/private/diconproxyengine.cpp000066400000000000000000000167661522615413000224320ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "diconproxyengine_p.h" #include "dciiconengine_p.h" #include "dbuiltiniconengine_p.h" #include "xdgiconproxyengine_p.h" #include #include #include #include #include #include #include #include #include #if (XDG_ICON_VERSION_MAR >= 3) #include #endif #include #include DGUI_BEGIN_NAMESPACE static inline QString iconThemeName() { return DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName(); } static inline QIconEngine *createBuiltinIconEngine(const QString &iconName) { QIconEngine *iconEngine = new DBuiltinIconEngine(iconName); if (iconEngine->isNull()) { delete iconEngine; return nullptr; } return iconEngine; } static inline QIconEngine *createDciIconEngine(const QString &iconName) { QIconEngine *iconEngine = new DDciIconEngine(iconName); if (iconEngine->isNull()) { delete iconEngine; return nullptr; } return iconEngine; } #ifndef DTK_DISABLE_LIBXDG static inline QIconEngine *createXdgProxyIconEngine(const QString &iconName) { QIconEngine *iconEngine = new XdgIconProxyEngine(new XdgIconLoaderEngine(iconName)); if (iconEngine->isNull()) { delete iconEngine; return nullptr; } return iconEngine; } #endif static inline QIconEngine *createDBuiltinIconEngine(const QString &iconName) { static QSet non_builtin_icon_cache; if (!non_builtin_icon_cache.contains(iconName)) { // 记录下æ�¥æ­¤ç§�类型的icon为内置图标 // 因此,此处添加的缓存ä¸�考虑更新 // 优先使用内置图标 if (QIconEngine *engine = createBuiltinIconEngine(iconName)) { if (engine->isNull()) { delete engine; return nullptr; } return engine; } else { non_builtin_icon_cache.insert(iconName); } } return nullptr; } static bool hasDciIcon(const QString &iconName, const QString &iconThemeName) { QString iconPath; if (auto cached = DIconTheme::cached()) { iconPath = cached->findDciIconFile(iconName, iconThemeName); } else { iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName); } return !iconPath.isEmpty(); } static inline bool isDciIconEngine(QIconEngine *engine) { return dynamic_cast(engine); } DIconProxyEngine::DIconProxyEngine(const QString &iconName, DIconTheme::Options options) : m_iconName(iconName) , m_option(options) { ensureEngine(); } DIconProxyEngine::DIconProxyEngine(const DIconProxyEngine &other) : QIconEngine(other) , m_iconName(other.m_iconName) , m_iconThemeName(other.m_iconThemeName) , m_iconEngine(other.m_iconEngine->clone()) { ensureEngine(); } DIconProxyEngine::~DIconProxyEngine() { if (m_iconEngine) delete m_iconEngine; } QSize DIconProxyEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) { ensureEngine(); return m_iconEngine ? m_iconEngine->actualSize(size, mode, state) :QSize(); } QPixmap DIconProxyEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) { ensureEngine(); return m_iconEngine ? m_iconEngine->pixmap(size, mode, state) : QPixmap(); } void DIconProxyEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { ensureEngine(); if (m_iconEngine) m_iconEngine->paint(painter, rect, mode, state); } QString DIconProxyEngine::key() const { return QLatin1String("DIconProxyEngine"); } QIconEngine *DIconProxyEngine::clone() const { return new DIconProxyEngine(*this); } bool DIconProxyEngine::read(QDataStream &in) { in >> m_iconName >> m_iconThemeName; ensureEngine(); return m_iconEngine ? m_iconEngine->read(in) : false; } bool DIconProxyEngine::write(QDataStream &out) const { out << m_iconName << m_iconThemeName; return m_iconEngine ? m_iconEngine->write(out) : false; } QString DIconProxyEngine::iconName() #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) const #endif { return m_iconEngine ? m_iconEngine->iconName() : QString(); } QList DIconProxyEngine::availableSizes(QIcon::Mode mode, QIcon::State state) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) const #endif { return m_iconEngine ? m_iconEngine->availableSizes(mode, state) : QIconEngine::availableSizes(mode, state); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool DIconProxyEngine::isNull() { return m_iconEngine ? m_iconEngine->isNull() : QIconEngine::isNull(); } #endif QString DIconProxyEngine::proxyKey() { ensureEngine(); return m_iconEngine ? m_iconEngine->key() : QString(); } void DIconProxyEngine::virtual_hook(int id, void *data) { ensureEngine(); if (m_iconEngine) { m_iconEngine->virtual_hook(id, data); return; } switch (id) { case QIconEngine::IsNullHook: { *reinterpret_cast(data) = true; } break; default: QIconEngine::virtual_hook(id, data); } } void DIconProxyEngine::ensureEngine() { if (m_iconName.isEmpty()) return; const QString &theme = iconThemeName(); if (theme == m_iconThemeName && m_iconEngine) return; static QMap> nonCache; if (Q_UNLIKELY(!m_option.testFlag(DIconTheme::IgnoreIconCache))) { const auto it = nonCache.find(theme); if (it != nonCache.end() && it->contains(m_iconName)) return; } if (m_iconEngine) { // dci => dci // xdg => xdg if (!(hasDciIcon(m_iconName, theme) ^ isDciIconEngine(m_iconEngine))) { m_iconThemeName = theme; return; } // delete old engine and create a new engine delete m_iconEngine; m_iconEngine = nullptr; } // null => dci // null => xdg // dci => xdg // xdg => dci // 1. try create dci iconengine // 2. try create builtin iconengine // 3. create xdgiconproxyengine if (!m_iconEngine && Q_UNLIKELY(!m_option.testFlag(DIconTheme::IgnoreDciIcons))) { m_iconEngine = createDciIconEngine(m_iconName); } if (!m_iconEngine && Q_UNLIKELY(!m_option.testFlag(DIconTheme::IgnoreBuiltinIcons)) ) { m_iconEngine = createDBuiltinIconEngine(m_iconName); } #ifndef DTK_DISABLE_LIBXDG if (!m_iconEngine) { m_iconEngine = createXdgProxyIconEngine(m_iconName); } #endif // Fallback to Qt's native icon engine for icons only found in /usr/share/pixmaps // or other non-themed locations that XdgIconLoader cannot render correctly // (e.g. xscreensaver). Also serves as fallback when libxdg is disabled. if (!m_iconEngine) { QPlatformTheme * const platformTheme = QGuiApplicationPrivate::platformTheme(); if (platformTheme) { m_iconEngine = platformTheme->QPlatformTheme::createIconEngine(m_iconName); } } if (!m_iconEngine && !nonCache[theme].contains(m_iconName)) { qWarning() << "create icon [" << m_iconName << "] engine failed." << "theme:" << theme << "and nonCache's size:" << nonCache.size(); nonCache[theme].insert(m_iconName); return; } m_iconThemeName = theme; } DGUI_END_NAMESPACE dtkgui-6.7.46/src/util/private/diconproxyengine_p.h000066400000000000000000000034301522615413000223760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DICONPROXYENGINE_H #define DICONPROXYENGINE_H #include #include #include "dicontheme.h" DGUI_BEGIN_NAMESPACE class Q_DECL_HIDDEN DIconProxyEngine : public QIconEngine { public: explicit DIconProxyEngine(const QString &iconName, DIconTheme::Options m_option); virtual ~DIconProxyEngine() override; void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QString key() const override; QIconEngine *clone() const override; bool read(QDataStream &in) override; bool write(QDataStream &out) const override; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QString iconName() override; #else QString iconName() const override; #endif #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override; #else QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const override; #endif #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool isNull() override; #endif inline QString themeName() const { return m_iconThemeName; } QString proxyKey(); private: void virtual_hook(int id, void *data) override; void ensureEngine(); DIconProxyEngine(const DIconProxyEngine &other); QString m_iconName; QString m_iconThemeName; QIconEngine *m_iconEngine = nullptr; DIconTheme::Options m_option; }; DGUI_END_NAMESPACE #endif // DICONPROXYENGINE_H dtkgui-6.7.46/src/util/private/dimagehandlerlibs_p.h000066400000000000000000000106301522615413000224500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DIMAGEHANDLERLIBS_P_H #define DIMAGEHANDLERLIBS_P_H #ifndef DTK_DISABLE_EX_IMAGE_FORMAT #include #include #include #include #include class QLibrary; #endif enum ExifImageOrientation { Undefined, TopLeft, TopRight, BottomRight, BottomLeft, LeftTop, RightTop, RightBottom, LeftBottom, }; #ifndef DTK_DISABLE_EX_IMAGE_FORMAT class DLibFreeImage { public: DLibFreeImage(); ~DLibFreeImage(); bool isValid(); bool findMetaData(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, QHash &data); QHash findAllMetaData(const QString &fileName); FIBITMAP *readFileToFIBITMAP(const QString &fileName, int flags = 0, FREE_IMAGE_FORMAT fif = FIF_UNKNOWN); bool writeFIBITMAPToFile(FIBITMAP *dib, const QString &fileName, int flags = 0); QImage FIBITMAPToQImage(FIBITMAP *dib) const; ExifImageOrientation imageOrientation(const QString &fileName); bool rotateImageFile(const QString &fileName, int angle, QString &errorString); FIBITMAP *(*FreeImage_Load)(FREE_IMAGE_FORMAT fif, const char *filename, int flags); void (*FreeImage_Unload)(FIBITMAP *dib); bool (*FreeImage_Save)(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags); bool (*FreeImage_FIFSupportsReading)(FREE_IMAGE_FORMAT fif); FREE_IMAGE_FORMAT (*FreeImage_GetFileType)(const char *filename, int size); FREE_IMAGE_FORMAT (*FreeImage_GetFIFFromFilename)(const char *filename); FREE_IMAGE_TYPE (*FreeImage_GetImageType)(FIBITMAP *dib); unsigned (*FreeImage_GetBPP)(FIBITMAP *dib); unsigned (*FreeImage_GetWidth)(FIBITMAP *dib); unsigned (*FreeImage_GetHeight)(FIBITMAP *dib); unsigned (*FreeImage_GetRedMask)(FIBITMAP *dib); unsigned (*FreeImage_GetGreenMask)(FIBITMAP *dib); unsigned (*FreeImage_GetBlueMask)(FIBITMAP *dib); FIBITMAP *(*FreeImage_GetThumbnail)(FIBITMAP *dib); bool (*FreeImage_SetThumbnail)(FIBITMAP *dib, FIBITMAP *thumbnail); void (*FreeImage_ConvertToRawBits)(uint8_t *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, bool topdown); unsigned (*FreeImage_GetMetadataCount)(FREE_IMAGE_MDMODEL model, FIBITMAP *dib); FIMETADATA *(*FreeImage_FindFirstMetadata)(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag); bool (*FreeImage_FindNextMetadata)(FIMETADATA *mdhandle, FITAG **tag); void (*FreeImage_FindCloseMetadata)(FIMETADATA *mdhandle); const char *(*FreeImage_GetTagKey)(FITAG *tag); const void *(*FreeImage_GetTagValue)(FITAG *tag); const char *(*FreeImage_TagToString)(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make); FIBITMAP *(*FreeImage_Rotate)(FIBITMAP *dib, double angle, const void *bkcolor); private: QLibrary *freeImage = nullptr; QMutex apiMutex; Q_DISABLE_COPY(DLibFreeImage) }; class DLibRaw { public: DLibRaw(); ~DLibRaw(); bool isValid(); QImage loadImage(const QString &fileName, QString &errString, QSize requestSize = QSize()); QImage loadImage(QByteArray &data, QString &errString, QSize requestSize = QSize()); int readImage(libraw_data_t *rawData, QImage &image, QSize requestSize = QSize()); QString errorString(int errorCode); const char *(*libraw_strerror)(int errorcode); libraw_data_t *(*libraw_init)(unsigned int flags); int (*libraw_open_file)(libraw_data_t *, const char *); int (*libraw_open_buffer)(libraw_data_t *, void *buffer, size_t size); int (*libraw_unpack)(libraw_data_t *); int (*libraw_unpack_thumb)(libraw_data_t *); void (*libraw_close)(libraw_data_t *); int (*libraw_dcraw_process)(libraw_data_t *lr); libraw_processed_image_t *(*libraw_dcraw_make_mem_image)(libraw_data_t *lr, int *errc); libraw_processed_image_t *(*libraw_dcraw_make_mem_thumb)(libraw_data_t *lr, int *errc); void (*libraw_dcraw_clear_mem)(libraw_processed_image_t *); private: QLibrary *libraw = nullptr; Q_DISABLE_COPY(DLibRaw) }; #endif #endif // DIMAGEHANDLERLIBS_P_H dtkgui-6.7.46/src/util/private/xdgiconproxyengine.cpp000066400000000000000000000422611522615413000227560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "xdgiconproxyengine_p.h" #include #include #include #include #include #include #include #include #include #include #include #if XDG_ICON_VERSION_MAR >= 3 #include #include "util/dprivateaccessor_p.h" D_DECLARE_PRIVATE_CONST_METHOD(XdgIconLoader_followColorScheme_tag, XdgIconLoader, followColorScheme, bool); D_DECLARE_PRIVATE_METHOD(XdgIconLoaderEngine_ensureLoaded_tag, XdgIconLoaderEngine, ensureLoaded, void); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) D_DECLARE_PRIVATE_METHOD(XdgIconLoaderEngine_virtualHook_tag, XdgIconLoaderEngine, virtual_hook, void, int, void *); #endif #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) D_DECLARE_PRIVATE_METHOD(XdgIconLoaderEngine_entryForSize_tag, XdgIconLoaderEngine, entryForSize, QIconLoaderEngineEntry *, const QSize &, int); #else D_DECLARE_PRIVATE_MEMBER(XdgIconLoaderEngine_m_info_tag, XdgIconLoaderEngine, m_info, QThemeIconInfo); D_DECLARE_PRIVATE_METHOD(XdgIconLoaderEngine_entryForSize_tag, XdgIconLoaderEngine, entryForSize, QIconLoaderEngineEntry *, const QThemeIconInfo &, const QSize &, int); #endif static inline bool XdgIconFollowColorScheme() { return D_PRIVATE_CALL(*XdgIconLoader::instance(), XdgIconLoader_followColorScheme_tag{}); } static inline QString rgba(const QColor &c) { // Hex-r-g-b-a return c.name(QColor::HexRgb).append(QString::number(c.alpha(), 16)); } static inline QPalette palette(QPaintDevice *paintDevice) { QPalette pa; if (QObject *obj = dynamic_cast(paintDevice)) { pa = qvariant_cast(obj->property("palette")); } else { pa = qApp->palette(); } return pa; } static inline QPixmap entryPixmap(ScalableEntry *color_entry, const QSize &size, QIcon::Mode mode, QIcon::State state) { if (!color_entry) return QPixmap(); // init svgIcon with svg absolute path // force to use svg iconengine if (color_entry->svgIcon.isNull()) color_entry->svgIcon = QIcon(color_entry->filename); if (auto d = color_entry->svgIcon.data_ptr()) if (d->engine) return d->engine->pixmap(size, mode, state); return color_entry->svgIcon.pixmap(size, mode, state); } // Render a scalable SVG entry using DSvgRenderer (backed by librsvg) when available. // // This is a workaround for a long-standing Qt SVG rendering bug: QSvgRenderer // incorrectly renders , , and elements that appear as // direct children of the root element (outside any block) as visible // painted shapes. This causes icons that use such constructs (e.g., many GNOME app // icons like Epiphany) to render with opaque black backgrounds instead of transparent // corners. // // DSvgRenderer uses librsvg via cairo when available, which handles these SVG // features correctly. If librsvg is not installed, DSvgRenderer::isValid() returns // false and we fall back gracefully to the default Qt rendering path (entryPixmap), // preserving existing behavior on systems without librsvg. static QPixmap renderSvgWithLibrsvg(ScalableEntry *entry, const QSize &size, QIcon::Mode mode, QIcon::State state) { DGUI_USE_NAMESPACE DSvgRenderer renderer(entry->filename); if (renderer.isValid()) { QSize actualSize = renderer.defaultSize(); if (!size.isEmpty() && !actualSize.isEmpty()) { if (actualSize.width() < size.width()) actualSize.scale(size, Qt::KeepAspectRatio); } if (!actualSize.isEmpty()) { const QImage img = renderer.toImage(actualSize); if (!img.isNull()) return QPixmap::fromImage( img.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } } // librsvg unavailable or rendering failed — fall back to QIcon-based path return entryPixmap(entry, size, mode, state); } static const QString STYLE = QStringLiteral(".ColorScheme-Text, .ColorScheme-NeutralText{color:%1;}\ \n.ColorScheme-Highlight{color:%2;}"); namespace DEEPIN_XDG_THEME { static QThreadStorage colorScheme; // } DGUI_BEGIN_NAMESPACE XdgIconProxyEngine::XdgIconProxyEngine(XdgIconLoaderEngine *proxy) : engine(proxy) , lastMode(QIcon::Normal) { } XdgIconProxyEngine::~XdgIconProxyEngine() { if (engine) delete engine; } quint64 XdgIconProxyEngine::entryCacheKey(const ScalableEntry *color_entry, const QIcon::Mode mode, const QIcon::State state) { return quint64(color_entry) ^ (quint64(mode) << 56) ^ (quint64(state) << 48); } QPixmap XdgIconProxyEngine::followColorPixmap(ScalableEntry *color_entry, const QSize &size, QIcon::Mode mode, QIcon::State state) { if (mode == QIcon::Selected && mode != lastMode) { // ç”±é�žé€‰ä¸­çжæ€�切æ�¢è‡³é€‰ä¸­çжæ€�,如果颜色值ä¸�更新,会按照上一次的状æ€�(é�žé€‰ä¸­æ—¶çš„颜色值) // 从svg图标缓存中寻找异常图标,导致图标异常。 for (int each_mode = QIcon::Normal; each_mode <= QIcon::Selected; ++each_mode) { quint64 each_cache_key = entryCacheKey(color_entry, QIcon::Mode(each_mode), state); entryToColorScheme.remove(each_cache_key); } } lastMode = mode; quint64 cache_key = entryCacheKey(color_entry, mode, state); const DEEPIN_XDG_THEME::PALETTE_MAP &cache_color_scheme = entryToColorScheme.value(cache_key); // 当size为1时表示此svg文件ä¸�需è¦�处ç�†ColorScheme标签 if (!cache_color_scheme.isEmpty() && cache_color_scheme[DEEPIN_XDG_THEME::Text].size() == 1) return entryPixmap(color_entry, size, mode, state); const DEEPIN_XDG_THEME::PALETTE_MAP &color_scheme = DEEPIN_XDG_THEME::colorScheme.localData(); QPixmap pm = color_scheme == cache_color_scheme ? entryPixmap(color_entry, size, mode, state) : QPixmap(); // Note: not checking the QIcon::isNull(), because in Qt5.10 the isNull() is not reliable // for svg icons desierialized from stream (see https://codereview.qt-project.org/#/c/216086/) if (pm.isNull()) { // The following lines are adapted and updated from KDE's "kiconloader.cpp" -> // KIconLoaderPrivate::processSvg() and KIconLoaderPrivate::createIconImage(). // They read the SVG color scheme of SVG icons and give images based on the icon mode. QHash svg_buffers; bool invalidBuffers = true; QFile device {color_entry->filename}; if (device.open(QIODevice::ReadOnly)) { // Note: indexes are assembled as in qtsvg (QSvgIconEnginePrivate::hashKey()) QPair style_sheet; style_sheet = qMakePair((mode << 4) | state, STYLE.arg(color_scheme[DEEPIN_XDG_THEME::Text], color_scheme[DEEPIN_XDG_THEME::Highlight])); QSharedPointer writer(new QXmlStreamWriter {&svg_buffers[style_sheet.first]}); QXmlStreamReader xmlReader(&device); while (!xmlReader.atEnd()) { if (xmlReader.readNext() == QXmlStreamReader::StartElement && xmlReader.qualifiedName() == QLatin1String("style") && xmlReader.attributes().value(QLatin1String("id")) == QLatin1String("current-color-scheme")) { invalidBuffers = false; writer->writeStartElement(QLatin1String("style")); writer->writeAttributes(xmlReader.attributes()); writer->writeCharacters(style_sheet.second); writer->writeEndElement(); while (xmlReader.tokenType() != QXmlStreamReader::EndElement) xmlReader.readNext(); } else if (xmlReader.tokenType() != QXmlStreamReader::Invalid) { writer->writeCurrentToken(xmlReader); } } // duplicate the contents also for opposite state // svg_buffers[(QIcon::Normal<<4)|QIcon::On] = svg_buffers[(QIcon::Normal<<4)|QIcon::Off]; // svg_buffers[(QIcon::Selected<<4)|QIcon::On] = svg_buffers[(QIcon::Selected<<4)|QIcon::Off]; } if (invalidBuffers) { // æ­¤svg图标无ColorScheme标签时ä¸�应该å†�下é�¢çš„æ“�作,且应该记录下æ�¥ï¼Œé�¿å…�å�Žç»­å†�处ç�†svg文件内容 entryToColorScheme[cache_key] = DEEPIN_XDG_THEME::PALETTE_MAP({ {DEEPIN_XDG_THEME::Text, "#"} }); return entryPixmap(color_entry, size, mode, state); } // use the QSvgIconEngine // - assemble the content as it is done by the operator <<(QDataStream &s, const QIcon &icon) // (the QSvgIconEngine::key() + QSvgIconEngine::write()) // - create the QIcon from the content by usage of the QIcon::operator >>(QDataStream &s, const QIcon &icon) // (icon with the (QSvgIconEngine) will be used) QByteArray icon_arr; QDataStream str {&icon_arr, QIODevice::WriteOnly}; str.setVersion(QDataStream::Qt_4_4); QHash filenames; filenames[0] = color_entry->filename; // Note: filenames are ignored in the QSvgIconEngine::read() filenames[-1] = color_scheme[DEEPIN_XDG_THEME::Text] + color_scheme[DEEPIN_XDG_THEME::Highlight]; // 在dsvgæ�’件中会为svg图标å�šç¼“存,此处是为其添加é¢�外的缓存文件key标识,é�¿å…�ä¸�å�Œcolorçš„svg图标会命中å�Œä¸€ä¸ªç¼“存文件 str << QStringLiteral("svg") << filenames << static_cast(0) /*isCompressed*/ << svg_buffers << static_cast(0) /*hasAddedPimaps*/; QDataStream str_read {&icon_arr, QIODevice::ReadOnly}; str_read.setVersion(QDataStream::Qt_4_4); str_read >> color_entry->svgIcon; pm = entryPixmap(color_entry, size, mode, state); // load the icon directly from file, if still null if (pm.isNull()) { color_entry->svgIcon = QIcon(color_entry->filename); pm = entryPixmap(color_entry, size, mode, state); } entryToColorScheme[cache_key] = color_scheme; } return pm; } QPixmap XdgIconProxyEngine::pixmapByEntry(QIconLoaderEngineEntry *entry, const QSize &size, QIcon::Mode mode, QIcon::State state) { char *type_name = abi::__cxa_demangle(typeid(*entry).name(), 0, 0, 0); // ScalableFollowsColorEntry is a subclass of ScalableEntry but its mangled name // does NOT contain the substring "ScalableEntry", so the contains() check below // correctly distinguishes between the two types. const bool isScalableFollowsColor = (type_name == QByteArrayLiteral("ScalableFollowsColorEntry")); const bool isScalable = isScalableFollowsColor || QByteArray(type_name).contains("ScalableEntry"); free(type_name); if (!XdgIconFollowColorScheme()) { DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP()); if (isScalable) return renderSvgWithLibrsvg(static_cast(entry), size, mode, state); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) return entry->pixmap(size, mode, state, 1.0); #else return entry->pixmap(size, mode, state); #endif } QPixmap pixmap; if (isScalableFollowsColor) { if (DEEPIN_XDG_THEME::colorScheme.localData().isEmpty()) { const QPalette &pal = palette(&pixmap); DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP({ { DEEPIN_XDG_THEME::Text, mode == QIcon::Selected ? rgba(pal.highlightedText().color()) : rgba(pal.windowText().color()) }, { DEEPIN_XDG_THEME::Highlight, rgba(pal.highlight().color()) } })); } pixmap = followColorPixmap(static_cast(entry), size, mode, state); } else if (isScalable) { // Regular scalable SVG entry (no color scheme) — use DSvgRenderer (librsvg) // to avoid Qt's QSvgRenderer bug with outside . pixmap = renderSvgWithLibrsvg(static_cast(entry), size, mode, state); } else { #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) pixmap = entry->pixmap(size, mode, state, 1.0); #else pixmap = entry->pixmap(size, mode, state); #endif } DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP()); return pixmap; } void XdgIconProxyEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { if (painter->device()->devType() == QInternal::Widget && XdgIconFollowColorScheme() && DEEPIN_XDG_THEME::colorScheme.localData().isEmpty()) { const QPalette &pal = palette(painter->device()); DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP({ { DEEPIN_XDG_THEME::Text, mode == QIcon::Selected ? rgba(pal.highlightedText().color()) : rgba(pal.windowText().color()) }, { DEEPIN_XDG_THEME::Highlight, rgba(pal.highlight().color()) } })); } qreal ratio = 1.0; if (qApp->testAttribute(Qt::AA_UseHighDpiPixmaps)) ratio = painter->device() ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio(); QPixmap pix = pixmap(rect.size() * ratio, mode, state); if (pix.isNull()) return; pix.setDevicePixelRatio(ratio); painter->drawPixmap(rect, pix); } QPixmap XdgIconProxyEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) { D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_ensureLoaded_tag{}); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QIconLoaderEngineEntry *entry = D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_entryForSize_tag{}, size, 1); #else QIconLoaderEngineEntry *entry = D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_entryForSize_tag{}, D_PRIVATE_MEMBER(*engine, XdgIconLoaderEngine_m_info_tag{}), size, 1); #endif if (!entry) { DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP()); return QPixmap(); } return pixmapByEntry(entry, size, mode, state); } void XdgIconProxyEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) { return engine->addPixmap(pixmap, mode, state); } void XdgIconProxyEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) { return engine->addFile(fileName, size, mode, state); } QString XdgIconProxyEngine::key() const { return QLatin1String("XdgIconProxyEngine"); } QSize XdgIconProxyEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) { return engine->actualSize(size, mode, state); } QIconEngine *XdgIconProxyEngine::clone() const { return new XdgIconProxyEngine(static_cast(engine->clone())); } bool XdgIconProxyEngine::read(QDataStream &in) { return engine->read(in); } bool XdgIconProxyEngine::write(QDataStream &out) const { return engine->write(out); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool XdgIconProxyEngine::isNull() { if (engine->isNull()) return true; // Entries from XdgIconLoader::unthemedFallback() (e.g. /usr/share/pixmaps) // have a default-constructed QIconDirInfo with dir.size == 0. These entries // cannot be rendered correctly by XdgIconProxyEngine, so treat the engine as // null when all entries originate from the unthemed fallback. The caller // (DIconProxyEngine) will then use Qt's native QIconLoaderEngine which handles // pixmap-only icons correctly. for (const auto &entry : D_PRIVATE_MEMBER(*engine, XdgIconLoaderEngine_m_info_tag{}).entries) { if (entry->dir.size > 0) return false; } return true; } #endif void XdgIconProxyEngine::virtual_hook(int id, void *data) { #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) if (id == QIconEngine::ScaledPixmapHook) { D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_ensureLoaded_tag{}); QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast(data); // QIcon::pixmap() multiplies size by the device pixel ratio. const int integerScale = qCeil(arg.scale); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QIconLoaderEngineEntry *entry = D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_entryForSize_tag{}, arg.size / integerScale, integerScale); #else QIconLoaderEngineEntry *entry = D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_entryForSize_tag{}, D_PRIVATE_MEMBER(*engine, XdgIconLoaderEngine_m_info_tag{}), arg.size / integerScale, integerScale); #endif // å…ˆç¦�用缩放,因为此size是已ç»�缩放过的 bool useHighDpiPixmap = qGuiApp->testAttribute(Qt::AA_UseHighDpiPixmaps); qGuiApp->setAttribute(Qt::AA_UseHighDpiPixmaps, false); arg.pixmap = entry ? pixmapByEntry(entry, arg.size, arg.mode, arg.state) : QPixmap(); qGuiApp->setAttribute(Qt::AA_UseHighDpiPixmaps, useHighDpiPixmap); DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP()); return; } #endif #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) return D_PRIVATE_CALL(*engine, XdgIconLoaderEngine_virtualHook_tag{}, id, data); #else engine->virtual_hook(id, data); #endif } DGUI_END_NAMESPACE #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/src/util/private/xdgiconproxyengine_p.h�����������������������������������������������0000664�0000000�0000000�00000004013�15226154130�0022733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022-2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef XDGICONPROXYENGINE_H #define XDGICONPROXYENGINE_H #include #include #if XDG_ICON_VERSION_MAR >= 3 #include #endif namespace DEEPIN_XDG_THEME { enum PaletteType { Text, Background, Highlight, }; typedef QMap PALETTE_MAP; }; struct ScalableEntry; class QIconLoaderEngineEntry; class XdgIconLoaderEngine; DGUI_BEGIN_NAMESPACE #if (XDG_ICON_VERSION_MAR >= 3) class Q_DECL_HIDDEN XdgIconProxyEngine : public QIconEngine { public: XdgIconProxyEngine(XdgIconLoaderEngine *proxy); virtual ~XdgIconProxyEngine() override; static quint64 entryCacheKey(const ScalableEntry *color_entry, const QIcon::Mode mode, const QIcon::State state); QPixmap followColorPixmap(ScalableEntry *color_entry, const QSize &size, QIcon::Mode mode, QIcon::State state); QPixmap pixmapByEntry(QIconLoaderEngineEntry *entry, const QSize &size, QIcon::Mode mode, QIcon::State state); void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override; void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override; QString key() const override; QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override; QIconEngine *clone() const override; bool read(QDataStream &in) override; bool write(QDataStream &out) const override; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool isNull() override; #endif void virtual_hook(int id, void *data) override; private: XdgIconLoaderEngine *engine; QHash entryToColorScheme; QIcon::Mode lastMode; }; #endif DGUI_END_NAMESPACE #endif // XDGICONPROXYENGINE_H ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/src/util/util.cmake�������������������������������������������������������������������0000664�0000000�0000000�00000003720�15226154130�0016631�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������if(NOT DTK_DISABLE_LIBXDG) message("Enable libxdg!") find_package(qt${QT_VERSION_MAJOR}xdgiconloader) add_definitions(-DXDG_ICON_VERSION_MAR=${qt${QT_VERSION_MAJOR}xdgiconloader_VERSION_MAJOR}) set(UTIL_PRIVATE ${CMAKE_CURRENT_LIST_DIR}/private/xdgiconproxyengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/xdgiconproxyengine.cpp ${CMAKE_CURRENT_LIST_DIR}/private/dbuiltiniconengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dbuiltiniconengine.cpp ${CMAKE_CURRENT_LIST_DIR}/private/dimagehandlerlibs_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dciiconengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dciiconengine.cpp ${CMAKE_CURRENT_LIST_DIR}/private/diconproxyengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/diconproxyengine.cpp ) else() message("Disable libxdg!") add_definitions(-DDTK_DISABLE_LIBXDG) set(UTIL_PRIVATE ${CMAKE_CURRENT_LIST_DIR}/private/dbuiltiniconengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dbuiltiniconengine.cpp ${CMAKE_CURRENT_LIST_DIR}/private/dimagehandlerlibs_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dciiconengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/dciiconengine.cpp ${CMAKE_CURRENT_LIST_DIR}/private/diconproxyengine_p.h ${CMAKE_CURRENT_LIST_DIR}/private/diconproxyengine.cpp ) endif() if(DTK_DISABLE_EX_IMAGE_FORMAT OR NOT EX_IMAGE_FORMAT_LIBS_FOUND) add_definitions(-DDTK_DISABLE_EX_IMAGE_FORMAT) message("Disable extended image format!") else() message("Support extended image format!") endif() if(DTK_DISABLE_LIBRSVG) add_definitions(-DDTK_DISABLE_LIBRSVG) message("Disable librsvg!") else() message("Enable librsvg!") endif() file(GLOB UTIL_HEADER ${PROJECT_SOURCE_DIR}/include/util/*.h ) file(GLOB UTIL_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.cpp ) set(util_SRC ${UTIL_HEADER} ${UTIL_SOURCE} ${UTIL_PRIVATE} ${CMAKE_CURRENT_LIST_DIR}/icons/deepin-theme-plugin-icons.qrc ) ������������������������������������������������dtkgui-6.7.46/tests/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0014246�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/CMakeLists.txt������������������������������������������������������������������0000664�0000000�0000000�00000004166�15226154130�0017015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������set(BIN_NAME ut-DtkGui) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets DBus Network Test) if ("${QT_VERSION_MAJOR}" STREQUAL "6") if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0") set(QT_NO_PRIVATE_MODULE_WARNING ON) find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate) endif() endif() find_package(GTest REQUIRED) file(GLOB test_SRC res.qrc test.h main.cpp src/*.cpp ) if(DTK_DISABLE_LIBXDG) list(REMOVE_ITEM test_SRC "${CMAKE_CURRENT_LIST_DIR}/src/ut_xdgiconproxyengine.cpp") endif() set(test-plugin "minimal-plugin") add_subdirectory(platform-plugin-test) include(../src/util/util.cmake) add_executable(${BIN_NAME} ${test_SRC} ${UTIL_PRIVATE} ) add_dependencies(${BIN_NAME} ${test-plugin}) target_compile_options(${BIN_NAME} PRIVATE -fno-access-control) if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_options(${BIN_NAME} PRIVATE -fsanitize=address) target_link_options(${BIN_NAME} PRIVATE -fsanitize=address) endif() target_link_libraries(${BIN_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::GuiPrivate Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Test Dtk${DTK_NAME_SUFFIX}::Core PkgConfig::librsvg GTest::GTest ${LIB_NAME} gmock pthread m ) if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND) target_link_libraries(${BIN_NAME} PRIVATE PkgConfig::libraw FreeImage::FreeImage ) endif() if(NOT DTK_DISABLE_LIBXDG) target_link_libraries(${BIN_NAME} PRIVATE Qt${QT_VERSION_MAJOR}XdgIconLoader ) endif() target_include_directories(${BIN_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/include/util ${PROJECT_SOURCE_DIR}/include/DtkGui ${PROJECT_SOURCE_DIR}/include/global ${PROJECT_SOURCE_DIR}/include/kernel ${PROJECT_SOURCE_DIR}/include/filedrag ${PROJECT_SOURCE_DIR}/src/private ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/dbus ${PROJECT_SOURCE_DIR}/src/util/private ) add_test(NAME ${BIN_NAME} COMMAND ${BIN_NAME}) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/actions/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0015706�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/actions/icon_Layout_16px.svg����������������������������������������������������0000664�0000000�0000000�00000002424�15226154130�0021574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ icon_Layout/normal ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/dcis/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0015170�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/dcis/selected_indicator.dci�����������������������������������������������������0000664�0000000�0000000�00000022062�15226154130�0021477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DCI���16�������������������������������������������������������������â#������hover.dark�����������������������������������������������������³������1��������������������������������������������������������������k������1.svg���������������������������������������������������������������� selected_background 2.3.svg��������������������������������������������������������Ç������ selected_foreground hover.light����������������������������������������������������³������1��������������������������������������������������������������k������1.svg���������������������������������������������������������������� selected_background 2.3.svg��������������������������������������������������������Ç������ selected_foreground normal.dark����������������������������������������������������³������1��������������������������������������������������������������k������1.svg���������������������������������������������������������������� selected_background 2.svg����������������������������������������������������������Ç������ selected_foreground normal.light���������������������������������������������������³������1��������������������������������������������������������������k������1.svg���������������������������������������������������������������� selected_background 2.svg����������������������������������������������������������Ç������ selected_foreground pressed.dark���������������������������������������������������³������1��������������������������������������������������������������k������1.3.svg�������������������������������������������������������������� selected_background 2.0_0_0_0_100_100_100_0.svg������������������������������������Ç������ selected_foreground pressed.light��������������������������������������������������³������1��������������������������������������������������������������k������1.3.svg�������������������������������������������������������������� selected_background 2.0_0_0_0_100_100_100_0.svg������������������������������������Ç������ selected_foreground ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0015513�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/dci_heart_dci_hover.webp�������������������������������������������������0000664�0000000�0000000�00000075362�15226154130�0022353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������RIFFêz��WEBPVP8X ������Ç��Ç��ANIM���������ANMFd������w��n��C��VP8LL��/w€G§ m#ÇüQßú‰ ‚@ÒÞ=�o"qB±Š[!Ä"Rl�Q"ÄßĤmÛv6ÒÝvfº¶mÛ¶mÛ¶mÛ¶mÛÖØnîŸ1»›÷i’&ß#úŸ0á©=då¹ߢÓb¾¿¼°jp½ Xàm8lõ¥W?bÓc¾¿<¿rH¬ÏÑÿ@8ýE�¦ ?G‘‡æ„¥u¶ÄÓXÒî†0êjy8•ƶ7€eõ/Ñ̃Ö0âêø‚f®6†%eOÒìùð[ï:Íž­Óž± 4Ÿ6?b¦å>šOœè�¹¢×iÍãjj<§5wKÂLý_´*¡+”®‰´*´ Œ÷M¡ßÔ/×÷¯Ø°ïJ(ýú&C7Q£?íç¥ÝëVî»þ9…~SÁè�²ïêÈn({ì £Ÿµ.d¸VÒÏŸµ�óBq~ÅGY c#4ŠOƃ?o¯ë”W c.å ‚à¯È؇µq0ÒM£6Ä C-Pœ;žâÕú0äJIëÿµ)¤oÈ£î¡q4>У¹V§SHª…QøRfÊÜ¢¡ÛÅ`¦ú ŠAv�¡ð¼(ÌywÑÀ–˜+ôˆÂÄnä†Y×\ú]Ó9¯P©t<Õ“™aÁBúY 2¡šXÂAª½°d Å=.Xr‡êQ¨ ¨F—…5žã®{aM©Hª�¡Ü¢¢uƒUYïSù˜VuԨ܅¾ ÕÕ°®ðWê¢+úT›CwœÊW/,¬Ãi­aaÈg*§ð¿œ�ÊHXÚ:�GÁÒ!T|ðo.•ï^X;˜«amÈW*óðï •1°zÑY,AåþV§ò3¬vg…ÕÞTj c6•pÀ<*s�q‰J8 •ËI >:Š¢>!¸.•#pÄa*õSG ¢2x1•2pDi*‹ŽPï †#‚5ê�<¢> £þÑGê_À!/¨ÿJý%8äõ¡ Ôï…CöQŸ�NýZ8d-õé1Ôo†C¶Rûƒú}pÈ>ê¿¡þ2r†úש ‡¼¢þÚvêÓ¼p„+žú�S©T‡#ÊS™Õ…Ê(8¢•%©†#6S)‰ÏÔÇxá�Ïê#c'•öp@S*‡�Ñ—Êa8`•¾ÈÈ•L}JØ>õiyñ÷•¹°ý4*ñ¯7•°¬°yö0*½ñÏJe2l>�JTfüŸO%<'l�'’Ê2芧PY [¯¦’R ú�TR*ÀÆUÒ¨l‡R*•ÊØ×u�JJ¨ë¨ö€m{S]¡@ •?¹aÓ<¡Tb AšLu lº‰ê$ˆÞ7T´æ°e �Ê›È-©~ÌfÿLEk»©n… wRÝ ¿ùèv‡íúR Íÿ}¨F—ƒÍ*ÄQí#'©>É[e{Aõ ‰ ºvr¡QƺR˜M£ªu…ÑMT}�`›.Õ-0œåÕøÚ°IÝDªO3Ãx…hªJÃ¥C©ÆT€™ŽÕ·ùaƒï¨ú:ÂÜ ÷²#à9P˜“®ƒ.fB€½—(tÁlæÛN# ÁÇ)ÜÍ ó>QØïA�=(|,+*†QØåFÀÜ;)„W„5uã)ls#@îÍâëê¶)¶º÷ ©ma]w…À³�Bz/X9X£°/–í¤  …µc( �Å!‡)hã`õDJg2ÃÒ̧)M„õ“(]Ë ³_¡4 �˜DéQX–ÿ¥™Ì$JïJÁ¢’¯)MC Æi~Vƒ%U¾SÐ& pÃ|¢šÂ‚|#È>i’ºÂt§D éØŽÉ|ã`r”�BrWºe¥Un˜p/¦ß�¯FéXÎ|€RdØ¡âWJ÷ Ã`þ›”¾W…=Š=£ô­ Uú@éU Ø%×Jqa U¥[yaïAJ¾Éð;<�ұ̰“{ Åí^ˆÁ«)®vÃfÃÓ(Ý* !ß%Jé`¿v±”~Ö…Rõ#¥øN°c�”’@×9ŽÒÏš°g‘{W#óP£ô¸ìšåÅ+ù3.P<• öuÍÕ(}ùFI[솭{&Ð`boؽæ7ú^ ö/x�n‚BÖÒï–8d@ÅäpNío¾×ƒ“ œ rÓ?vÂ÷»(ü•zS꟢ԎQxZ¾.õ‚Â^8+ôœÂÕpø8ò&…gàp<¥¯áãE”ÆÃið¥Þðí@Jçp\ì…•áÓꉞƒ‹a”r—9ÿ 4®¶SºF]¢´î2'PÚ€ï‚Û(ýš.«&Rú¾û„Rb5¸Fq$|6‚âhXN)­#|Õ%�Ò2è?G)±|Ô(‰ÒùphÉ‘@éI5ø¦ÊSJñ9 ©ìcJ÷ËÂ'eþ£ô¤´5M¡ôw1ø¢øß”RšCã@‹Òï…áƒÂ¿S²Aë,Šñáyþ_)΃æo(þZ�ø™â"èn¤økAxZðŠ[‚жŸb|axX(žâÁ0xuŠâï%àY‘Šg¢àIÌŠ—…G¥ÿ¢x)<Êx…⽪ð¤ò=ŠW3³,W)>®ê<¦x#3<Ì|•âËÖÐÞä9ÅÛYáiæ«“{As·$Š·²ÁãÌW(¦�…ÖQé¯g…ç™.P^}�ù”/e‚bNR^M!‹(Ÿ‰�/"÷SÞ -Q»(�‚OÂ6S¾œ²] ¼3¾ .§üs ¸.òå•!ðQà#Ê÷ëÁe�(€¿&Z{ÂU§—­9ð]¿ŠÖ\¸˜œN1u|Øê9å�pº„òËðeµ)_Ì G™�Q~P>-öå„ pPì;Êñ¥àÛ)?mÛ†÷)_Ï Gm§œ66£R(Š�¯ƒŸÓfK4„ðe´Y¿�J¥|«0”œç(§M€­ŸR¾×ïUý�ò³¶0¢|<å”ñx;$‘ò•`HŽ ´Yñz9m®å�1ëhsù m¶FàÀÌtºHŸÃÚ>¡ã§ía\éŸèð§²00Ë!::žF?°hk}S;?£ÍóÞ0¸Ì,£3m¥°%Loq"�oS�5ÃÿA–¦ý4Í�ANMF�� �� ��—��‹��C��VP8L��/—À"¯§¸m‡û��rýþ’¶ðîiüä Dálˆ¡ØwNÁ¶ÿ‡äøÿ÷èÛ¶mÛÉ"¶íÌÆy¿×¶mÛžØN»qÆ;iÕãþììôóUõªzåvDÿzü †O]¼~û¶5 îT nøê½káÚmÛ×-º{xC¥Ö/ëC×´lj¾<Š;®Ssî�åS CcïÚ( �}ó(¾Õ�Šÿ †ÖÁETG@kߊà ûP²¦BóØ0ÖlhžhQ:qÅÝо˜Š]Ð~ÅE�ÊfQúÜý÷R|Ûí¾�(]*a¥µá‚ÿ] i)p¡úUJ››�Ni:\Iùƒ1é5áÊJY ˆ™Jé ¸Tý ÿCñç&Áð‰>GñiÆZÕax5‹±§bl:ŒOgl(¾ …ïaüwš §ð,Œ–Âð©6ÁøÍ¦.¤°Æ/¢°`5…i0~:…U©ÆÁøñRwPã‡QØžJa4ŒK!u%…)0þN «çQ˜ãçPXt'…T¿†Âô¡ž€ñ�PÜ�Â70þ# �üEŒ½ã�36�cjÀð@”±çPü…;aøP Ÿ x …Ç`ø6 ©(îGá, ßGaŠ“Š(t€Ñ )Dø÷G »`ô: ¢$•BF ö§�Š’æ”FÁàÁ”Úã¿Ã>…ÁR8�R©¬60¶Y„ÂN”j¥ð2Œ}�B´JJ!Ü †¶ŽRø1£(½ Cß¡tbüg(D;ÃÈÞ…³qˆ]Jé ôBR¥©0p¥K)�–SÊ(ã—(­„˜”Né!÷(¥‹I�gPŠt…aÝ£”æBáÛKéP<ŒŠ?DiŸª¾¥�0j%«Ô¯R*l ƒšRz 6jdSúÑcâ~¡t½:ì,£¸Ƭ§8¶ü¿Q*jCº)ýàƒ½ÖAJ'ʈÀJE-`w;Å—aÄë·ÃvâQŠ‹`ÀRŠGa¿sˆRQ7x¾oˆR¨3œì¤˜Y¯s‰âN8JøƒâIðtòŸ�‡³F9_óÁþ7(æ6‚Ó»)oƒ‡wQ´î†óG)Z³àÙ¹”…†Äß)‡À£CBÿL„Žº—(æv„';çRü»ôôºEñRx°ÙŠ·ú@×<ÊçjÁsµÏS´æCß}”�U�Ç*¡|4úß§¼7�OÒ(è‡Î2Rþ¹,[º›\¦üU2<’ô9å+Í ¿så/“á‰äÏ(çu…ƒ‹(‘ $NùÖP¸3!Lù븞òåðd¸5+Jùûrp¹Ì7”£sàÞ‹ò¯¸ZþGÊÖ ¸¹ŠŠ}Uàbå?)[«áî&*ŽÕ„k5�P±no¤âLC¸Tÿ$©p#Y­àJ‹‹Tì€6Rq½;\èz•ŠíðÆ*ò‡CûÐ<ÊÖxe¥E98šï R¶ÖÀ;‹£”£k¡uy”rt)¼4-LÅý>hóí¡"2Þ_DÅ›IДø*Á»àµ!ùTüP Z_SQ0ÞëyƒŠ  ¡Î!*²ûÀ‹­3©¸ÔŽÛgRq¹¼Ùà$ápTçšÂ«ÕöRÝ�GKÂT¨ï–ûœªa;î~ª¾ ÀË /RõSØ,ÿ Uo%ÂÛ¾]T�m[ ŽPu¿ž_¦"{lôºLEd%L™GEx%”soQñÏd˜Ñ>“ª—’!Æ?DÕå0¥Î!ªÒê@¨ü UÇÀœòŸSõwoÄ´9KÕW`Rü£T¡ÔùT=Ö‡©z2Åñ÷QY ó†fSõsõ?P•?&¶´†×RÜ�ùŠŸ¥Bs£¿¨Èé�ÍÉg(Þ)p‚Òu ý¦<Šö`h¯ñ;¥3A#)Ù=áÁHŠOƒ;lJãø’Òlxò$…żxŸÒ7AÄô¢ôC*<±0æP<Äÿ¡l ;àeÇ΂—[(\ £èvJ=àé wáiJ�Qô1…/0ØúŒÂlü¸Há~}7…?(lBÁ® £«Ùš¢p2…c0ü…©(\Há!~?…E(̤Іw �‰t 9q0<.‡Bzk û`ü ­SxÆ¿Iað£fÁøY›M¡;ŒïNaöJ �`|# +·R¨ã+QØz�B*ŒO¥pð,cí ŒQ8ûcóq ¸ÊØ/NRÂø…Ó{)$Áø’l P Æ—£°e …Ö0¾1…•oSèã»Qxk…ûaüT wu£0Æ¿J¡O ç`ü! ÍÂùŒµKÃðø\ÆæÅã(…¾0¼#…£(|‰ÂG0ü o °'…߃0Úú†ÂPfD)Ü £[Rˆ–ÇG(,€ÑoS8Œ¢{(ä¤ÃàÔKFQ5›Â½0x&¥Æøÿ0…ŸJÀØð·N¢Ø4Jc`ìJÓQ¬d„Â7a÷#…œ ›Ò$:�ÒÄ4¢”• #Ó²)ØM»ŽÒ³0òJ!´¡”SÖϧt=¤ ”ÖÀÀÍ”¶@lcSê ãP²[A^Hé§T–ö3¥ePTÏ¡ô {›RN ¨ž£í�£ÚE)= eò�”ÎÇÁ ø ”2“¡îKñôÅ^p²�ÒÕv0¦C¥•pTý¥¯R`Hú÷”þ©g³(΃Ö2ŠSá0x„â1‰âá�œ6Î¥t¥ h•C)·œ?Hñ› ø¾ì‚‹ÐaŠ[ƒðyxÅ#!¸©s‰â«ðùë#µánå ðõ$Ê£àvÅü[áã.çÁuÒyŠ7�o›F(žO‚ûúŠ?V†O+eRŒ4€Ž¾6Åsiðeú9ŠÑ¾Ðóå½ ðaâ~ÊOA“µ‚òº|^Oy•]É')ÏÀg�¹”O$A_¥LÊïZð•õåŸ*AgÓå—á'ëÊ‘æÐ{G>ågà£g(çßÝÃlÊOÀ7�P¶GAÿ½T<ŸÁˆQ*rÇBÑÿ_*¢�À”^—©z; !ð”MÅ•A0§õ/Tí.‹˜”UTýÖ&U;KÕ-Q¬îª.T‡Y)먺2E½ÿ¡j[*L ¾D•ýb°ðY›ª÷C0p\>U[·Quu̼1›./Þ Skœ¥«sµ`nò ºX�“OØth?eÁðžÿÐÑ¿ýa~½Oéàëf¸”\Eå†t\¬G¢£�p͸=‹BÖ¸–”|4“Å~|(׫ÙÈ{ïÕÌ‚o��ANMFÊ�� �� ��’��‡��C��VP8L²��/’À!ÇG&mÿ®÷– ˆ �´…wOãBD"wœ‰OжíŒ$½…ÖØ¶g¶wǶmÛ¶mÛZÛ¶m�m³5]]õ¶òýÉŸüsÑÿÄc»pË�ãç,_±pʰ®•üЬÚmøÔE+ÒçNÔ¢<Ûnó—×)&ýþÜèÐVnâ‹§P¼ñÕÖ±p5ט÷i+òǺ'¡¡á¶#´—ôá„qP>±â•·jÃAü ª~ë{Õv%Sµéë¨JØ\ö‚=¢êvØ.vžŠ“|°_ö¹0›çQÚ^ö}½�Rq¹$lÆýH9´.ÎêþGG¿Ö�³¨å©”ÿÈ [¾)o�DZ[ô^€ãZÿQ~Ý;)˜:º>¤Í»Ý¡#÷Û”§ÃFåŠ;ÐSû"m]‰‡ÿFŠIÕ¡ þ@q=´•:Eç*AÛ2Š¿EA5—âFh,w�ÊËå q9ÅÅP¹Oé9h­r�Šû5¡õ ¥‡Å! ôC ôÖO¤ê½Ñ_Szb|…kÅ »W˜Ò4è.|™BZMH¯Qêý³(ìƒþΔކP!�Âópc/-áÂÓ•aÝIáNA¸|ŸÙŽä…ùnQØ K¾‡æÀ�Ü2óF¸3�BBdŸDál \*u‰é)ÍáRô) S‘ý+ “àZÍ‘ápm,…o�­D˜ÖÛ9á^çUp/î&­á’ÈšFa ]Ca²>£P†V¢ð2£hý ÆþAkb42QX cPh„Œ¹ž‚±ñæ!ã Zïøa¬ÿ­o"ã­ïÃà÷h=‚ô@ ­K`ð"ZSü(K¡/ îK¡,ÚR¨ ƒkSh‹!´FrÃà<†`­ 0:�Ö ˜Më5}�ÖÙXFëi}šÖeXAë?0ú_Z—c9­Gaô1Z—c­gaôyZçc"­·aôMZ§b­‘X Ñ:�(T€Áe(tD% �`p UL¥u KkZ Ò�Ñú2 >Lëd¼Cëü­ï"c…ª0¶P˜ÖÅÈhFa.ŒC¡-2b’hýÆ~Hk(2¿ 5\†J¥õ+dͤ°†. 0Y¥#´^ ÂÈày U�í{ C`d #û4 ÂDßf {�$ ]a`o )…`yšÂŸ>çÿ—Â˰֡4Æ §Ô�ÂWÎÅÁ°ÜW(|©-¥e0l=¥Î¿¥�XFUL¡ð#ä¶”Þ…I¾)µ�âJý`Ð�JŸBõDˆÂ•|0&ßU ¡'¡ÜGé ŒÙOiÔoR·€!-#n„�Ñ”N愹NS;¾o)íƒ)}{5R(DºÁ€>”’*ÃærJ7KÂóåîRZ »ÑÿQú6�G}Oé¿(Øn¢´ßE)TÖRŠ ‚§GR\'1SJ¬ ×K¦ôW ÕH¤t¡<[ü¥Äp8žâÏqðhÎß(N€ã—(¾æ‡'oQ|ÎsýOq<¹�â‘\ÐPíÅ™ðàLŠ÷«CK÷0¥ð`xnX„R¸4-¢˜ÚëœJq)tù^¤˜Ø žj’Hñè‹ýŽâ½:ðPí»ˆ…ÆB')ÞŒ‡gâoR*¶À3˨x;Úb_¡b5<4#Bù‡‚ÐTàkÊ‘…ðÔØ4ÊÇ+@KÙÿ)‡'ÃcýQ¾Ö�j^¦œ:žë�@9¡'wx@9©+<Øðå´ép8!Dùn x²ÆE*öáÀ¿‰ŠËOÁ£¥ÿ£âã¼°�ã5*Ž•ƒgóMőаYâW*~.ǾJÅÍ–°Uû"ïå„§ý;©x4 6z'Pq �¯O S±)�…oi„rd è‘HÅGù!æz•ŠäÁ0¢þU*NÅC(÷7šÂ�rÿSñ ,­nRq´"ŒÉ÷‘•>dú¦§Rñy>ÜCÕ[y�žëEªžŽ‚Y“CTü_9ý_*ÒæÁ¸öw©¸{�Š{]a`Õ£tt¢:ŒÌ÷|”†6Óndk�æI¤­äá0ºÖÚ¸Ô�†ü„ʯ‹ÂøÀFÊ‘­A<úß§p¯?%Ÿ}ÄlÉÏ”Äã£ààåË€7�ANMFœ������Ž��ƒ��C��VP8Lƒ��/ŽÀ �§ m#ÇüQßú‰ B@P"IñßœÌÆ”ƒK³7ß„ælÌ4ÿ@ÿÿÿCróžÝM²¹mlÛ¶mÛvm\R±“ë]m·QÓØ¶�³o÷ýDßÏÌ|g¾ý9¢ÿ‰ÿã =ÇÍy>~á sÇõ® ÝVµ¾潸ðÞ sÇ÷ª„{¸õŻێƒ¦#VìH¡x{ÛGýÂð0nÒ¯™t”ýûüRp]áÙ-yt”õÛ´¼i¾4™.2×·ƒ«ÇW¹t‘º¢ô7ýž®wt‡ã�éúçVÐ[3)J¿4ƒ£v›©#úu=è <‘AM‹ã`[lMŒš²ž BSýíÔx¢=lºœ¥Æ]M edµæ¿€|;J­Yãá>ðfŒº¿�@‰üHݱ‚pYô:º±)aÉ[o.Nøã í­ŒG*í¡“èù?Ö}úÆÛK?ÿç:ý�«¸¿h~åÐrJ÷ýäí/5ÀƒÚçiÛóvï„rC–Ÿ¥ýÖÇà"²‰vÙ‰�á é²TÚ]¬‰{•ÏÐîê; à ÃÆ,Úm/Ç…7Ñ&ûÃrpXì™;´9S¥ÌaÚ\~" ‡¥ßͤÍö0Zë(Ç’ªÁE©÷r)ÝM9gQ.*¯§M’gÏR¾:.[¦‹�à²ßEʯÂQÿ(ÅßKÃuøc:�}V®KþD16Ê^£øq:¦åÑQÎ8è¼CñfØK)ö4õJ¡ƒÌþÐ4+Fé'ØN¤{Ú:gÐ6³;´ÍŽQš›7(½��½³i“?Ÿ t»äw)m„ÖQÊs u%¥�!ÖÊ¡°£ô>CñSè-´•Bn]HIÒjA÷r ¿¡¹Z …¯!Ôȧ0ÚC¿R9T Ú§P(¨õC ›àA±|äz xð…O¡O¥m/ª^惬ð¢YÕ´xt…xÓ2�÷bcáÍZ �ãÑmT jÁ£�Œ‡GÕó©nÇ#U¢T¿ƒgó¿´àÕ×T£ÕððI ]á]žu¢ð4n¡zF¡º ÂÙTÁÈxª9aÜïJ¡)ŒlL¡+î¿Lõ =MõÜÿ™j Ý@õÜ?Eu& �AõîʧÚ†6¥š_u©F‹ÀÐp”j]ô§zÆ^ Ú“¨n‚±›¨NÄ<ª_ÃØ¯©ÎÅóT×ÁØuTŸC<ÕÏ`ìbªñXHõ=û>Õx¼Fõ3»˜êkxŠê*»†ê3˜Aõ[û%Õ9CuŒÝBu<ºR½ cÏQí‚ Tc%ah(ŸjÜK¥Ú†¶ šmáÞªÏÃÐÙTãþzª¿ÀÐ�T×áþTªéa¼Fu&îס0Fv¥Ð .QM€‘ŸR½ÀƒõT3ŠÁÀðMªðp�…Y0p …áxXø.ÕÃÌÛK5#‚GÖS�ãúPHÀ£])lƒiÖN Ý¡¤Ð† ¤pÊ‚2“Ân F÷QX�5r›Â5ƒÂí8/S¸�A%nPX©ø oÁ )$—‚ø …œF0¦i…W G®Pø×‚!�ÿ(\‹Àf ¥Ù0d¥é° ì£�\ FTL¦°7�ÛŽ1 ßÁˆï(D;ÁÁJ£aÀXJ«à¤Ì- ·+Á÷UïP¸ZŽÆSú+�Ÿ‡¶R ‡¿Qz >_HéW8­™N!¿|Ý£€Bz 8žKéj%ø¸Ú JóàÜú›ÒŽÂðmx7¥M\ÔH¦´¾ÝHénu¸EñIøôiŠ£ár5¥‚Áðåð(¥5p[t¥ô6ðaÛLJûÃp]'™ÒÕšð]Ík”’ë@à(¥ãeá³rÇ) ‚–)îz ¾*¶‡âËÐc}Añ¯ÂðQ‘¿(~eASÑ�¿ Á7¡o(î C[ù³ðI �â¹ ÐØè.ÅU|a­¢x§´vÉ¢¸~°>£˜Ý š‡PüÞ[ïS, í3)¯­)ÆfÃç)jÁSëʯÀ“w)/³à¡õå÷á�µ„òÚ�< ¬ ¼^Yk)'…àQèsÊë-xøœòEàI‘ï('àa0‘òŸx÷寂ð4˜HyGih/¹�ò7!xL¤|¸24W:Hùë<&P>WZ랥œ„«(ßl �­®S^€/¬O(§÷‡¶^©”—XðË"Êy“¡i\.å÷á£gbc¯BËó1бWà«YQÊkBp\B9:>•Cù·bpùžrÞxø®wåƒUáªÒÊ™ƒáÃ67)_i M/P¾Ý¾¬w†ræ(8î›BùB#ø´â^ÊÑWàp^>åÃUáÛb¿Ó&±„–ÒfsIø¸ÐÚüW¶%§Í—…ákëÕåó­`ÓàmÞ³à÷ñ9”3Ç@˜B9o è~‡rì½ ëù(åä>0¢áiÚüV �Ä}I›³�aHÙ-´9Ùêì§ÍŽò0¦ðzÚ¤ ýAwióU&=¥�_£]hÁ¬¡it•>Æ5=Mg›ÃÀ2ÿÐñæ²02´˜—†`êäl:È� ƒ[Ÿ§í•Î0ºÜ?´ÙZ†‡>¢û$ó�¦rz þ �L<–’z��ANMFž������Ž��ƒ��C��VP8L†��/ŽÀ ·§ m#ÇüQßÝï B@P"IqÙ¤¹oz&Í`vÍÚüjضo¤;m’ÁŽmÛ¶mÛ¶mtlÛ³6ƶm³‹a™Ü¿Gïó}y¿ïÝßýOüÿ&/ßsÎÆï÷œ:¹ëÛuÓ;•H­_•î±þ»]'NïýaÓÜ^RÀé$M–Þ¤Uü…95üÐ’¸ÁÂkAZo-o– Žy›þC›¯wÔö Do“Ÿ¢h3ö·–>8‘~êc†tcx*„�qü†ôlF&èN9ý-CþoLbØL>íC~7;5tzGüK-OúxaÃ?4’Z^�õA[±SÔv¼�,‹ž£¶ó¥ Ç;1–ß ö@ M�qÓ}Ð�êjþ3„Ô{©y_Z„\äµ_Ë %Ïuj¿W!VC±¶�ëÙºn½v}&{=@‘UðEÅ—´~û¤ž­ëÕiÕsìÖó±´ñ®Bªýž–ÏW5O1uûMÿÐ2º>ÕŠ¢eäòf)!&mºü)-£!„zQ´îmç‡�Ä=NÒ*ª&>”K«Ý­ü°ákµ‹V1Ma»B-V„íš§hñ¦b±h±«2l—ÛC‹˜j°™ã9åGMJX‡§”ÿ{FùQ „Ôà>åÈ<°•ì"ÅàÆ”1Í7 aM2„˜l5å«)`ç[ŠQ] ¡{4mFõ„†¶ï)þ])>--•"iëeh)õ�boXfEéAnhÊs—6‚¦ìw(½É ÏJrC[îÇ´|’ڲߥtȹ ¥òCcÁ´xUs½¤Ô bÂ;âê@k™wãêCkµX ÷AIi47P Íý)�…�ì? »<Ð=œÂRèöüJáu ¨Ã(ü— ú—Qùà í™ÿ¡0Š÷…�pÀû ¿¸œô¡ðÀ‡/ÛP¸æ…IÏòÓ‹\pÂ{™B|¹‡B38“å?DW‚3 )ìÃTÏÁ©âo‚]àÔiª�Lø<�Bw8Ö` ëLa0>¤ú, ô?¡zŸR©Î‡‘³©Òàc `dY Mñq6Õé¹Ou>£º†.£zü±T;ÃÐNTcýÈO!' ÍA!?R}cŸQmˆ!TÁ؃T‡`1Õõ0v=ÕÅØJu<ŒOu ~¤:�Æ úöPí c»RÝ�T[ÂØVT�ã,ÕÆ0¶ Õ³8Hµ5ŒmKõ0~£ÚÆv£ú'vRcPýk¨Î�±Ó¨®Ã$ª_ÃØ-T'¡#Õ+0ö0Õ®(M5.! õ¾¡ZÉ)T…¡Å©ÓáÃ=ª`h_ªwñq#ÕC0ô'ªÛð±Õ@™,šê|ÌGa�Œì@¡(>zîR=#÷P½‹ÏJÀÀ"ási ë`à 5ðÙs‡jLf—é=Õ»|1ŽÂ<·„ÂD|™!†êûÌ0,[4ÕøìP¶PXÃÖPøj9 qE`T©�…²þ¤°&yQØ©"¥æ0¨=¥jÿ¤ð )ŒIþ˜ÂŸ�K(,‚1K(JÃb…ø20¤l€ÂFXe~KáœFøÎQx“ –£(�…c)�†µï2…èÂ0 h … >ب¤pÚ×'H)Ø.é¤è�­#(ºÁ]GCó|Šñ�á‚vñCwØVŠñ�àx‡xŠÛ Ý÷3Åø.p¸s<Åßýp ÑŠ�p´k€â�Äp$ÙqŠ�þp°W€â©äp(ÕYŠÁaplH�â¹Ôp,í%ÊàÐxÊÓÂÁô—(ÏõÀOå«éáhºK”׆C{ørÊ×3Âát—(›�šì¤|-Ow�òîdКtåKà‚4§)ŸI�éNR>›®Hy„òí¼Ð–ó:åã)á’$»(¿(M%ŸR>� ®Iø#å·� ¥ÞÊ¿'†‹|[)Çõ…†nq”wú᪰Ŵˆð DÏ$Z¬ ƒÛ&ÐbGB„”`-fÂ…ý”�¤C©öR …+[EQ¾W¶s_£Ó.­ò/å×�`³J$å×uàÚÂ(Ç…­î1”Ÿ”€‹³œ§Åj,Ã#hq%;\�ìwZìI‹ä?Óâ@J¸Ü·šw‹CÌw…[Àý£ƒ”ß¶…P÷_ÊÁI0¢måàŒ0|áO9ª# )÷Œ¿¦À§$Ûhñ²2ŒÉ~ž7 áC¾‹´¸š%ý‰¯š6{E‹¿R¨ðÙ´i±Ð ÓºF3„è0°ìÚ~RFf>A›'3ÃЄkhksB˜Û?––q#`t¥§´x^†g:Bñhï�ˆ£;Ó�ÿƒ¼ ïóÓ½ù¹áANMF¦���������„��C��VP8L���/��!ǧ m#Çüißü B@P"Iñƒ¹nŠIæÐ˜0_ÁmÛ¦&Iûû¾P:³ÓÎìHÛ¶mÛ¶m—mÛŒ¨.ÛfªÂJ+>ìŸQQqÏ}ï¾wûwDÿ®É£6?òÁ÷§ ®çþõÍ»¬\ &õ‡mzè½oOæ];wæ‡Ý2ºQ�ÞV™úP:õ§îUF*Nz �úÌG¦W…Wñc_�Ðéµçà2nìa:�¾9!TÞ›AwnªÕwÿMwY‡ªÁpù]è>c–Ûs‰î/Áe¹4svnâVdÓLþÚ L5z�æþ×�ÚÆŸÐÜ'Ía$°ö*M^˜9°ì2M^Û€û2OÓôse!”{‰¦_,· ¾¥ù¯ë@©ó ÍÿÔî:äÒIvê­«g�<~îÚ»>( “´Ž(Ñ.�N²Rn_3kìà±³WÝ’’E'Ýà¦sµ‘Ô - Úoÿ(Fíå>(îr‘ÚhêšVˆÍ×½¡öBO8ïzžº¬õá¤É‰|ê.tAQë|ê2vÖ‡“º{Ó¨»ØN[] &oCœ–Þzžšü6ÉÔ¤¯I‚ÓÄÕÙÔ\jgÕNRޝ�7Un�RÎ>E9|¼ Ü”;¦|¶&œ$}Hù·pÛç$]üØn;ÿHùóRpp/å§JÃ}¹Çéø©2pŸôåG¡M1ºF;ctÛ3"'AW-›RdLM/¤ƒÈB˜š¦”Wš(EfÁÜ䵑é07)LéUÈÃ)ÅÂä¼u«`r&ű�â¦tf7Rs fPú= Jo„`ø.Š/a6ø¥5PËæPÈ©Óq¯Sø¶,LWΤ�_ÊJJ`¾Ü·T2êÂüHJëP2ô'…gàE�t–¸Ú^Oá]Øø˜Â+PúQš�ËfRêõ= '“`U™4 ŸAHi¬ÚGi(¤÷)\M†EM¯Sxb·…Øx‡B¬'ä')Í�5s(= Mƒ«r«Â’*¹®Ôƒn'¥'`É”vA›ø;¥Ñ°b¥_¡D)«*,¨‘M!ÖN¥ôr�¾¾Eé~8ª’Ci-|¿™RV%8›NéFø¼[!¥ipú"¥3Uàëi”^„ãy”Rãàã„(åÕ€óÉo†�ï 8n ¸¾]DñA¸*û+¥Âþðéà0¥ßÊÂ]›+” Z—­.PºÒngS¬y†â\¸¿‹â×åá»ò_S¼ Þ§˜’Ÿ%½Cñƒx˜¨všâ³!ø*ôÅ3Õa¦íEŠ÷à£À}/¶…©áŠ7Ã?�#£`n9åðÍÊ+aòå�ðÉÊG`4ð(å-ðÅÊO`6þuÊ›àƒ ”߈‡é2SÞÏ7Qþ¬ ÌWúŽòvx¼•ò÷ÿ�5~£¼žî üG xS÷$å#ð.p€òéúðªáß”ï£àm”ÏþÞ5N£üh< =H9½1¼lœFù…Dx�ð åÌfð¶qå”r0^ö Ê™-àuã4Ê_T�á*ŸRÎhï“ÏPþ­>ŒÖû™òÙÆðCý?(§µ†Áæg)ÿÕ�þ¨õ#åsý`¬G>å_kÃ/U¾¤|} �¿FùûêðO…÷(G7ÀȪ(åO*ÁO¥_£æ¶\SóVø+þ1j^,—¥ž¡æÙø-x5_Ö„«ªQsO>ÜNÍÙvpÑìOʱ=ðç¼0åKcà¸åÈ2øuøeÊÑMp¸°�òÕ ðo—jJ€ƒÐ jòzÁÏÉ¿Qó^hË¿LÍɦðwå÷©9ÙšÆ?SóEuø=ñ j.M„8¸€šçKÃÿ�ýÔÄ¡ÖG¨9„ ©y¹J”z˜šÂŰ¥_>5¿6Cqƒ/©97ö4ú…šó£P44Ÿš“-`S¥·¨‰nߥ惪°+þº¼'Ö-)¤‹Âå°±Oçôƒ�õ¿¡ÃïÀÖÒOÐѳe`ñº0µ‘XÝ?‡š¼!°½Þ—¿j�û“N„©KÄÿ…Æ7Ÿdñ_'’á�ANMFÔ�� �� ��’��‡��C��VP8L»��/’À!·§ mÉüqï¿A @RHÁsEK|åhˆH<‡7lÛ½õÿï¼'µ­¤nÓwßµmÛ¶­´ËvÚeÛ¶íÚMµ¢*Næ>™ë5óšyõqDÿ7íê}¦,Ú�¶së²éÓCÐn1rƲ-;¯®_8¹o ø"vÀ}_üG±à÷æÔ…¶Æ‹_ü«ˆbæ— Šƒ§Ió?ȧ£ÈŸw´ƒ†.î§³‚�U€W�ž¼B7ßN��«¤…¿ÓMÞ³ÝàE�/è:{K<W¼ý2]ÛºSß§–3 Âp³:›Z>î�ñ÷•Q×þžpÐÿuY�&B[¯ÃÔXvw ñ�D¨ñX?è Þ¡Þ¿S!vÜO½‘{CÐPñ]jÏ a\µR®“÷Ó™•uô�Ÿœ-¤3klë#tV˜±÷§ß�dYtv¤\¶:G'Ÿ˜Õ)åBÍF§}SFO‡p=¸› ?ß2¸qå:ÍÜs‚²RáªíTž¹µ ”U&¡ò… ®öPYòÞ¸8([îÌ 2»#\´Í¢ê×qa8kþp!U{¸“ª+÷Ö‚³ð¨©ÊíǵOQqpB�μ`QqßF*J¬ç�1{©8[ã~¤\z{4Üuü—®~é�wQi%”O€£ÀË”t‚ëØû,:¶n Áuê?”ß ÂÉbÊV„ŽáWè0w8t$½My¤äS|(=©tt¶5ôï¤XÐ ÊðºGèàxShÛNñ×(¨6R¼ž¢òL#hÜAq;5/SzZSÎSq©=´>N)¯ä'(}½�ò)–�Þ¨/)=±m…ó5¡{´EitW;CÁJ…ô…È(è_Ca7ô¥ô.„¦…àE:m‡áÁ“¬Ø¡�[^„ßg¹½áE¥, »a«|…ÂZx“ô¯g6�7Ë)äUAù%ŽÅÀ£º¼ZÔ E¦°å¿¢°žµ¿™ÏæRøåêZ´çÄû¡·À»¸,Ú­z¸±’Â]0ô6 «qãsÚ#É0´)…/p=:Ÿö?`ìo´DãZ7 [`ì& Ýpm=…¶0¶5… ¸öí¹Ì¡ým\ÛOûû0ø=Ú÷ãj¨ˆö-0x3íE!4¢0�£Ðý)¤ÂàT ý1�öH N¢0 ‹h¿£¯Ð¾ëh?£ÏÓ¾i´�ÑGhß��´ÿ£ÿ¦= i´ïƒÑûiOÃzÚ�Ãè“´oÂbÚs`t&íË0�öH, •Ò>C)4�Á ( F2…!0¸…æˆ*¡}= žK»ƒ«i ?I{®½KûüíïãÚ )0¶šEûV\ëIa-Œ�K¡?®ÅÐþŒý€öÒ ¸þíV#Zµ˜ö¯pc5…[`è ëp£~„öŒ0Œ Ÿ Ðå¾§0FŽ¥ðʯ¤ð;L üFaÊW- 0Ž¥P\ ¶g(ü€qÁ(¼{GJ“`Ü J] |EáD K:Ká+Hý(í€awPñ[ ùõaT“" ?BîOé˜ø€R?(>¤4M¤ôT­Ë(œ­c*�¥PÚÊ=”ž€1{(톺j«7 é¡�UæP:”�#�Rš 'Áo(¥Ãˆ'(}g­Š)DFÀ€q” “á0�Rf]ø¾áJ[á4f/¥¯ÃðyÔw”þ�†ãÎe”î‡Ï¡TÚ._Ï xÜÄüE)¯|üÿBJÆÀUë|J'kÁ·µOQÊo— )þŸ&üBq\¿Dñõ |z‹â‹pŸ¸—âýðå÷%BCËËWÇ«(^j -£,JÖønj„’5 š¶R, Ÿ -¡¸º/QÌë_uϧøb�Úb¿¥xáðQ‡\Š?ÄBcõ#3[Ã7m²(©­)YÏ5‡ORÎQÌJ�æ.yO'ÃM2(æw‡ö¡¥3šÂMNR,¦YO%Ãó¦§(Ff“e”O§Àãä Š‘Uðhå³­àiÊÊÛáÙ”3ÛÃÃ6ç(ß ¤œÓžuÊ¡ü¼ ¤S¾ÜõºD9ÞÒ) ‡'ƒ (?€Ç�tÊ%SàÁ„bÊÏáy �²µÚ—X”Ÿ Â�G¨¸ziT¤à‹À=T<‚ÆP:÷Ã7iT¼m±¯Rq+|´:Bù»ªÐTù+Ê‘ÍðÕ<‹òÁ&ÐÒà_ÊÖRølR åó� ¡ýÊ%Sá»Ay”óFÂõ K” †Ã‡]³)—­€Ë…¥”/ö�/[ePñh.‚wSq¶=|Ú`/W„ãø×¨8Ô¾­ü ûšÂa�Ÿ©ø¹:|û:Y½à¨Cï'ÀסG¨(ž£ó¨x"¿¯²¨¸'E`{„rd+ �OÅG•!&¼JEáTÑé<‡ZChô'™=`H£½T\[ŸL*ö7…1•>¦ÂÚÀõÀŠ*>¯ ƒÂ�Qõv®&¼HÕ3Q0kY){“¯þC…µÆ ¼HEîE*.�€�ÍÐÕ¡–0²Ò‡tñqeº�N#÷‡`îÔ:*œ £S�ÓÁ™®0¼Ú§T~U Ƈï¥y Œ›Á„K.NÀM¢îsÅ,WôL]Ü<ªMM»¶cjø�ANMFâ�� �� ��’��‡��C��VP8LÊ��/’À!§§ mÆü‰·;�"%"IBì†ü9²€Ö[z›þïÿÛÿŸ�üÿßµíî̲³ÞY=±¶mÛ¶mÛ¶í݇mÛöc�™uÇÓæúŒr»§÷ä¾?Gô?ñô.P¹aû¾ƒ»µ¨YÖ|åjµì>¤O»ÿ/��í¿ñÅßô?úôèÜÆ>h ´\xò‹'´‡ÿxiÓ€ \®ºì½t:¹urXh(>öâ=:ÉøpyM¸;ò]‹Î﯇([œJ¡sëÃ1àFáe‰Œöã¾pîñ-£½¿º(tÇιM¶„ÃÎ_QG‚‚ÐÚéoj²ž«•ß ®+= /xÈ¢¾‡c¡òM QŸu²4µºJ½Ï•‚ÿ õÞl-“Ò¨ûzC�oRwÆ,DŸ?GRé8Ô¶¾!:N‹Ðñ±DóXßïŸÞ®Rœ1¥j\u9�Âó�gV˜n�_Ô·zñüð+¶›¾ï[‹Þ(€¨b_¥ÒzwR(-Ö_¡zræRýûÊÚPÅO|Û¢ò킈¢ÀëT…vV‡£@¿7©œƒ¬ñÖËmá¬ÊÖ'T½[Ž}©H?çm?¡Âš<(LÅk�à¼ôî4*ž÷Ãé*>©�¨|ÃîR§S¾1ÑUù€ŠÍp8¢˜ºØ�h˼Ä(.­N EkUO¦x«%tÌÓaú\èhr�bj8È÷Åo*BO¯'tê=ñŸSü6ê5?BWý:xкŠ|Hq”�2)}„¾F©|ÜúŠ|D)Ü ß”~+�­BT¤w�Îà�”>ñADéA èí¦hM„Þʉ”F@Œù“B¤'tÏ ¸º;G(ü i:¥½Ð¿ƒÂ ~hßNiÿ~/ýþhû¦0ôø…Â_ØûS°:Á�B_0Ï� p£ ¥Á°@ḅ9IMàÎs>†­6…ÌZp©ÎCfEÃ¥jê!ï: çàZ— .‡k§(lDÞß(4�{“NÁ½†þ@ž>‚›>¸ø>…FÈ]Ka, Marߣ=5†Si91É´¿ c_¤=%Ù­(L‚±)´BöB Õ`lU ‹�}‚ö;0ø6í'�ý!í/ÀàhÿÙ7i߃7Ñ~Y…-Ú'ÁàI´[…Q•B{Ü�BU4¤PW£Ðm)ÄÃàrÚ¢'…¢0¸(…žBÁƒ† /…ü08–B?t „ÁÅ(tF `py ÍQ�BS\‡B”¦0�÷¦P Y�h_ ƒgÒþÙ_Ñ~ï¤ý{d_ ýü í/ { í‘’066�öuÈîIaŒmK¡²ƒ™´Ÿ„±;h·J çKÚóÁPß¿´ÿŠÜízÂÐv!·#…gaè) �‘¸M{zYY:•ö‡ù�g?… 0r…ÓÈ۞½Â0°h…Èëû…Âb¸‚Ÿ>ØfSH( ãâPX{ð …µ0n…P »)$U„a•Ó(ì�T!•Âö<…ŒÿAÜGÁj £:S:¹b*…c`Pì¯R*@±™Ò*´†Ò6¨‚w)¤V‡15Ò(Ü�ƒr¥÷}0Ä÷.¥iP¾¢4†L¥ôµšF(<ª#þó˜Bfc8:@é ¼KiœoPZVRºRPJoϷΤÔŽŸ¡ôwqx¼ÄJ—á¼L"¥W}ðtà J eÅ0Škáé-‡#ª‹”"áá¡¥Kˆ®Ø¿”B àÙ!JÿÆ!ÊÖ™”®ÆÃ£®SÊhƒ¨—Püª0Lùr ´Æ\ ž�ŒÊ¤üN‹¼I9s <3 �òwñÐVæ ÊéCà¡®I”ÿ©MUÿ¤œÒžjý�ò½6ÐÒ<�òãNðX£»”S†@C¿dʉMá¹jÿRŽ,DԳ”¯×‚Ëÿ@ÅÁ�¢ ì¤â·ÿ“Å?¡â� ¢(ô"Ÿ—‚G ½DÅÏ•á¸Ü—T¼^ž ¢"¡-6¼FÅÙüðòj*ÒÆÃÑÀ$ÊÖf¼=!ƒ²µÅ¥oI„rætx¾Ë#*^, EÁsT$õ…u®PñSUˆ¿¤âfQî+*ô„Ðê6ßU„!…_¦"¼¶ iT¼ZƶSu©rbPµ7�“&ePñÝÿ�Uñ3*2gðŽ÷¨Hè˜u—ŠG½a\Õ_¨ÈSñ{-÷£z³Œ l¥sk[�¦ŽI¥Ã”±0¸É:ºÑF—~—>-Ãóí ò@ Ì•L1yž õ¡ðS<%bçýÅ<Î�ÁÓÃWwÜ’¥ãêÀ#ANMF°���������„��C��VP8L˜��/��!·§ mÆüqï�@�¤-¼{¿¢wzD_¢3qoض’¤mÛ™•mUõÌÛ¶mÛ¶m{lÛ¶ív�§jÔ®j×L1cÿ]�ó8#ΈóúÑÿ„ÿäîóùtGVö™Ã¿oýè�™�*Áè ]ç<òɶß�Éùcçg�Îï‘‚€ËxàojÝ?îîQFÊ xh/õ{\A9=^Ë£×K/w†ßHŸwré5ï­ÞPnÙ^úËœ[>’–勵ý++Àp©…'èÿäü<–^qžþO// ƒÎ¸lšÙ;Ê�‡ÈÔlš9:ÆÒ> ¹OÓ¡­þ-Í}Vf&Ÿ§É³c!;“/Òä¥Y0Pâqš~¹4„2oÐô ¥à7e+ÍïL†’¼‹æw§Ã_Ýlz¹´ëéU³Ç�0wõó?þK/‡áºéåÂögVÍ;lÜìOï¼H/ÇÃOÃãÔº»×·�@Švºùgê/´ÃÕç¨u·¯l…i½n‡Kí©fðÞø$uçh/M½Dݹ(®wŠºÓ·Ô�—z÷ž¡îL x­q’šKËÃk…Mÿ£æTƒjÙÔœZQ^Ë­¹@Í™ºðV1‹²ûÔ�ð“ò¤Kùè^ÊñG*ÀOåG\Ê'ÂKÂ'”³ûÀoÏlúø»=üvÛOù«<ÜIùãŠð_é-z~·ü——òÐw�SrïŒÀ„s ½¹k˜ˆlq)¹} «xˆ’;¦¦ÒC|.L͈SÊI„æyJî<˜›§6>æ¦Ç)½¹3Å¥09Ë¥n)LΣØRd¥§av55Âì#”~Š@Oik ~šâ§Q˜�}Ci Ô‡)\¨ Ó±/)dV€éôsŽ”„2‰ÒT˜¯”Eådu˜Oi®w~¥ð)‚¨~œ×åvDPÈtp]O … H›yÕ�@êPèƒëÞ£ðç•Íèa âZb>Õ¼Tµ˜Åo8(9—jA®N¥ð‚{dwiö4…¸úU·9‚K¨ŒàšPøW ©n‡¥ßS-LBñ` aé| CP|Õx:,M�S½ Å;¨î€µÛ©îB™ª·ÁÚ[©”iAa ¬@¡ÅHªñDX›èR¹Šj,ΦºêªßÂâo©>ó%Õ§añÓT¿ØEu,^OugÕŰx ÕÌCTgÂâ™Tž¦:�§zú8Õ °x"Õ{©Î€Å3©îÿ™êBX¼ˆêïßS½o ºóª/Ââg©¾?Õ°økª÷Ï¥zÑ�½‡¨.ìE¡¬M¦0¸*…©°v…Î ªÏÃÚ;©ž@ñ›TODaë?TßGñ| ]`iS «PÜ”Âðt …–(vS=WV–8F5Wï¡0VŽ¡ð®¶£ð¬ÜN¡®:‡(ô„…Ý)ŠàÚ ßÀ>g…�¸.9ŸB/X×—BQu\ÿ2…],‹þDáM(m(�‡eÓ)µ�ú …œ²°ªâ ßBè@éfXu7¥.�>£�×�5) ð)ÄfE¶:°&²ƒB¼%ä§)Í‚5³)=Mêe çSaIÊy S [BéXò¥åÐÆ~§4VŒ¥ôKô�] gRaAÆY Emáå1J_Fúèw”€§ŠG(­@è7PÊ)oC)vAÈ»Q ¯¯R:š‚Pgœ ô*Nik !.µ›ÒñÊð>Ø¥ôBü %wüB»€âÃðUê7J…ýÒAE”~+õ/QºØ ¡ly™ÒÅzð;œbN„°ÊQJî(ø¿›bV"B—”IñnHøœâÖÒY™í¿ˆÂDâ??L@¨bQÜ›3 ÎS|9‚E^¤x®>Lõȧø˜ƒÐ8�P,è sS(߃°8÷Rt§ÂäÊ· $7SÞ�³�SÞˆP¬¥ü4 Gߣ¼!XKù½(L—ú†òF¾žòw¥`¾üÊ7#àM”¬€ *gR¾A:·Pþã“ò凿ÜGùŸ4•±Ÿò3Q}’òþ Wí å7b$ö*åƒÕdµ”?)ƒ�J½O9»&‚­v€òÖJ0^ñ[ÊÙµtµ”M�áäŸ(®‰à«þCy­¹�ò¾jCÚŸ”O´†Á¦Ç(ÿ•ŽpÜøåK}a¬ûʿ߄°TÚF¹`2 �ͧ¼' á)ûew-Œ,w)Sa*ù65O%ÀwôAjÞ/…pEŸ¤æÓ ðYö}j^J@Øœ[¨ù­ |¥þ@Í}B¸È¥|¬-|4>LÙ]�pŽÉ§üß(xîw‘rÁ$„µûÊîÞæQ¾<�ámv”šWKÁCìQjN´F˜«fR³3ÚÄ/¨ù«Â]ñsj²[AÓp/5Û*#ì±§©ùoÄA©y¥$,XíRsOг:NÙÝèÀŠ1¹Ô|™„ëʾNMÞxØÒþ5û›àj�LjNw�=Õ~£æò½@Í_µaSù©q·ÜâRóE"ìŠÞEî}QX7!—>r'ÃÆvGéùX{Ø™¶‹w§ÃÖ’OÑÓK¥`ñ¬|j –ÀîG©9Þ¶§n§¸= öǶäSÉÝÃÿ…ª·fÅYϺ9a�ANMFª���������„��C��VP8L’��/��!ϧ mÆüyï@„€ D’¢mf&˜Â¬™Uó´°m;#IoR­Q{lÛ¶m­mÛ6ǶmÛ^{·Ç¶§ùžõàÿþäOþ=Žè¿S¢Ã‹Ã¦.Ú°{ÃÂ)C_îXfÝR]^>uцÝOþRÇ’‚®ðÌâ‹Ô]Xþ\y˜qª¿²öu—–>[ Á•xï_zýû³2ð]õûCôšöQiátY’E?Ù˺Gà#fÀúÊ^ÞÃ�é¶;éÿ÷žðêÞ�Fÿ{;Áh�u4³¥)<µÛG3›ÂXìÇ™4•3¶�´IÓh,ëË<0Óð7šLk M»#4ùWS˜x,�f³¿ˆ@ˆú.‡f3Ÿ‡ï˜4¿8?”Kh~B,ü%l¤§ãk†}òú3¯:lÕ1zú±8î(¶�^²÷¯òѫϼöéðÕÇèi{2ü$î¤þøÄþ©�R{�;FýÑʸUî0õÿîž�)µïøcÔïK�÷äÝÔe-í�Þi7/“ºÃe�[,�º«ãš;ÐG:/̢ðšo5ÙÓËÃkñ™Ô¤Oý•š«ß�×2“³©ù1ÞÜyÔl¨ ?•æSóçnjf…Ÿêk¨Y�§Ï)_yÞ�Ï�çèãhWøtž¸Lù;xHù·Šð_l-=¯/ ÿe~¤ü ô%/P\Ñ£èqPLäŸKñRYèÜuG¹0ôj½¼ Cî Š["мHq”cÏÑÃË0æ ¢ø:äbW(Mp`ðMj?†Ag$¥k%!N ´9F¿¢f2ŒF¯¥4RÝl  ¬;›âæX˜Mþ—BNCk)d5…é<;(ü— Ó 2)l„Ú€Ò—0_(�Êùª0ÿ¥ÆPfPø#T9Ç;2Û#€˜_(ÌÆ�¥2)tC ­ÓyûiÒ�BViÜñ9…õè~ÞŒ€VRø·Ýƒ!¨˜»<‚€êQ8ìâV [˜3í—x¶�B3ÜD¡‚‹-†àzR‚›ÎQªG"°2rˆê1¹•)|K¿¥P¹�Rh KSx¹“©u`©s„êä¦Q�k§QÝ�x OÃÚ')Ä×¥P ÖÖ¢P·ÕÌhX�Iµß[TÓ`ñTßIu,^EuÔtªcañXªÓQýGuá:ªÁâ©®ÝEõuXüÕ�Û©¾‹ß¤º}Õ`ñ‡T×Ì£ú,þŠêÂIT§ÀâÑT§¦º¯¤:èyªañŸT_èL5'ÖF]§Ú£<…æ°¶…QT߆µORM�ÃNª+aíTª»�ûÕë`iÌ9ªƒ‘Û�B?XÚ�Â]ÈMʦ:–Ž£šU7·PM/+¯PÝŠ[ÏQx V¾Há Ü*–Mõ`4,ŒüK5§"no¢p,¼‹ÂÜq/…_]Xõ…‡pGÜi ÷Àº(\Ì�;?£ðO ,˳ŸÂ×PJ¦Sx–½M!½ÔQ.‚UÅ®P˜¡t…±°j …Œò�FSÈn‹ZS±è ¿ÅšØ?)\-ù]JïÁš÷)}�M¾ÃnT†%•nP8”º~”¶¸°"²™R?èWRzV¼DiB)½BÙ&ƒÒ‘BðÛ$ƒÒ¹jaÕó”2šÁÿsG芤øLL øKB–òÅ 0»�â¶|U¾í·ÇÁL‘ƒWÆ D1Ë(( SÕ/Pœ…ÐDͦx±&̵ˤ8ÕEH"S)ft€És(Žs w,ÅœaöMÊ£„ÀFù˜By„ƒÀ�¡”‡Â¸;•òH»#(Ïta>zå1.uGS^� ò¬£<)‚�#c)oȃ`òo¡<3�EO£¼½�‚JØEyQŠ›Oyw‚KÞCyM~’oå½I2iåíÉ a3åŸRlÒÊ¿…ñ"?Rþ¹ ‚NÚM9­ —û�ò©>qå“õ`´öqÊ;“†ø�”/µ…Á–(oŽG8ò.§œ~7Œõ½NyM>„%f.åœ×`è…lÊK➨‰Ô �À€û 5Ó¢&w5 òÂwÜ,j†»ÙÛÔì* Ÿ©[¨ùá{<‹òþjðUñoÊÙ/ Œ}nP¾Ð>šŸ¡œ>álužræ³ð|ï Ê—Ú#¬ÕS3, žÜ�©9Qá-ñ+5«á!ïljþ,ƒ0'®¥æ�òÐßCÍÖ„;f5gÛAÓä85sâvçÝÊY/C|8�rÎç,¸7�š)y D ¢&ýaØÑò,5{JâŽÔ5Ôœk[ÊÿAÍɸÕà 5ÿU†=I«©Éx ¹�Ü fK*lŠAݘ±ÔMŒ…eÏfÒWæ‹°¯ÍYú8Û6–û•ž+;ãÐãâxØê¾“M9Ÿ¸°¸Ëyj/õ…Ý~¥æ�*°½ÀlŠs À~ç±³TN?Šÿ‡ø'Wœbî©å�çG�ANMF¨���������„��C��VP8L���/��!§§ mÆü�w@„€ D´ò*Ú¦E†÷°Áx�ÿjÛ¶�‘¤»86wlÛ¶ms=¶m®FkÛ¶º{5¶m4•ûôööû¼É›¼û9¢ÿ ïù›�]ÿÞ×ɇÎøí‹·×Žj”Fó5»þ�/?pú`ÒWï­×¼�|Ž·_ý§C݃”å­"0’£ÃºÝuÎßk;æ€oͷߦÛk;šÀk¨Ý«·éöö®Vð#çcÓ[Òø\ð�Ò>zÛûd.ŽM8Eïg&Dà2ÇäËô~öÑLö>D3ûúÂMhØQš9:ÆŠ¾Jsôg4÷N ˜p‰&/õƒfè5š¼2¢ëhzG9_¤é-1x-üÍÿPJÑiþ›bðVá0ݤÿõò¢Éc‡Œ›ºôµÝwéæH d«vˆnî$¿¼hÒØ!ã¦,~ùÏ4º9^^*� þïUmc�âí×í¥þZ#dÕ½B}ÒÂÖ1HÑ6+ÿ¢þLu¸¯rŠºÛÏ5‚›F;R©»R™UÎSwm]m¸©ÿÌ-êÎÕ„ÛR§©I[[n ­J£æ|Õ2Ç©¹º �Ü\y‡šsåà.w5¯”†—2»Ê'÷SNl+/%wQów^¸ ¿Eù|_xívŽŽ´�×îg(†‹”¿* ïEÞ§ë Â{¡O)/‡¾é}ŠOEa"¼–îœ%!˜ˆl ø t¹PrfÁÔÄtáL�©É�ä…f+%gÌ�u¨u&ÂÜ$ŠÏAn˜ ´&Ÿ vL΢ä4…ú†Òk0»�š§aöyJ?BêK)9̆ž§øyfsüLiÔÈA wªÂtü û ÂtÅ[ŽD¡ ¤ôÌÚOår%˜ŸHi(”Ÿ(|‚•.2[Føú‚ÂoÈÞœB¢!|ižÆ,g4|©› Ð Ù^¥ð|˜à¿+áÓN oà¿<©TïW€_3™ùN>•½G5-/²†Pxþ=“”¾½Ba8²Þ¥ÐþE‹Á¿¦ÞÿyÒ©þK“¨¦çAf' ³`é ��¹˜ªS –Vt¨.EæWTÿ„µ)T¿F,•ê&X»�jj¬…°v�…=)”„µ%(ôœBõ2,¾DuÊVª¿Àâ_¨ný€ê˰ø%ª|Cu%,^Iõë$ªs`ñ\ª¿ï§ú$,žDußiªã`ñ8ª§ŽS‹'P=þÕÇañ$ª{~¦:Ï¢úÛgT7Ââ•T¿~“ê°øªo¬¢š‹¤ºz,Õ´ì=GõáÖjÁÚr:§ð¬Lá!œ ú*¬ÝLõ$2_¤z5 KC'¨¾�Ì :ÁÒ&¦"³…m°t-…Zø÷Õ[yaeÎKT#k9…ñ°r4…�ȪOaw†’(´Æ)tƒ…])D¶~„}¡ß)ÌF¶ÂiºÃºÞî•BöR°,ú…— Ôs(Œƒe�RpêB}�Âùü°ªð Ÿ@hèPX«6SpšBzŸÂ½º°¨á ïA¬yŸÂ¯aXI¢p¿ä­”&ÁšI”ž†¦Øu ·ÊÂ’2·(\+ Ýã”>„¡�(=m$™ÒHX1†Òoaè›> p½,,¨pƒÂ½zp³‰Ò·a>ö3¥µp•÷¥…ü JÇrÃ]7J: à�œ®p»“Ò…ÒtùË”vÁuÁÓ”~Í��çN¡tº Üwv(íDpC/QJt�—u§#°Ó)®‡§x¥½Ðþ JÉqx«|�Ò�Æd“TJ×*Ák/‡Òù `… ”œ>ð¾œâ�"\Ñý—Ã@øŠ¿äAÀòþFñÃ0LäßGñÓ8ÿŒâþ0Så2Å7#Pä5Š—+ÃT« Š;CLxÅŒ607Ì¡¸A m¡˜“³(¯C@ÖQž³›)¯B –RÞ Ãá×)¯@�–R~# ÓñO(¯„ï+(‡ùRþ—ÚGùD ­zœò�ÒB‰¿)_nƒ�.RÞ]Á(ü+å;=`¬Ë-Ê)E”|_S¾?†Fߣüs'ׇÔ, Á@h5ŸæA�b¯PóB ž£ÏRófÁ o¡æ«‚ð˜ïcj¶E¸Ôì­Oeþ¤f‚øèÊ[ÂCƒ3”“Ì~é”ÓGÀu¯Û”3†"¨­®RvV„à*4=Aùf'·ÖIjÞÎ ñmÔœ©� —J¡&©´E¿¡fwY;ïGÔœmMÝcÔ|]A�l¥&c,Äþ·©ÙƒÓÔl‰A /v('fÃŽþ©Ô|S Ùò½KMÚ@ØÒð 5' «æ~jÎ7ƒ=¥“©I†Ì�·¨Ù]6å~›gÍ:ê>Ê»ÂËzrV…aÝàTzH럤ëS ag‰ïéò‡°5¶…®¶Åañètjï>»Ÿ¤æL Ø^ì+Šß‡ýÑùiTRçFð¿ðÐÂäû̼—<¿$‚��ANMF¢���������„��C��VP8L‰��/��!·§ m#ÇüaßüA B@P"IñÓ˜cæÔœ™Å˜óÔhÛ6õHû‹QHÙ¶mÛ¶mÛÕ¶mÛ¶Sm”íØù¾àÛ¿ÓéÜsß»ïÝþÑÿ„ëèóo~ë�s% ¥žþåå}ÓÚFÀ`TÇY_ûõLZK2Ïÿñö- zÆÀÛf+ßȦ>å™95`¤þ¢—3©ÏykU x•¸è;:.ùdj\ÆÍû&LÇ?.­ߟEw—Ö…‹&·§Ñ]ÎÃÍ`¸ÎÝAºÏ=P«ß¤ûÐõa0foÍ\_±;2i&ÿp,Luÿ�æ~hm§ßh0uC1Mæ¯ @ŒÜ¤É’Û£á¾Æ'4ýa„jŸÒôWµá¶Óišÿ§9”fGiþ|w¸’Ká“oÞ°pʰþ#§/»ãƒKt’Òú\§“³oݺdÊð~æ.ºá�t’?nFP|cy#Èm6}RBmáH”* ¶èí¥Í!7\òZ!µÁñp>º�ºSÛkÁIãÃW©Ë„²ÙÔ�Û\Njl9A]hœöRsqI$œÆnH¥&»w»TjÎ.‹†ÓÈg© �³¦×)÷ÄÁMÕ[‹)§_¢º!nb·RNk 'Uþ¤|¤#Üö>F¿t„Û¶?P>Z úÀ”ˆ†û„ÇèøÉ8¸�¼“ò{hS,Z 3ÛJé¨t-Ì, R\ ]³JÁñ055HÅó`jD¥¼V�#¾¢s“‹©-žs# (}q>¥Òi09§”šð2˜WBi ¤„‹”vÁì:jn„Ù-”®T‚°�Ò‹0}7ÅW0ü¥CPkåQ8_¦#ߤ�œ�Ó•NSȯe…Òa0Ÿ˜Låb}˜TJá*Æ]£ð¼¨wžr»Á‹û(¤Ä£Âb 9uàIÇl–—N†'53),G…_)ì�G#‹ùï6x´�Âø¯-…Ôxµ”eOÀ«¸ë: |?…áÝ-_Dó¢üª¡úð.¢2¼«¤zÿ¶§ð2,}‘B”­¢0–N¥°eÏSÍK€¥ñ¹T_@ÙEª¯ÁÚW¨^BS `í: ÍÆSèk»S¿‘jn$¬�Ì¥ºñ~ªÉ°8™êýR}¿@õÿ©Þ‹o ú÷ª+`ñJªç3¨Î…Ås©¦Q�‹'S Q‹‡SS ‹GQ çQ�‹§P-¸Fu,žC5õ$Õ-°x5ÕsÉTï„Å·PýéEªoÃ⩾tˆêXœLõæyTÃI°6>Duy `í� ýâ‚T;¨†âðÕ£°ö{ª?¢ì íaiÃ0Õ{P6’ÂAXº‘ÂX”ÅåP=+ÿPÍ�ÿÏR+GPxå“(|+ß¡0åqYTÃÝ`a×0ÕÌxüw…Waá[B…vaªáî°®¥ž¨ø)…`[à3 _BOi ,›Bi<”ÀÏŽFê¸Óþ @�Di3¬ÚIi:„À/rÁ¢¦ùŽ ¥ô,z�Ò(ÈïPškfPzš¶E®$Á’ªW(„Ú@w¥Ç`Éc”n‡¶Ò á‘°b¥³‰ÐO¡t¡,¨q‘Ò8y�ÒËðà-J/ÂQƒ,JËàûu”2êÂÙ J]áó®AJËá0ð)¥“Iðu�3”> Ài“JïFÀÇQSÊiçK(ÞßFq ܼL)<¾�Kñ¸J:G©°?|:0Hé\5¸ë¢”Ò¾l�F)ÔnWS<^>¬y‚â:¸†â÷ ð]âwŸ��ø#ß�†ÏbÞ§x$&^¥øl�¾ŠxŽâÕF0Ó·�â½ðÕÝ úÂÔÌ0Åá£Ãóanå�ðÍ.Ê;aòAÊ›á“Í”†ÑÈ×(†×Á«(¿ ³ñ_Q ¯…V…)~ÓI¿P ¯ƒçkÂO‚ùÚÇ)†7Âã ”OÔ…�ÏSÞO7Q¾ÐÞ´¼Ly?<ÜMùJkxÕî:åÛð(p+åkíá]§ÊEÀ“ˆ(§v‚—�R(¿ ¢ž¦œÞÞvJ¡ünŒÇ¿I9½;¼î˜Bùë$Nú’rj7xßá*å?ëÃh½ß(_ë?´¾HùllqšòŶðGÓ“”SûÁXÏk”Ï6‡_êÿI9 �É£|¢üS3™rÉ*YRLù×ÚðS•/¨¹5�×�ýÔ|]þŠ{ƒš—âà2æij>H€ß¢§æÛšpUísjž‹†ÿ·Psº=\4;JÍ]ør})å¬QpÜÿ:åðvøuF�rñ8œ¤Z�ÿʤæ�(8ˆ¸�šìðs‡sÔ|”mâ+Ô\ê ×M¦æX[hšüBÍŸ�á÷Ä·¨ÉqP 5U…ÿ#tw�êÊ"jŽ‚J¨y9b¢¦d3l—MÍÍQÞà[jò&ÁžŽg¨I†²Áר¹Ô6Õþ–šâM›‹©9ÒvÅ>M—ÏÅú-%tQ²6ŽÎ¤ã¬±°³ÍQ:<Þ¶V}“Ž>H‚½ûJ© ß «ÇgQ“= ¶·þ‹âßma¥GÃTJNÄÿB—ÇSX~ýÑÎð�ANMF´���������…��C��VP8Lœ��/�@!Ÿ§ m#ÇüaßüA ‚@ÒÞ=�_Î$BÌâJ¤Ø�{1ˆ&ÞƒÚ¶m‡äè®3¶�I6¶mÛ¶“µmÛ¶m+öîNìd˜FÝ ƒ÷y«Þªw?Gô?á;«Çü{?Ùu¤”I·èÀ–wožzE* ftšqûûÛ¹L–Ýõé} zf!ØV«>.¥þÔk³jÁHÃEïQ_öÉÚUaÉôì~3%>sæþBï/¯Œ�š=YBGo­ M8C¥Ï¶„áº�Åè¿äÖŠðXý�(ýÇŸnƒY·–Ñ̉5ið�yÍ9š9w6LußAs¿@Ûa Ííí #é÷$h²lmbêUQštÊ„ÿšßÑô•!Tý†¦®¿] i~W3(ÍvÑüáîð7¼Œ[_½vêð^�ûŽœyË{ûéåD\Öó=¸;_¿qúðÞ�z›rÍ+[ôP>~Fž§¶äåÕ!7ZúaŒÚòa¸Ø¿ŒÚò7gÔ…\mÚ‹ÅÔF'ÂûØ(uÛVT„—Ú×RWÚÉ®EÔí^Q^*,ÝL]l ¼ˆR³gj^Ó–¡¦¨{Û“Ôì™™ ¯ÎÄ�ÔćÂ[‹S”KÖ¦ÁOÞMQʧS.¿.~R—S>Û^ªì¢ü} øí¸…>~m¿�¿¦¼¯ôÎÇÝ»Rà?óaz~4þ#7º¿Š@»ŒbÙ ˜Y§§ø"˜™\Jqt-K)• „©Qeô� S½Š(•µ�œú ¥’�07"Jml4Ìõ*¢ôGÄ”bÃ`rbœwLö�RZ)ÿ¥Õ0»˜š`v1¥ã!ÜBéi˜¾‹â« ?Bé.¨µË(ìÎ�éÈ›~΂é¬íÊëA¹•B¼'ÌgÿLåßš0ß5FáN\ž{’Âý¢Æ~^v®‚¸ƒÂé<\¶ŒÂ©Ê¤õi^Œ�@ �SX‰KÎ kPÿ(/¬A@Ë)ìÂ¥e ¨ÙL>† ÒPè„‹·Q¸ÁÝøEÛDá\pöQ-­†àœ\W¥„ê~ÉŽž‡¥ÏPèŒäj #`é0 k‘|‹ê™ Xš~šê;pŽQ} Ö¾@õ¸ÓŠÂBX»€B«ñ `m…ñ©žr`­s’ê¦'¨~‹¿£úÄ×TŸ…ÅÏRýz/Õkañ5T÷¥:Ϧz´„êxX<�j …¡°x(U—BoXÜ›žúÂâ~bT‡ÀâaTã§©Ž‡Å㩞û�ê2X<�êá¿©Þ ‹o ú×ÛT߀ÅÏQ}çvª;`ñ÷Tï™K5ž kÓ˨.ïMa0¬íJ¡onŒê-°v5ÕX.~¦ú7¬ý†êŸHÞA¡),­™ ú’#(\ K—P�dN Õ½¬tþ¦Zšƒ ¯S+ûRø�'RøV¾Aa.æSu `a›Õ¢\\z”Â˰ð Oá²vma]—Bw\þ-…waÝÇ~„2–Ò�X6œÒ8(‘Í6§Âªô�vE N ´V­£4Bd3…3µaQ½sþŽ@FéMXô¥‘�?¡4ÖŒ¦ô94WÄ)æÃ’¼B ±6ÐÝGé!Xò¥ Í?D!ÑV p)æA?‰Òþ|XPé_JcàåJ/ üÎë”Þ†§úE”f!ô‹(�­ oË) ämK)-ƒÇÈ·”¶ç#Ô•vSú6¯M‹)½ã Ä)Q*n ïK(^�ßLq1|8ïPr'"´]JïÂW•”J»"¤ÝË(¨ =£”Ž4D(›£í ¿«)n«ŒVÞNq|;¯Rü. ¡Ëú–â«0�óÅwR²Ô÷(þ• �Q|ÚA¨œ§)k3½Ê)Þ�PÝI±¼LMs)^‡]CÑ�s×P^‡Ð¬£| :ORt—!$Ë(?£©ïSt!ó\Š¥ÂlöÝÁ<—âO90]y3ÅÄB¾À¥¸­ Ì×ÞKÑ]Š€»÷ÕA�PtW#Ðe.ŃML‹#”¯B€ë)-@PmOP¾A97R>ÞÁu8Iù�8÷R>ÙA¶?IùÙT�òåÓ]lû“”ßÉ„ñŒ7(ŸîŠ ÛŸ üu> çAùTWßîå?jÂhõß(ï€0¢¼· 6ÚIùpÂÑôÊG»ÀX‡C”ÿk�°ÔÛA¹h :Gyo#„§úŸ”csadF”òæÚS¥ï©¹Ñ�oç*j~ªŒpe@Í éð™ö85Ÿå"liÏSóueøªð)5¯g |‘{©ÙÙ>l¦æÁB¹Þ¥|ª?¡Éû“ ¦?¦ÉgË‚pŸø5M›¡è�4ýcq¸­ušæOT†Rù$Í_¨w­Bt’¾sÛÔQ}ºö=óåß²è$£%òµH§“Œ�/L‘ܵïÈ)[I£“»à¦Ý=jÃ;g×�hºøÏ(µ�:#¯íj#;§×‡\{ÆOajt†óŽ÷©K[U Njn΢î~ä6 Q—¶¤2œTX–BÝÃnpÚô5·fÆÃiÁ…ÙÔ„š×¾IMÚ´8�›šAÍ£VpV>…rxC"ܔܡ|ûåð¦BpSxõsÊ•à¤àÊg[Ãm‡Ëtq²Ü6?AùXa8x�òûà¾ÈûtüQ!¸�ƒò'ТY#�¥Q:Ê™ 33ÃGAW>‹Rx8L N‘ñ0Õÿ9¥P%È�Ÿ(…‡ÃÜ�µ‘0×ÿ9¥Ýˆý)EÇÂäØ(uSarX”ÒHñ)m€Ù¹Ôl‚Ù•”®$@˜Mé‡ ¿Bñ› ̾¤´�jÑ…ÌR0û…c…aºD…ìâPæPˆöƒùÄãTÒ+Á|¯(……È{�ÂÇð¢bó=j /Þ¦�‡|C)<® OšÞg^Î`xRá!…‘È÷…õð¨w„ÿ.…G«(ìÇU¢TïƒWS˜û>¼J̦­†¼yvÀ»-%À³Í"ïÕH x,ïªF¨Á¿U)üK¿£P ¹ã(Œƒ¥£)ŒCîTŸ‡¥ÅžR}¹ç©þ k¤ze(,‚µ ©FËt¡ÐÖ¶§Ðu2Õ§ °6á)ÕÉ©ž†Å§©nþŠê·°øª_¦º o¡zè<ÕÙ°xÕsiT'Ââ‰TSïR‹GPÍSM†ÅÉTÃO¨öƒÅý©>¹Mu,A5ë*Õ °xÕ'¨.…Ås©žýƒê+°øª¿¿Mu,þ†ê;‹¨fÀâST—¢PÖ�PݘÂ`XÛ�B³ØT_‚µ+¨>ˆÁNªWaí1ª¿#w …æ°´&…õÈíHa,]D¡3r㲨fÆÂʘ+TC±ø÷u ae2…‘דŸ°r…�È‹½M¡5,lMáv<þÛDá{X¸“Â6䫞C5ÚÖu mˆüßSø¶þ¦ð ”î”úòᔺAÝGár¬*”Bᄞ”êU”ú@ÚGáQuXTû …¿!¶�RØ{»)D;AþœÒhX3šÒ—ÐÔxJáv,IºMáIuèVQz–¼Oi5´/Sê +þGéBè{QÊ, ÊÞ¤í 'QúþþLé]8*“Ei|?ŸÒí$8KéiKø¼ÕsJcàô{J×’àë2)”~€ã !J»càã¸ß)…*ÀùHŠÛàã)Ž„›÷(އo'P|®/QzÖ>íöœÒ¥D¸kþ˜Ò?õàËÙ”7ƒÛ ¯”…Ë^£8î_§x4¾K�òáD˜O:Ey<^@ùL)xQá2åðt1å+àMÕë”×ûÀÊ)ÕáU­tÊ/àQ`;å´Zð®nå·càIÌ›”3ëÂ˺”¿Œ‡qŸP¾Õ�ÞÖÍ ¼«Œþ‰ò­Fðºn:åƒI0\r?å̆ð¾N*å³U`´ÒÊ©õà‡êW)§6‚Áz7(_«T:G9Ô ÆÚÞ¡|±2üRú(å'ƒa¨ÿcʧËÃ?Å÷QΙ #S#”&ÁO…wR³#×ÁõÔì-ÅBÍW…à²À'Ô|��¿_¦æPY¸*õ75oÆÀ‡+¨¹Þ.ê\¢fü9)Bù~_8î”E9güšüˆrdNxFùÉPø·ÍjÞˆƒƒ˜MÔ„:Áϵ/Qó[Ih¿¥æzCø»ÔßÔ\nM­ÓÔ+¿øœšû!vÿ‡šo ÃÿÁ�ÔDW¡Î S³-+&=§æÛ¢ÈWàmjÂSaK÷5çê"¯êajîö‚=u/R“ݹ=îPs½l*¹—šÈâ%9Ôì+ »â^£Ë·âaÝ´çtž »dÑqV7ØYý$žª [ FG_�½�jsV`u÷,jB½a{µc�×€ý_ˆP o/€ÿ õ^¾Á¼/Ô���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/dci_heart_dci_normal.webp������������������������������������������������0000664�0000000�0000000�00000003204�15226154130�0022502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������RIFF|��WEBPVP8X ������Ç��Ç��ANIM���������ANMFP������w��n��d��VP8L7��/w€W§ m#ÇüQßú‰ ‚@ÒÞ=�;Ñâ(Bܹ؈[qÎ…Ø‹P0D*˜â+dÛ¶mHÒ.·mÛ¶mÛ¶mÛ¶mÛ¶m–«rE#ÎɈ›ïýO8.Ó}þÑ;¯~$üxuûØ‚îåCa ¼r¯…'î¼ú™ðãÕ�£ z” �ù”�¶}¡¿ï;º¤‡£Ì½÷ý¢¿¯;º¦†Ñr«Ó^̦J°T{g<íE®«cNÐÉ•º°Õø6�œ©#yÐé±Rð[á,�.�ÇÁ#é,mž2KûÍߨûúÁ^ÕkÝ’Á_x»sÔçãÏdêg‡Â_ÒΗ©„�–>j÷[À^�«T'¦ú¨ì5¹Cµ=ü—‰¢7!vƒzþ¢Í¯ƒÃ`7dL,•˜Šð—å-•ç%á$ÏÚº“ NŠ=¡ò!;ü¦r+œ…o¢�ã©á,Óu*Ç‚ ö¦r.-O¡ß5apšê•ÐrERH 3èg Dì¦ŒÊ e;åÕYLusL„]¤Ü Y‰òG^˜ ÞOå\ÌäüJY âe+˜J~…âiF˜jBy Öª”‹a.ó Z¾�¹”5aÙGñ2‹ýà¿„ú0þŒâ þçK¤è £õâù·Œö ðÀ¿É¯#`¶;ÿ,‚Ù°Sñï>E˜žy$†ûP<Äß’o“ÀtPr˜ŽxMQ &PL‚ÆSLŸEá�Â'Ië=xâ­Qaå)à )*t§h O´¦è>“"'<‘ƒbæ.Z£‚à‰ (Zw_£õ6F“r1e¸¶ål(é>S¼O —¦ý@ñ% ´>”«àÒ•”ƒ¡†Ü¤ðÕ…+kù(î‡C¯Nù&\˜âe øÛD¹.Ü@¹~3|¢ì×u ü˜þ;Pþ,�—åÿEÙvvSÞMW¥¸M¹¶2¼£<7í¢|ŸöR™ �¡Òv—Pi ×´ðQ®€í¤7(#ËÁ%å£(¯'…ýÜ_(?æƒ+r ü’Nê&P>Êd|@™Ø�ÎFP¹œOy…Ê88ÝFåt8ü•-Apšä•ƒ¡hè^*g#à<Ý}*;BÀ�mT¥‡‰Üï©ìEÀ‚ÖSùœfÊü¦²3 ZIåwy˜ªKeW(¼šJl]˜kž@eW(¼ŽJbK˜ì裲; ÆC6Rë³}¨í ‡áˆ=ÔÁô0jÇ’ÃhŠãÔ†ÃüjÓÁ`º‹ÔÆ #¨ÝÎ cYoS‡À §ö4/ åyJm 5ˆÚ»0Rü-µ¡\¯D*ßkÂ@¥¯T|}ÈöñTbÛÃqÓ(*‰]Ø&1T|£à°_"•ØVt�_Ô–…ÀAÐLj‘õø²Ÿ¨LÛI¶SûZ n(ø‚Úå̰™á<µ×EáŽl·¨½* [S»—nI}šÚ聆Qçµ éឈíÔGÀoïxj{“ÂMA³©® ‡º�ê¢`¸¬wµ Y ¤?A-qÜ×ðµ7å!Š=¡ö» ÜXò5µ˜.°4ûEíMi¸3ëeª‹Bñ'dº�Ú�ìpkÒ�TOeÌpŒêÁpoЪÏ_P� W·�¢Íèvp{é—´õª ÜŸémœÏ /„-¡ß5áðH—ª±}à�²¯¨¼ª�/eØEkü’ôðXùŧ?D>XQ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/dci_heart_dci_pressed.webp�����������������������������������������������0000664�0000000�0000000�00000037530�15226154130�0022670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������RIFFP?��WEBPVP8X ������Ç��Ç��ANIM���������ANMF&���������������C��VP8L ���/���ˆˆþ�ANMFš������^��W��C��VP8L���/^À'ÂsY.& ÀU�ÛvÜ6�Ð/À[_ ÈÂÄÏ×M\@àã¥�ˆþ'þçëúBçu¤üÅj.hø_V¿�ðà½àöÚx[ zlT¾±± ãÁ6.6g´ÿ²3ã v -ߨ{`²;¡ìÃÝwgžLÜ‚™`âµoT¡~Rf¨‚:\N!.§Ðp…†3¨Äá”âpJ ûJ©aJ {P‹}£N1œb8Å“S\œâ‡SlN±9Åæ›S\œââO ûF-ö tÆ”þ`SjØ�Ò‚ýƒÒ ÇF%Πðço §S8á ÊToÊ •SVPS†ÛJ‘áæÜ)Bc¥ÄÐpJ ZAÁ‚æ›C›tV:Îá ½ààŒ®s° š‘p=� ,H9ÈÓ ’ÎôÙ`rAÚ™| LÍp¦ F‚ ÃÐ\Ù5Œ²‹agÇ0l.8›Š• ƒäƒ ˆœ7ƒ*X-�9« º•§A< ýˆY�ANMF"�� �� ��“��ˆ��C��VP8L ��/“�"Ï Hò§~ EµmS/Èóÿ3€TÃzÁÌÌ„��èCmfC¨FgU�ÊNÇMÊ �¶mÛuÛfó�¦ …p€‚9æþÿÕ•"q9O}ˆèâ¼ÌËOÙøª·ü„ª2/?eã«ÞRðhþµÑ«GùZ �èÕ£�,¿<®Ñã´‹<¡Ñ¡‰/<»Î8u)<»Î¨î k¬3ÏÊ«GUI¬U<ùÂZEP/°fÄgI¬¨PIþcÝÕáƒSÖ-‚žõv¯¬®3Î_Ùâ;‰-œMl“ñ*‰m2Î%¶Z'ìô êÚ¶Wi¥×`ÊÈ�•AZ»S–FFÂ{þÇG]Š�Í÷;¢ÿ GjS”Õn¬Ê<]Á‹Údeµkª2ÿG!U|µWNþÜ—+8TÅG{ådßîKߺ9qžmk 'º9qÞо¿ÀŸzm¹¨-°T½ž¹èTÂ�jz.¾6+,Hö=÷�‚sµëéäºÅ\µ³tÒÿÇù•κ³ÊžÎºÕ�þ(aA:0b«±¤fÄ5–m‹…ëž‘^,Íç�aù;£|ƒ‹##lá$é]§à&µŒÌ¦pU0®¡„»†Q5pù͈¾átud4'8V#1 ®×WFÑ%p¯{FÐkøØXoSøÉnÿ…¯‚aÛþ¶ y(á³b¸Ã~+†:Ôð]1Ðþ+¹CÜ!ŒŠ¡ 5B©–Ý"œ’!Ù!僱ÂÊ,±9BË,ƒè7/íÀU#DÝÑ{§fr¢g“ TÕÒëY!\õC�„½§·/„^ÓSƒðË�ì1d=�÷9âÐw±$':5 âQ?tx@\{:{Cl¯�Ø-âÛôtÐgˆQ.6kÄ©\xX!Úw.js9p¶-wÚqf§{râ¬? ì9ã2”–OìR¼\8ÙiÈ¡¾ùh?WEï/üÌ»F(�ANMF†������{��r��C��VP8Lm��/{€Ç„ÿjN#�@"š»ÓÜ#0ópÌC¥ÒX’û»Ä$� ?I1iI!UY>y&E `Ûd¶I”ñ4±œbh£ÕEq�dŠàÁ*Œu˜6¡lCõ áÂ>˜g‡`½s â¤s ï @6�ºj¨K ÐÖ¶íIc½¢LlÄô^H/f\šÞ{E×�Îßó?’øÿÿÛZ;ýOd©m´îþep¼9ÖäÎÉc—ýþýñº ÖÔ‘ÇäÎé’…L…•³€Éíã¨-î¼1m§QFêZ+`ZooÊìz—™ÎªHU»Ž™%:°¡ÄÚ ˜5jÙH,ÇÌÚݵ�}ü‘*ü$,Tñ2†Œ¹�˜ŠN bŸSQ¼‡L… ª{«aÀñ¨î*�ôåª §Ð7PåKiËÕFËø^Œ©¶]FºªGåKøœ‰©º]Eš¢GõÑÜÔ_ªo‘œ¤Ž¨K�y$åÎ(èI뵉áÕ.EEU ³(ì1‡!·…A»Cq~Ø@ñ/F6úv)²ŽŸ|‡"} ßËêâûšBoñeÇ”jã |^Rì,ŸbCÔ(ØY§`·EÁ‡×|óNÁ1Çü_,¦àÞ;\Sðmƒ‚�\ ^u(¸Šņø<£Ø |.Sì2> …öl|]Rè ¾)tßV‡"ý~v(²Ž>»K�‘�þa Ø¥¸hƒuŠ;À�‚Oa~ÃÖ(ÌÅÐÜ3E=#a"¦ Þ8’Ž)¨‰Ä‚G1í<’g(fiÎ(ä ©ìEü±‘n†"f‘¶I-¤¶žhü³…ôUŸ†‡%d™¡ásȶC£w‘õ‚_ sþ‘Æ>ZÈ^ôhh{*j� ¨™Œh`4Uó1�ë-B�Kã\¨Ü¤a;P[§Qu¨nРÔ7iÌt4iÈô4iÄt5iÀô5©ýèܧæ:ônQët»Ô¸ý‹15õ–aÂt—Z¢9˜1áSC8 Sœ6•ÿ…9Å*þ(Â$ûžJl˜e�Qá¥ã~SY&º1•ôÖaæt— ˜êxÌÜ…¹¿î™ñцÉÖ)3�[0|›vaþ\—)ÿ›‡Çcª�QȰo™âÖ†”\�‰‡�´ÐåÐh ²�C>F!­p³¯wœ‡ÀÊîíÇëÍn�ANMF:������k��c��C��VP8L"��/kÀ'£ m&þeïxp\Û¶Òàî2gNTA=,ê¡'w‡xòÞ_ A‰DaÚ6Lv{ *ÿ¤$Ɉ“E''LÅD�Ç.üÜpóÞ�#/Œè™Ñò–´¢†å‹’9Jzä(ù"çÇ)?�1€”b@Ò1O„r‚�B!€�B>‡À¡Ý²mÛVÛfûÊjLaff,3³Ù Ǭîÿÿ†€#]]�[zŠèBwpû�×eOÇ{³1ˆˆCÛï¼.{:ÇïwarèÅ%C/_ A{ôU�¡W/‡`FÍרY[€ŽZ;¦¦·SÇŒp2‰ÐÙsF8™AÄÌ7FÌç8PdÄïDYh2rs«mFn.C[=¡‘7 =Î[y® çþ¤¡r ·©" ]è<¨ÐØY×éS«¹w«4xœº®Ñ ç"L}§Q¯L£ùBžRôsÏRø"‚²M ofðƒâó¸?M fÑëœÑ‚s…žuZ±‰;uA+.¸�¥%ó¸-Ò’"n²´&ƒëmZ³�ë ­©Àõi�Ÿ§EãG´èágZôé˜ymZÔâù6-jÓ¢ãO´èë-:§EIŸÖø.J´¦ˆëuZ³�ë mñs¸)Ð’M!gP4N!㢘Ãý¢˜_(”ùã•#‰‚.#ßKA½Èíñ(Ès�=DQ‡�½GQ÷�ýMQ¿‘�¡¨X;µ]RKa5mÖ¶ŸÂö¥°£Ç)ìØA ;ÐAa�õÖ˜ñ)Ê·±HQ«Èþ£¨^dïSÔd�SÔId÷ùä—"7DACÈ_§ [È×ãסÐK1½�¦˜3Y«²b!|…B®£ÈY£ˆuÅW(â*"ìy ˜·u‚N!ú�ÿ‹˜Æm¾U‡¸;4ü&bíI=n!¾Ë§Á^'’ܧÁ�(3Ic'l$kݦ¡[-Hz�†^Dòw4ò œ18î@¥vƒÆ­×@mÿ. ÛÞÕs4+8õ»4ê.t¼¤A¯ ÅúFc~–@�ÓGCú3ÐåŽÒˆ1úJ'hÀT)tVL3õé è­šfÊsÐ]5ÍTç« ¿jŠ)ÎT!�ŠI¦6U�tJG˜ÒX)Òrû˜ÊÐ^¤çüa ÿ¤i ö/6ÒµžRó+¤‡:ƒ{0á‚Omþe˜ql‹š¶NÁ”ÎujÙì�9uSÔ0_“öõQ¹¿fÙo¨øÎ†q·*øw`â©-&Þ: 3ÛW˜pµ¦V 0ÑPÌͼb‚×6Œ¾ì1Æ»Ó÷¯3rý̯bÄH5$dž ùOmi{9ïeç_¶!ANMF8������w��n��C��VP8L��/w€'F�mSìýncÛV•wwrB d¨‡ŽBw}öƒ@ÒÎ_mÛ6Ìb§GwˆgÊ$3jÌgÍ(;ö s¤›3­œùM%æM!o>äó%›/v˜tþüI%�ý¤’ŠÁ� bHæI"É…>xE¡¯ê(´þ9…¾¸M¡w/QèÕ£zäg ým….J¡Ã²,Š´3qƒ"ï!ôEnBhEŽE(¥…;SÞA�K�£IxBq¯]Eqk“ÓFaíÙˆý‘Â~G\~'Eµ þkŠúuTŸ §´Ž ×(æzœZè·¿(äg¸f¼¤ˆg©pK£áe'ì‚§ì74þM¼ ³h¸= ^ á?ÁsòE}1Þ ëhp}!Thl`Ô–ÒØePý�†n‚rÒ)y6ê™·ià�Lè(zEã^BOu3 k®�®Ï:iT×çÐ7²�õŽ�Ω�ùôδhˆ= ºçi„=úi€½~,Òw{)ü™oÑg{ üšmÑW{.ü›ÑG3àç¸núÖ3þi£OíÃà÷'�ô¥ùSø_ùŠ>¼­… Å÷¨ýa ÌȽDÍ×ó`JÚ1j=™s7QãŽDµ–ºì�0mzµôÎ�y_4RCÓ˜Xö�Ê�+`fÎ9*žÏ�©É[¨´;¯°èÙ^³GµÐcëX˜^þ€žVÀüì“ôp"¾¢›ýS„Ln£cû È©|@‡‡U�”¹ƒ±ö¶t«ýåj}èú¯5ð �ANMF������{��r��C��VP8Lþ��/{€ß1’ä¸MÔïüÕ/á Â9 È‘$¹Vzzf¿@ëpÄì!°'°C‹«Ö°oG8pÛ6’ˆ¤³÷þÿ¡sÏ6]I[8µmÛ0£SyPr†S9lj\àÇr‹#yÀO8”Ìð�}i¸ÇŽìÈ#¶å[òƒMéö‡o×iÞŸnkKþ¸àÓíeá@g¼»÷•­¤c©^ýúßseÏRÞ9♥ž¿û-ÄÍ`o÷½Çi�{ïù™Á÷Þ<íâ¶ÏüŠÀáìpëÓ®Ž&iMÛÿÄ*ßþÛ†)ÂW~¦4}ýG“ £5¤tk�è:ZÃz­U ë ˜º4#:eËP–ŽÁÄÐ^G‹iLUX&È,„@&H­YíI¨¨ @�V $�,µ Ír”Ud)%�å(T¡YF©KTþ¡bpCIRJd*UŽBµ�¨@¦ŒJòË?*`úÐ4BM£579j”Í#Âä¨y˜µ å HˆbæÐ&G J€’ (I¥" D ”‚HP Ô¿Å€¨ö@‰¶mÓ¶3߹߶m[±¿Û¶m7?¶ÍÛvòlÛ>ïÍÊýçl­R*ýOhxó�ð«ÆV}ûäi«#0Ðk§3Ÿù¡š±%_=rÒBXˆìùXËžÛÚZ~¥ŒáOì�Ñ1ç¥Pµø¦éP^­ jÚùcalصÕÔii:”í VíÍ#`¤×9eÔmÚ>¡ãŸn¡n厡¿âgš(܈�ýKhâ÷UÐôÎo¤¡g‡ `ø+4Ô|¹��oÐ\âÄÍK¢¹ƒ¡>ù7š,Ý1»—ÐäŸÓ¡:5�f›¶¡kKÍf΂ڌ šö7£c¿FšÎž •q4ß°v—jšÏš€ðþßÑFmmü:�aÞ«ô¶‡�)êtÏ®¦¨Úùêù…ýÔ'RÜ©ˆR@qÅCw#ÞŠØQuØ01—Qä•èîW@‘ÅýÐu…Ž®O)ôstŽj¦P4:Ž¥ØÐñ.ž‡H)Å–G–Sð’£)ø¸{)ø¾(ø£$ Nn¦`Ÿÿ‹5Spk"'¿OÁŸÝNÁAÁ‡Î¡à…^.ÅVFð2ž…Ž(ö t i P:ß¡Ðѵ‰B7¡«g&E÷F÷ybFUS`íHÄÞB�÷#nl-ÅÕŒCü w=çSXáMaG!°ÇÏõKÁ«Û(È_‰°ít'BgRLú�„¯§˜uPyžB^€ÒðŠÈµµ±ªwSÀ=Pîû3�ÿ¥Ô§”Òñò)ÐYÛF§Û×Aï":}!4½Wéðë Ðð�ý¾ôǦÑÑô±0±°”N–/€™]ké`ýn0µÑ§sþ&˜;’Γgѱ³aöj:uLßB‡n…q/Jgîƒ/JG†/J'M€/JH€-ï6Z¿6¯¢åk`÷ Z½¶�j£µöS`[-µö©¦•ú pcM -”ï WdÐxÖ2¸3ñþ{\ò%�~3 nõ}‘ßì ×¼kiì.ÖL#þÉps¯ ¨Ü®.L¥vúR¸;êkjþ8.÷}ŽZ¯õƒÛÞ¹mTn¿4ί« båHX˜H¥ä…�1ôc*|1RzÜÀлzBЦ*Ölƒ¬…ÿ2à¿%�6ø)Ÿ1þムpæ%ŸþõÏ'—NƒEANMFø������{��q��C��VP8Là��/{@ßç°qÛH8Ù§ÿjŸ‹ 8¸"`E’,[éî9o5€´ ‡@&б:x¬çœ™fض�#¹/ûOÛ.�€ D¢¶mft*ï�,Ox”g<È ^q/Ÿ¸â„n¸“þ,‘øÆÀ²«LÛv–e�aBܸ{ÖÃQ7îžÃ“‰…ƒ,ä‹K—÷ðfaá g?'ξŸ�«ÎŸÓ—_6§NßþHiy¤øåŸ ràè§ŸÍ�£ )©‰Õª�<±Z܆f-«6dbµ¼Ÿ¹¬ÿÍ�МË»Y ²r3¨2:M§�*» T€FHcЗ„²›6ÂËtJ¶�JCJ÷•P®6P!mÄlHˆ&£ÓP�¤!m‰)Œè@4BÕ#�4#��êŒòH¥I9”šD*Œ¨(M�T�Ät*Ž@b)*Hí)Ží`3@i Iô‰¤(N�Ä4Eƒ� Á�(„A1¤]gP`€HÌ?Cƒ5lÛéͽ3Ù®bÛIÝÆ¶êÔ¶m›©Û¬mÛ6b;Ÿ§¹ÿ,g^=ýÑÿÄÿ”·çUË~ªbIÅ·ó/k}¯óUK~¨dIõ/O]»·ó^Ÿé먰ü‰ý¡ãõŸ¶† ëg ˆÁhíK¤òW§d Xÿâ©üÛ•u`,}á:j­=#…Ô¥©µñò4ÌŒ^Ní?F!rì¿Ô^y( 4œG#³ê!´ÁBYÒº½ÖÒÐò~´Š†6„ÞY4V}&JΪ¢±êó¡á=L£÷ùÈûwÓè$ªþ$^è#ëÏ¢á9>Ôü™4>ÃË>Jãó|(ÝA �ÝL @å¤Ý”r¢¬ ˜ª¾ˆªó­¨‹ˆ©5áÃwSÖ„%~¡°¿9�â.Aiý�·µ>J.§À«QœXA�«(:š"�EÑ[ù. �«)2h‚üÙz.òoSèûÈ¥Ê(´"…l/Ší‰ì5{²Ë(öid¿¡Øoáí¤Ø]^S nÚ‰‚;õ¢àžÃ(xèX >ü` >d9€‚»·£àöu)¸ÖRìfdß§ØÏ�O±‘=žbOD¶ŶEn9…®Ž!÷$…N@~ …ŽD¾Ö:ŠÜœ@áAŠ|EmJìˆâ×(ð=”Œ À‘(‰}Aqß!dÅ„ï û¡ÝÊê‰ðŵÍvPÐÎfˆº‚‚.BdükŠùÒGô>ÕRÓ*ã(ä^(eþ¤ˆ¿2PëP@ЪwQÀ�PN|Fç?�C½å6:¾½%tÆt{ ôn£Ó·@Ó‘¿àA·î�töçºÐoµ�Žnj ÝÊèdyO˜92 ƒÁ0u¼æn¥s·Ã`l<›£þ:µÈ‡Ù=ž¡CÏÇa:ù �y) óé7èÈ›iØH¿A'ÞÉÀNú :ðN¶Ò/ÓúëØK=GËÏ&a3±˜V—ÆaןL‹s}ØöÆÑÚ#18p=-Ý7N¯¡…ÿ.€+‡•ÑxÕQpgÀ6Þ1.uXI£ëö‚[Í ÁŸ[ÀµúoÑØ‡ à^b6 -JÁÉš¸ ®SFíŠàn÷ ÔÜÒ.·øžZ¿·†Ûu_¤Æ«õáz­{¨|¿Ç•Q©üÈØw%Öî)�?`ä§M 'ñ8#¦$!êÄ2†”Ÿ i]eÉÏ]!/yÚÇUÌVtjö�ANMFÜ������w��n��C��VP8LÃ��/w€ÕЖ$I±Ee_0éÿøÒLOM×{ŠqyW¬/3³AŽ$I’‚è£*ì =•Y½Ã ¯ý"Ï�È8i϶m›³mÛ¶mÛ¶mÛ{7’Ié�åc†x X¸´JUÕJò�˜–Gå.¹¾‘sP¾XÈâ<`ÜÅòk•ÿß�÷äiXn¿÷õA¹ÒlvÀ{`P›Cåîðcð¿,ø”¦[’^{vàxÈšÓÅ\ð=—�¢§†hÎÅ;ô <å±àgv‘÷Úˆ'wcZ¥ÊdzKøOš ½næ�ãk36¸šý‚7©Žwª»\­áÏÙ/|ÓFxÎ9v )$8›ÛDÞ› ;îð¹\qun¹hŠÈx»´r^Îí‚;äå/·çvò"Ÿ¼Í×¶Š ¿ÏJïØ¥gáåî™"øhJÞB(í3Ë•�}ÁñA¾˜YDïÈ !šX›y‚ä´mûðæx0óˆ-îŒîîJ'3Ó‡8Ò¶Ûy53ç4»³Ë–|:sÝ !öÁ«ï‡3Wp‰¸]ñNÌnÎð/ñ=\ᯙ-|Á…Ò¸¼8ó½ú{æSVb}rÛ,BêYí§Y‰X‰wfø¹Î‚×åGΨfg!ò¯K;ˆï,…\ˆø•Z»óä⩳ȸø)#¸­¶Èý…“FØ,‡-âüc‘vëMÞç 8ÛšY¥;›\Yqt•m0¸ª¸àú�}4´³$¢µŸ×�aË£5'�™ ?Õ\äù_¬YÔõÃa¯:°7ÇT#•W]&7Wi=U½ÿVŒË3U‡g¥‘ª#cªîª£{¥Æª£[EqÕAqSxÕ½�CÕQV WºƒËš}g‹Îšƒ�“µŠª9f¢ýOͱqlK[“l»UFÅAÁÙ~ ÿƒcÛ–&êEÏÙ¶M»ÕÓûüÈÇÕ', ÏkVmŒ_pS>­Up¶ô‡®5:tñ÷„òF¥è­^Â4Eþ �6z™ÒU'èñ 5x©Ò¿{M#¶Ê^x (–jÄ\øa}&¢ðW…"_}An•Ya$Ë]8@ÄÚøÑëŸ÷ÍL~ð6záwÂs/fØè#áî'uŽtxÞ‘òÎÈ‘½k[æ/ƒ§qûïoöàgÔ‚_¦Ó[‘¤Q‰ÞNÔ�4:Áçb|Ä`üóŒ™?”¼>^°ùÈ9XIÒñhÁÉ g¹¾«{×�ç]ð0Rá'6‰3ñ®èÛ­ðR;wýo£~ÿÄÙØÌ‘÷1 >ˆÅù(ë‡àó©÷ðÇßDÞÇ�»>a³{/´1xÝ·ßÀìý€f×?â= Zï ¤á»ý ySx_Lþn¿6½öÎ{£˜òÑ>Ñ'Àòþx'îòå˜Þ²GÀ@‹éü`žÖcà“z²ƒp�‚Hþ£)Ô±€J ~óÎEþ ÃcÁÞÁGV¯P G×:¸Ë)ü„LÏuq˜ó˜OžG„ð ÿ¡L8<&žaJóÖ ã_‹$ozŠ�él� »ßèï7ÚËccwÿªš>e“xtLBç?�ÙχÏf‡HÕ=ѵ .�{ðêçÌȉpXœ/÷?h\Wâ£ÅÇÁJ*”ý9d†ßΟ», ‹yG¢™]ÒÒÜ Q¼à¼�ANMF¦������v��n��C��VP8L���/v€ÕЖ$I‘$™Gƒìþÿ'7TfVÆÒ“/3ó=ñ]3äF’$72�nÈÞäîteÕ ÅSzíWöl@”�€¨s¶mÛ¶mÛ¶mÛ[œmÛöªgþ 7’Ié 阱w_àKîÒ…†Ú¢V¤‰+s�È,ù6 Wpsep7îÂÛæ®Áâ^°ë˜ø ­†Ú7So‡ƒ"qða-ä(d3ÇÞtîâ›9%´(hµHfKGÑJiÊCïÚ U�ÕʬëFûÉ8ª÷ójôÁ}ðv×Û`£z|â¢êZQÓ·zDÛÇ1/' |U�dZTãâ‹Áb1wHÌêBA¥û.Vž;«ÄÍÚgíl'žj�‡D¾xúbý¯Æø ¨bÃëlù‚ÚkŒ(øuOêÒY ‚ù9ùøD!5Œ¸â¦ÕÞ¾™ˆßH:á¢dÛ¼Äq $ÿ#ËÖöGs鿆’ÿµrÒm %p~¬ÚÚ_Í/(éd)Ié´Sˆ¦;JÒG 'Ÿ…vj8ù‹¨.ÇŸˆ8®Äùòë‰6–£ªÐÔRÛ9¸ÒÀçÊâ/ÏdŒ¦|vV"QÀ¹v‰›i…íNû%ØKU‰Ã_N¶•w%þ' ­e[hó¸}7y•mfG õ§«È m³|™o2ö&ãS€�í¨‘ŒÃ£¶Å[Æ)ï6¥^)a o*:çPŒƒŽœct8j)ç‚E‹‡œûÕ‚•s?¸’º¦<Áə±xÏ9ùÃQë9G¶Õ›s?{3§äN6èçÝĬ<â7c‚øÜþ/ãÈ´íM…dDÙþJ¢æK¦Ó¥lûÏ|;ÜoSÎùv| þ‹¸Ê¹;9ÞTr¶ádã_P~Ë•üE ùÄFé¹™>õ�ô’)ù…­ Ï ‡eŠ´}æD,´Ÿ'²·p 6ÿ0K ë/:³ŒÞ¶”ùHÈ9’_YDg�cÈÏ  Cp îò ŽÐå?&ù¦Âæ-Ü�Bc³Gs+îⓟŸ�G¶âÍ3˜ úÌ)´—î@OœyŒ$÷˜ùL÷¹‹@°=kôÝ7�3CN<Ï™òÌQÎݘ >c A <�v•˜ó%3nx9Ýy†ÂaD{ÈŸm$ßÄæŠ[Ó¸ÌÊê›)ðH¬¼ÁÄ<Á4Þ¡3wþ(`–xǃ±È„o;ã…,°´W¸„áõc,üo¯r AkGÐ_¼’;ÁôºÑgïx5lù‚á5cŒ~î±òDu¬×ßlx½®PÍZѼ:œ»ÊïA…ƒ =½Âõq2 'y Ì>‚::™Æð÷$(›c“1bïi`�¡O*¯4CO„R�NÆEÎJž “h€Ž ¯rŸ+ûóA‡*¸ÿÎlÙ†™Ý×’ï)�¿LîM¦�@OêçÎ[¤ÈŸÈÒÓ¢¤Ãžð)¨xbÜ…C“íá¶"žÚ/¤èiãËÇ%žø¢%…@~N€¡+n–à︋‡à¥È"]*Gö/¤ìì‹x@ªÞ8º÷™ŒËŸ8&yz»Œî8½�£œ³aÀæ$ðšÅŠ¿q��ANMFÄ������w��n��C��VP8L¬��/w€ÕЖ$I‘]EÖìêÿ™v¶»¦Kð–â'f–Z —™/Ù¶Û6Úÿ\¹ÏÀ÷=€‚sÅ=) �X6š}¶mÛ¶mÛ¶mÛ¶mÛ¶}—Ý+ ¸‘¤HJoH»ÇŒýwáÎâ\ºa”(:sJ´ØŽˆs✄MØ#¹È!|ú% ¢"~K 8¸>ô¼x]÷ÛȱbVúÿkQ: —.6¦H݉Š˨jqòÓ\#¾Ä\²é÷¢ñ„ÒÅíl!~C},ýŽ—ŸÔRæò¨ø›-Ä}T&‹7óÚîCIŒþ4›‰³¨0ÎM˜dQqÒMûK:U“X5ëÚ~ˆ‡gqµÈ��ðQú¹¸Ÿ}nr•ʸö%”-Àì&vˆ´�Ø¡ :šÝ~ŠQÈ¡»]SG3Ãý¨DNäê]Ci—gé´ó‘¸@—ò}7“HË„Ñ8˜”Õ™ärTpOOC•3Ï[†¸mÛ'ÞEÅå̪gcš»ꟙäw¦žmïJK¼ÍLÒÈ—ÆøÇJÃ3—ø!Zö®”ÄçÌ%Æ1¾)6"˜Ù>"åý»„x�ÙäQNdËB…3ßSéaæ‹*oh>³:Ú¾‰ýZeâïö±§.¶gbÿÈeÍBHþj'†€ôWiÐ…×öÃ,EYi÷¦=‹!º‡“§«Mš?hߥf9,™3ÕToQ­¶mÕ»zlêÓ[Êm§'�TÜ·¶ù§¼_q—oØ‹ gI`d™5‡³l±XsbÉ<ÀÅw͉ŸLÖYÔ×]S¯:¢¶È½ê°[TxÕAx(¦êpÌ…ïB¡U‡"—áZuÄTªîÂXuˆ�ôçšÉŸl„ÅTÍ‘i;”Ts�a³4jÚl‚øª˜ø~pruTî·íeXUr>=6¡à>㨒z#U¶m³ë�’ð™ÄXµð¸°Tª�hù@µ¯ÑdÆ+°b­%¯‰ê¬îñ*.ñS§_).¯ Rê R} '�VIó€=6SºU«[ê¯v¸Þ ø¦‘*$ÿj™±u…!›µ×²ÖÒéF4jq5zâšEÕ:ÿ/ƒ±D¤îv¡„±ÇŒwàbhäÈ7XÏ|CœŒÛu t’ÞG톈{aãAŸÀO÷Ý�<æH˜3ü8b¤Ä)؈P÷x¡¾¬S:ücÅìhá9ÎYø¡�¶Æ ïÐ)œ‡A/ŽFŠƒ3q°Iã$®»s÷ÝQ· ^gÃüânŒÄ=›ßù˜òí}â*ä-Оµ·¹ü°uâž.ì­|~»mw¿÷v0Çõ-çtNo‰Æ$ïm9Â,ÞE£Zß*¼É¢óÖx%ßè�žc“{{�côn¢á<‚k1jòà œH��4HÍgÿ2H¶‰·�™×~ºí‘`“ăƒò7ÓÒcYù.+ñL”<š÷ò~Nøñy<¿IÓáYõ€Ù:Tßizê1ý‚£ê 'üâa�™üÑsílç‘1%:Žß%Ò›^,´†�Á£{ªm ê¸Ç¸�ÐpÈS$È5€Êëc‰'¤å*ØÌbe=²†Ø]T¯…kxÀºl}ð £8+WÃë@Žù@"Aûš7ANMFü������w��n��C��VP8Lä��/w€ÕPl$É‘$™çÜë¯òҙgÒɱmÛm›3tLÕzç�ü{.�û;G¶ÏY�$›¶Õ϶mÛ¶mÛ¶móÚ¶mÛ¶í·ßÙ§¿¸¡ÃÇñÉçâUŠR“üN%ó«ëŒ·�2 |þ8Ž�‹Gæÿäwª¥¸xM¾<Æ Ç`ý_cÖø±¤mòUj3nÆ+×4àÖ_™7y_“‹6ù2Ó&_s�•>t~Œ3%&y5CöÔ¸hv}ìgJlòjÆ?z^»�‹üo?^¬%É;YògL¸`t˜^-UÉ;¥|ÆU£°â1¶e^òn¦»·/û¾š›¼›…²¸mö�a‘\11·÷žš}'vÉ£­öîýù°²”'×”b÷ZàÉŸ}c)K®Éj]Ü™\N%¹*U½üo5¹*5“[ÀeÏ¥‰Nråä·)_¦<þL®œadIÀ5K�“kÓɳvÀ‡)Ol’kGKS®XÒÄ<¹zbå¹dç0H®žakÊÀ…É—äú‰Áôsrý¿�×�ãlò½ ¼ú“¥©$I WÏ]=2?yL)6{Og%š˜ÏcSò(Ùüöh—éÉ£J¶çí�_“ËÉÃô:ðÓìZª’‡•Z£;ðc¼’1HªæsÜKª¹*y¨®Ö.EI™ªßÝ�–>tjòH�|fZòÀ̳àsÆãä�| |qP*ÉãRÕaÀ÷ÖÉãÔø!‹’ÇÉ"àgú&Óà—kiò0]üN¯äQNoà‰NMMò T9x6ÑI¤:ÀS³oV'�ɳ/ðÜu:yŒž�^Xb Mâ €�¼rM*ÿ’Gd›c<ðzò$y„ó1pÁóöŸ<@<ÚWÜÓ‹’Ü>Î�®�w’ÛópÑ«OrsúÙDàª9°”%·Î2÷�àº}YùŸÜ85Æ àŽ^On¬×�{ãä¶jÜôÔ1Ó›j¸§ŽÀ]ퟹÉ-3_û÷ubÖ&7,u®IÀ Yš­ÉíòŸ.ÖÈ®Ô$7KÕµXÅs©Mîå¼�¬Ó{É­ô!°rÆ»äFÎ÷ÀR3¾%·áO`±%Œ“›¨Ž%�«mâ Ýäj` Àz›8ÑIn Æ6x‡Mœè$ß®†6x�M&߬¿-x—%L>$ßêü¼SŸ$ßÈWÀ{õZÑ&ßÅ;À»õDj’oIUOï—í¥5ù†¢{�Ü˲>¹<e °gdirqVø2 ØÅÇ%#¹Ts½ ìãîSÃ’ ¥ý��üì4Ã6¹L]=:{Yâø1¹H{.ÛéùÔ$¤*×�ÝKcòvmrlötM+É›Y✠ìêPÓ·œqÎÁÀ¾fÇÑ‚�lîÚ’ ÉKÙhlö7&—œäg§�'Ø{¥{ò¥ú²7p†ç’¼,Úäs~´$àîȆä“ÒÄ=ÀI>LÌ„ä/�÷ip–)»�d`ù—üÈà:ì¹¼ ANMFâ������z��p��C��VP8LÊ��/z�ÕЖ$I‘$™ÇàÿrCUfTÆ>»l-Ã33_ˆ@n#É‘t¦¯ëBÿFtEdOã´¾ùž=’� #)ƒbmÛ¶mülÛ¶mÛ¶mÛ6϶o˜@p#I‘”Þ�v�f羓á &LQåË®ËT�!dá íDœ�ƒ•£â¦ �b¼pìÞ ¼,­¨4eHÜJœ ž’ÿÄiÐCä¸îFC]n*ABØ#Ïfžz%o•á¨tÔ¡�Þ�]tk9"Ìuò]T sCºÃƒ‹2�ê–Ÿæ:ùSŒ]”í»É×è\A¾ü0[‰Ç0šbp#k$E¾š­>‰*â…'ñ“),};{ˆŸA …ðF抿³‡üTÝKºÆ:Œ‘¿f/ñ>ôYýbû2*T~™½ÄŸ0‰Èèz‘Tög¹ÀÁéE·;¯XŸ”c”í/º¿ÀÌâÃÑ .v×»3‡Ä`hçµw£êgž·gßc\È0oæ [º~ÂðM)Wg&9ÈFjÛ߆ý3“Ü≺½ÿÅöÌ%×™½‹Å™K msbof“s;' Gg6qÜxy gf>1tÌ|b¹íõFUÎ"¢ê[ºØ¼fLÿõnþ÷êLþùiõ‰”­YÈÇÜ�•EEÌR1ËQ ¿×šüN+¾Äs¤v)äØj“8ºà¢—ÏrHÕy/ůz“¿™tg ¢fA$îlò¬âäÅi׫Ø,‰ˆŸ,H­9L?™<¨9qdÛ4ªW5÷ŠƒÊö%F³(4¶=£ê0ó09Xu8d[œU�<µ¹!ŸVÝS.„™L³¬'fÔÝ#S2uÇ�öå®Qw n¦NÝQºFź#Jæ©»ïM8êŽð˜O‰¯ÚýÝ–Ï«î+Ûb¾êpÍvXYuXcû¢;Wq±ýEÕýdÛâEÍÄ{.ÄqAcÍa“mû‡šC““qâsÅä÷“CœvXS°…ƒ /*Ž(ùŒ\¯îùXÕ±\R\VKÜÑP^�¶ÕF¼äKyR+<[¹“õk�ÃÈ+äD¥pb-³ È¿uŸ­ÎAJ�‘ÄõÌ,n«„M÷)MA¨‘Ä?w“ ¶ÆÞkËT%þLúˆ¢lœ‰�$ŒŸ 0 Ý,(¤¬=ïÃÿÇÓ½cþIþ»ÿAÈ]VC÷„²q§ `äaao~ fÆ�ÌÑPÝ3;Ͱ?Èñæ#'x&>�™üÄ&à 5ùoÄÄ_žÔ�„XÞ/�Gk§ÁÀñ†!NdŒÉÌÌ< ;ºBª�‹ ´�é|�p:(GG Ç8o€‚”±1bL¾kW½�éÍΩ|÷×í#S»7ó»Ú:2Â?è q"�ÛFzޝhC4Ô§[ÆhþÒãBDn)ÿ}ëlCâVAª‡€¾ïmqí>†x`%þç'0Lõå÷ìäO#ä…x››üÀTðP€[\g†÷<ñ{0LºÄS[q›bðp((èÌŠ1ÄFêýΑ‘pCzLÄ]bú¯ zyXL�îÓÏåWb0n6]PÞôEž(Q�7±ÐY=¾Ê¡qg^bÍk��x?o|ù _—€{K;Ñt„£áv<¦s¹ žàHÓZ¤‹�¹â¿ø"žcˆ‹a¨-ÈÏyTs9,$öä8“¼aDoødANMF ������w��n��C��VP8L��/w€ÕHlI’$ªfç¿ÇûÝLwM¥rI’$)D?yv÷ÞÙª°¬žÅpG{òtH€$É´­~Æ·mÛ¶mÛ¶mÛ¶mÛ¶Íg|<\ß»•¢Þ|>ÿ”{<ú­½"—š·ÍïæãJ\ ©ïꕵW>Ú×®èå+Ú`|ì*Ë€µ×4×ò>¡5>îWCê»\^]ñXý(ïÍG´ßNþ˜«›Øðªù·~èå•Vt‹Lk¬§š„ðªþ]=üؽ])D[?åW·&1\‹mu�SEtÕíõ±ëäHã תeÙa*‹¶}<*åZ¸“§v}Ñ·×cµÈÛp'·¨&ÚòïgžœwsÙUJôòsWlî„»õ‚Ýö泌ˆ%Ü�k™çÍ_ôÔ+p­eñ„û±®5Λ�螯,Í�°§yá*&zòù»TÞ„=õ‘•CtçãQ)áaW,v[Ñ�ݶ±†]‰2ÕE×íVa_<ËÑŸÕq1a_œž}DW«_LغºN¼D_n¯µW„­1®¡¢k«ƒbÂæµ–‹¾Öž6Ç0RtåÑv1a;³—Ña{Œé"zý¹ÊÆFÄæYIôŠL Cig=w{å|“+n/ÑÓÕAa�k˜è™?¹’Åê+�èÉr(ŒjމþÿX•Ã0Ïj¢ÿr? Ë#Ñß�U=Œ£–èON†qõŒè—¼ñ„qñXùE?kÏÍ\ÑO>†�ù,úþ\%ÃHW)Ñ×êÌ0Ò™%úʵ02×EÞü«%ŒŒÅ?¿ÏÏ a¨«âcõ C�¾k/ C�…9†š£Íó0´>Ï·04߆&*–04–¸Ãи†Öø&4 ­ù†Ö¯Í�0ÔÜ^{Gjv­5) 53Ú„¡¦ƒ•# õ•C”ad�}­î #ÍaÑ×£ÝÂHº‰¾¼RÆÆå™Fô�3a WE?�Õ9 tuýØMT—Þ‚D¿kÏ ãœ¥¢?&[aX^YEW7…aÎÑš3Î0*ÏÜ¢ÿWׇQl=1é%ÎÊ(z¶ö„0ˆñ¢§v@>†1æ£ÿþ¢çZ'L‰Ñš¢W«{³MôÒNWcˆD‘ZôÚt #ì.¢+9pFtÉïÌùŽÏ'³èšiNoŒi+ººöæp¸n]ön^‡£Í+ƒD×­üùNœ•_t‡1áØxh!º·fj8ÖÌÝt{-‡Â¡r{‰îú”áHy Ý7éó=h¾ù�A´C Ô˜p\bµ€h�U!‰á°$j%Ñ.Ó(ŽpTœ¦‘hí«'·ÓI´Óéމ1ýE{ͰpJ #E»u\8ÄŒíg|8™,zãÃÎ4Ñ{ÞîL½Ë5²1á­1ÎÑût@<á�ñè`Ñ;=»ÄÞ·«—è½´ˆ=¼)vÓVôn§NÂ[’¨ Dï×r5&¼¡þõYYt‚ȯ°=!>‹ŠÎ°³æuØlÞ{d�╲¹¶rß�4¢s쀵…�œð$:É7ïÕÅakÜÞ¢ÃWØ7cDçiãć I4-E'Ú¥n'Ì”�édî<7Í ;«èT�àåp¸Å¯¤¢sÝ^ÎìÆ„Ë1,r{‹Ž6c c¥³ètS&¿Ã¥b•�ï™¡Þ œ{VFÑoþkÖ…—f«ÿþ¢!®^±…§±›A¢9Z.¿Ã“âª(šdÒ×Sá?NÚéDÃ\U�íÍçÆ^ùb¶9UDo�������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/deepin/������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0016757�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/deepin/cs_rect_64.svg����������������������������������������������������0000664�0000000�0000000�00000000745�15226154130�0021441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ���������������������������dtkgui-6.7.46/tests/images/deepin/index.theme�������������������������������������������������������0000664�0000000�0000000�00000000303�15226154130�0021106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Icon Theme] Name=deepin Inherits= Papirus Example=x-directory-normal FollowsColorScheme=true Directories=actions/64 [actions/64] Size=64 Context=Actions Type=Scalable MinSize=32 MaxSize=128 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/images/logo_icon.png������������������������������������������������������������0000664�0000000�0000000�00000001503�15226154130�0020170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������‰PNG  ��� IHDR��� ��� ���szzô��� pHYs��Ä��Ä•+��õIDATX…Å—ËKTQÇ?g¸8ã#qD ’i#eQS‘`Of㤴iÓ®”2ZM¹ê/hJè¬E !ÂÔ0CÍ‚ì�¡= È)£š¦LÇœÇõ´¸ê½sç¥3>¾ðƒßœß÷ü~ßù�{νG`Æoéê€*ÀäÇq–‡ àº�VìbÄ‹ž_Z�& >f|e!�ÀK‰é¾K+Ð ¸W©°�€j6‰��•&Tܨ°FæF¥@à“Nà5«×öd�À…(uëPœùšµ *U1²Ê³#üsð1=3Ð6 Ÿ"Y‹ðÞÉi [Mn[Ṵ́„kಢ2cAÁ¨Œ™.w,/CWŽû´e…hò ñÈ(´@±8¶J Ïž|¸R—¾e&@ðÒÔ�½†à«ä+ò`p+X…¶ec0^¾�KÜ5"Å^ž‚V¿FSœ.JÍOf @…û�ê*ÈL€WÔ, |³º_nKÏO„”aÊà›Ñýb%=?²Z™†ßçLŸ#«%pØt?‰ç»ŠâÇÌȪŽ�ú>¨�õí‹Í%Òî‚(Ęæ˜É logo icon ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/main.cpp������������������������������������������������������������������������0000664�0000000�0000000�00000002504�15226154130�0015677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include #include #include #ifdef QT_DEBUG #include #endif #include #include DGUI_USE_NAMESPACE int main(int argc, char *argv[]) { // gerrit编译时没有显示器,需è¦�指定环境å�˜é‡� if (!qEnvironmentVariableIsSet("DISPLAY")) qputenv("QT_QPA_PLATFORM", "offscreen"); qputenv("QT_QPA_PLATFORM", "minimal"); QString paths(QFileInfo(QString::fromUtf8(argv[0])).path() + "/plugins"); qputenv("QT_QPA_PLATFORM_PLUGIN_PATH", paths.toLocal8Bit().data()); // for ut_dicon.cpp 测试指定缩放时 dicon çš„ ut // 如果需è¦�删除,请一起删除 ut_dicon.cpp 中 ASSERT_FLOAT_EQ(devicePixelRatio, 1.25); qputenv("D_DXCB_DISABLE_OVERRIDE_HIDPI","1"); qputenv("QT_SCALE_FACTOR","1.25"); // Testing `setPaletteType` called before QApplication constructed. DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::LightType); QApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); #ifdef QT_DEBUG __sanitizer_set_report_path("asan.log"); #endif return ret; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/�����������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0020343�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/CMakeLists.txt���������������������������������������������0000664�0000000�0000000�00000002107�15226154130�0023103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui) if("${QT_VERSION_MAJOR}" STRLESS "6") find_package(Qt${QT_VERSION_MAJOR} REQUIRED EventDispatcherSupport ServiceSupport) endif() find_package(Dtk${DTK_NAME_SUFFIX}Core REQUIRED) file(GLOB plugin_SRC minimal.json *.h *.cpp ) add_library(${test-plugin} SHARED ${plugin_SRC}) target_link_libraries(${test-plugin} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::CorePrivate Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::GuiPrivate Dtk${DTK_NAME_SUFFIX}::Core) if("${QT_VERSION_MAJOR}" STRLESS "6") target_link_libraries(${test-plugin} PRIVATE Qt${QT_VERSION_MAJOR}::EventDispatcherSupportPrivate Qt${QT_VERSION_MAJOR}::ServiceSupportPrivate) endif() target_include_directories(${test-plugin} PUBLIC ${PROJECT_SOURCE_DIR}/include/global ${PROJECT_SOURCE_DIR}/include/kernel ${PROJECT_SOURCE_DIR}/include/filedrag ) set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/../plugins/platforms) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/ddynamicmetaobject.cpp�������������������������������������0000664�0000000�0000000�00000037512�15226154130�0024705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2017 - 2022 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "ddynamicmetaobject.h" #include "dplatformsettings.h" #include #include #include #define VALID_PROPERTIES "validProperties" #define ALL_KEYS "allKeys" DGUI_BEGIN_NAMESPACE QHash DDynamicMetaObject::mapped; /* * å°† base 对象的 metaobject 替æ�¢æˆ� this,会跟éš� base 对象一起销æ¯�。 * 通过覆盖 QObject çš„ qt_metacall 虚函数,检测 base object 中自定义的属性列表 * å°† settings 对应的 setting/setSetting å’Œ object 对象中的属性绑定到一起使用 * å°† base 对象通过 property/setProperty 调用对属性的读写æ“�作转为对 setting çš„ setting/setSetting 调用 */ DDynamicMetaObject::DDynamicMetaObject(QObject *base, DPlatformSettings *settings, bool global_settings) : m_base(base) , m_settings(settings) , m_isGlobalSettings(global_settings) { if (mapped.value(base)) { qCritical() << "DDynamicMetaObject: Native settings are already initialized for object:" << base; std::abort(); } mapped[base] = this; const QMetaObject *meta_object; if (qintptr ptr = qvariant_cast(m_base->property("_d_metaObject"))) { meta_object = reinterpret_cast(ptr); } else { meta_object = m_base->metaObject(); } if (m_settings->initialized()) { init(meta_object); } } DDynamicMetaObject::~DDynamicMetaObject() { if (!m_isGlobalSettings) { delete m_settings; } else if (m_settings->initialized()) { // 移除注册的callback m_settings->removeCallbackForHandle(this); m_settings->removeSignalCallback(this); } mapped.remove(m_base); if (m_metaObject) { free(m_metaObject); } } bool DDynamicMetaObject::isValid() const { return m_settings->initialized(); } void DDynamicMetaObject::init(const QMetaObject *metaObject) { m_objectBuilder.addMetaObject(metaObject); m_firstProperty = metaObject->propertyOffset(); m_propertyCount = m_objectBuilder.propertyCount(); // 用于记录属性是å�¦æœ‰æ•ˆçš„属性, 属性类型为64ä½�整数,最多å�¯ç”¨äºŽè®°å½•64个属性的状æ€� m_flagPropertyIndex = metaObject->indexOfProperty(VALID_PROPERTIES); qint64 validProperties = 0; // 用于记录所有属性的key m_allKeysPropertyIndex = metaObject->indexOfProperty(ALL_KEYS); int allKeyPropertyType = 0; QMetaObjectBuilder &ob = m_objectBuilder; #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) ob.setFlags(ob.flags() | DynamicMetaObject); #else ob.setFlags(ob.flags() | QMetaObjectBuilder::DynamicMetaObject); #endif // 先删除所有的属性,等待é‡�æž„ while (ob.propertyCount() > 0) { ob.removeProperty(0); } QVector propertySignalIndex; propertySignalIndex.reserve(m_propertyCount); // QMetaObjectBuilder对象中的属性ã€�ä¿¡å�·ã€�方法å�‡ä»Ž0开始,但是m_base对象的QMetaObject则包å�«offset // 因此往QMetaObjectBuilder对象中添加属性时è¦�将其对应的信å�·çš„indexå‡�去å��ç§»é‡� int signal_offset = metaObject->methodOffset(); for (int i = 0; i < m_propertyCount; ++i) { int index = i + m_firstProperty; const QMetaProperty &mp = metaObject->property(index); if (mp.hasNotifySignal()) { propertySignalIndex << mp.notifySignalIndex(); } // 跳过特殊属性 if (index == m_flagPropertyIndex) { ob.addProperty(mp); continue; } if (index == m_allKeysPropertyIndex) { ob.addProperty(mp); allKeyPropertyType = mp.userType(); continue; } if (m_settings->setting(mp.name()).isValid()) { validProperties |= (1 << i); } QMetaPropertyBuilder op; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) switch (mp.metaType().id()) { case QMetaType::QByteArray: case QMetaType::QString: case QMetaType::QColor: case QMetaType::Int: case QMetaType::Double: case QMetaType::Bool: #else switch (mp.type()) { case QVariant::Type::ByteArray: case QVariant::Type::String: case QVariant::Type::Color: case QVariant::Type::Int: case QVariant::Type::Double: case QVariant::Type::Bool: #endif op = ob.addProperty(mp); break; default: // é‡�设属性的类型,å�ªæ”¯æŒ�Int double color string bytearray op = ob.addProperty(mp.name(), "QByteArray", mp.notifySignalIndex()); break; } if (op.isWritable()) { // 声明支æŒ�属性reset op.setResettable(true); } // é‡�置属性对应的信å�· if (op.hasNotifySignal()) { op.setNotifySignal(ob.method(op.notifySignal().index() - signal_offset)); } } { // 通过class info确定是å�¦åº”该关è�”对象的信å�· int index = metaObject->indexOfClassInfo("SignalType"); if (index >= 0) { const QByteArray signals_value(metaObject->classInfo(index).value()); // 如果base对象声明为信å�·çš„生产者,则应该将其产生的信å�·è½¬å�‘到native settings if (signals_value == "producer") { // 创建一个槽用于接收所有信å�· m_relaySlotIndex = ob.addMethod("relaySlot(QByteArray,qint32,qint32)").index() + metaObject->methodOffset(); } } } // 将属性状æ€�设置给对象 m_base->setProperty(VALID_PROPERTIES, validProperties); // 将所有属性å��称设置给对象 if (allKeyPropertyType == qMetaTypeId>()) { QSet set(m_settings->settingKeys().begin(), m_settings->settingKeys().end()); m_base->setProperty(ALL_KEYS, QVariant::fromValue(set)); } else { m_base->setProperty(ALL_KEYS, QVariant::fromValue(m_settings->settingKeys())); } m_propertySignalIndex = metaObject->indexOfMethod(QMetaObject::normalizedSignature("propertyChanged(const QByteArray&, const QVariant&)")); // 监å�¬native settingå�˜åŒ– m_settings->registerCallback(reinterpret_cast(onPropertyChanged), this); // 监å�¬ä¿¡å�·. 如果base对象声明了è¦�转å�‘å…¶ä¿¡å�·ï¼Œåˆ™æ­¤å¯¹è±¡ä¸�应该关心æ�¥è‡ªäºŽnative settings的信å�· // å�³ä¿¡å�·çš„生产者和消费者å�ªèƒ½é€‰å…¶ä¸€ if (!isRelaySignal()) { m_settings->registerSignalCallback(reinterpret_cast(onSignal), this); } // 支æŒ�在base对象中直接使用property/setProperty读写native属性 QObjectPrivate *op = QObjectPrivate::get(m_base); op->metaObject = this; m_metaObject = ob.toMetaObject(); *static_cast(this) = *m_metaObject; if (isRelaySignal()) { // 把 static_metacall 置为nullptr,迫使对base对象调用QMetaObject::invodeMethod时使用DDynamicMetaObject::metaCall d.static_metacall = nullptr; // 链接 base 对象的所有信å�· int first_method = methodOffset(); int method_count = methodCount(); for (int i = 0; i < method_count; ++i) { int index = i + first_method; // 排除属性对应的信å�· if (propertySignalIndex.contains(index)) { continue; } QMetaMethod method = this->method(index); if (method.methodType() != QMetaMethod::Signal) { continue; } QMetaObject::connect(m_base, index, m_base, m_relaySlotIndex, Qt::DirectConnection); } } } QByteArray DDynamicMetaObject::getSettingsProperty(QObject *base) { const QMetaObject *meta_object; if (qintptr ptr = qvariant_cast(base->property("_d_metaObject"))) { meta_object = reinterpret_cast(ptr); } else { meta_object = base->metaObject(); } QByteArray settings_property; { // 获å�–base对象是å�¦æŒ‡å®šäº†native settings的域 // 默认情况下,native settings的值ä¿�存在窗å�£çš„_XSETTINGS_SETTINGS属性上 // 指定域å�Žï¼Œä¼šå°†native settings的值ä¿�存到指定的窗å�£å±žæ€§ã€‚ // 将域的值转æ�¢æˆ�窗å�£å±žæ€§æ—¶ï¼Œä¼šæŠŠ "/" 替æ�¢ä¸º "_",如域:"/xxx/xxx" 转æˆ�窗å�£å±žæ€§ä¸ºï¼š"_xxx_xxx" // 且所有字æ¯�转æ�¢ä¸ºå¤§å†™ settings_property = base->property("_d_domain").toByteArray(); if (settings_property.isEmpty()) { int index = meta_object->indexOfClassInfo("Domain"); if (index >= 0) { settings_property = QByteArray(meta_object->classInfo(index).value()); } } if (!settings_property.isEmpty()) { settings_property = settings_property.toUpper(); settings_property.replace('/', '_'); } } return settings_property; } int DDynamicMetaObject::createProperty(const char *name, const char *) { // ä¸�处ç�†ç©ºå­—符串 if (strlen(name) == 0) { return -1; } // ä¸�创建特殊属性(以'_'开头的属性认为是ç§�有的,ä¸�自动关è�”到native Settings) if (QByteArrayLiteral(VALID_PROPERTIES) == name || QByteArrayLiteral(ALL_KEYS) == name || name[0] == '_') { return -1; } // 清ç�†æ—§æ•°æ�® free(m_metaObject); // 添加新属性 auto property = m_objectBuilder.addProperty(name, "QVariant"); property.setReadable(true); property.setWritable(true); property.setResettable(true); m_metaObject = m_objectBuilder.toMetaObject(); *static_cast(this) = *m_metaObject; return m_firstProperty + property.index(); } void DDynamicMetaObject::onPropertyChanged(const QByteArray &name, const QVariant &property, DDynamicMetaObject *handle) { if (handle->m_propertySignalIndex >= 0) { handle->method(handle->m_propertySignalIndex).invoke(handle->m_base, Q_ARG(QByteArray, name), Q_ARG(QVariant, property)); } // é‡�设对象的 ALL_KEYS 属性 { const QVariant &old_property = handle->m_base->property(ALL_KEYS); if (old_property.canConvert>()) { QSet keys = qvariant_cast>(old_property); int old_count = keys.count(); if (property.isValid()) { keys << name; } else if (keys.contains(name)) { keys.remove(name); } // æ•°é‡�æ— å�˜åŒ–时说明值无å�˜åŒ– if (old_count != keys.count()) { handle->m_base->setProperty(ALL_KEYS, QVariant::fromValue(keys)); } } else { bool changed = false; QByteArrayList keys = qvariant_cast(old_property); if (property.isValid()) { if (!keys.contains(name)) { keys << name; changed = true; } } else if (keys.contains(name)) { keys.removeOne(name); changed = true; } if (changed) { handle->m_base->setProperty(ALL_KEYS, QVariant::fromValue(keys)); } } } // ä¸�è¦�直接调用自己的indexOfProperty函数,属性ä¸�存在时会导致调用createProperty函数 int property_index = handle->m_objectBuilder.indexOfProperty(name.constData()); if (Q_UNLIKELY(property_index < 0)) { return; } { bool ok = false; qint64 flags = handle->m_base->property(VALID_PROPERTIES).toLongLong(&ok); // 更新有效属性的标志ä½� if (ok) { qint64 flag = (1 << property_index); flags = property.isValid() ? flags | flag : flags & ~flag; handle->m_base->setProperty(VALID_PROPERTIES, flags); } } const QMetaProperty &p = handle->property(handle->m_firstProperty + property_index); if (p.hasNotifySignal()) { // 通知属性改å�˜ p.notifySignal().invoke(handle->m_base); } } // 处ç�†native settingså�‘过æ�¥çš„ä¿¡å�· void DDynamicMetaObject::onSignal(const QByteArray &signal, qint32 data1, qint32 data2, DDynamicMetaObject *handle) { // æ ¹æ�®ä¸�å�Œçš„å�‚数寻找对应的信å�· static QByteArrayList signal_suffixs { QByteArrayLiteral("()"), QByteArrayLiteral("(qint32)"), QByteArrayLiteral("(qint32,qint32)") }; int signal_index = -1; for (const QByteArray &suffix : signal_suffixs) { signal_index = handle->indexOfMethod(signal + suffix); if (signal_index >= 0) break; } QMetaMethod signal_method = handle->method(signal_index); // 调用base对象对应的信å�· signal_method.invoke(handle->m_base, Qt::DirectConnection, Q_ARG(qint32, data1), Q_ARG(qint32, data2)); } int DDynamicMetaObject::metaCall(QMetaObject::Call _c, int _id, void ** _a) { enum CallFlag { ReadProperty = 1 << QMetaObject::ReadProperty, WriteProperty = 1 << QMetaObject::WriteProperty, ResetProperty = 1 << QMetaObject::ResetProperty, AllCall = ReadProperty | WriteProperty | ResetProperty }; if (AllCall & (1 << _c)) { const QMetaProperty &p = property(_id); const int index = p.propertyIndex(); // 对于本地属性,此处应该从m_settings中读写 if (Q_LIKELY(index != m_flagPropertyIndex && index != m_allKeysPropertyIndex && index >= m_firstProperty)) { switch (_c) { case QMetaObject::ReadProperty: *reinterpret_cast(_a[1]) = m_settings->setting(p.name()); _a[0] = reinterpret_cast(_a[1])->data(); break; case QMetaObject::WriteProperty: m_settings->setSetting(p.name(), *reinterpret_cast(_a[1])); break; case QMetaObject::ResetProperty: m_settings->setSetting(p.name(), QVariant()); break; default: break; } return -1; } } do { if (!isRelaySignal()) break; if (Q_LIKELY(_c != QMetaObject::InvokeMetaMethod || _id != m_relaySlotIndex)) { break; } int signal = m_base->senderSignalIndex(); QByteArray signal_name; qint32 data1 = 0, data2 = 0; // ä¸�是通过信å�·è§¦å�‘的槽调用,å�¯èƒ½æ˜¯ä½¿ç”¨QMetaObject::invoke if (signal < 0) { signal_name = *reinterpret_cast(_a[1]); data1 = *reinterpret_cast(_a[2]); data2 = *reinterpret_cast(_a[3]); } else { const auto &signal_method = method(signal); signal_name = signal_method.name(); // 0为return type, å› æ­¤å�‚数值下标从1开始 if (signal_method.parameterCount() > 0) { #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) QVariant arg(signal_method.parameterMetaType(0), _a[1]); #else QVariant arg(signal_method.parameterType(0), _a[1]); #endif // 获å�–å�‚æ•°1,获å�–å�‚æ•°2 data1 = arg.toInt(); } if (signal_method.parameterCount() > 1) { #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) QVariant arg(signal_method.parameterMetaType(1), _a[2]); #else QVariant arg(signal_method.parameterType(1), _a[2]); #endif data2 = arg.toInt(); } } m_settings->emitSignal(signal_name, data1, data2); return -1; } while (false); return m_base->qt_metacall(_c, _id, _a); } bool DDynamicMetaObject::isRelaySignal() const { return m_relaySlotIndex > 0; } DGUI_END_NAMESPACE ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/ddynamicmetaobject.h���������������������������������������0000664�0000000�0000000�00000003527�15226154130�0024351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2017 - 2022 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DDYNAMICMETAOBJECT_H #define DDYNAMICMETAOBJECT_H #include "dtkgui_global.h" #define protected public #include #undef protected #include #include DGUI_BEGIN_NAMESPACE class DPlatformSettings; class Q_DECL_HIDDEN DDynamicMetaObject : public QAbstractDynamicMetaObject { public: explicit DDynamicMetaObject(QObject *base, DPlatformSettings *settings, bool global_settings); ~DDynamicMetaObject() override; static QByteArray getSettingsProperty(QObject *base); bool isValid() const; private: void init(const QMetaObject *meta_object); int createProperty(const char *, const char *) override; int metaCall(QMetaObject::Call, int _id, void **) override; bool isRelaySignal() const; static void onPropertyChanged(const QByteArray &name, const QVariant &property, DDynamicMetaObject *handle); static void onSignal(const QByteArray &signal, qint32 data1, qint32 data2, DDynamicMetaObject *handle); QObject *m_base; QMetaObject *m_metaObject = nullptr; QMetaObjectBuilder m_objectBuilder; int m_firstProperty; int m_propertyCount; // propertyChangedä¿¡å�·çš„index int m_propertySignalIndex; // VALID_PROPERTIES属性的index int m_flagPropertyIndex; // ALL_KEYS属性的index int m_allKeysPropertyIndex; // 用于转å�‘base对象产生的信å�·çš„æ§½ï¼Œä½¿ç”¨native settings的接å�£å°†å…¶å�‘é€�出去. 值为0时表示ä¸�转å�‘base对象的所有信å�· int m_relaySlotIndex = 0; DPlatformSettings *m_settings = nullptr; bool m_isGlobalSettings = false; static QHash mapped; }; DGUI_END_NAMESPACE #endif // DDYNAMICMETAOBJECT_H �������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/dplatformnativeinterface.cpp�������������������������������0000664�0000000�0000000�00000002760�15226154130�0026134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dtkgui_global.h" #include "dplatformnativeinterface.h" #include "dummysettings.h" #include "ddynamicmetaobject.h" #include #include #include DGUI_USE_NAMESPACE static bool buildNativeSettings(QObject *object, quint32 /*settingWindow*/) { if (!qApp) return false; static QPair kvs[] = { {"Net/ThemeName", "deepin"}, {"Qt/ActiveColor", QColor(Qt::red)}, {"Net/IconThemeName", "bloom"}, {"DTK/WindowRadius", 18} }; QString domain = object->property("_d_domain").toByteArray(); domain.replace("/", "_"); auto settings = new DummySettings(domain); for (auto pair : kvs) { settings->setSetting(pair.first, pair.second); } // set object.metaobject to this, destroyed with object destroyed... DDynamicMetaObject *mj = new DDynamicMetaObject(object, settings, false); if (!mj->isValid()) { delete mj; return false; } return true; } DPlatformNativeInterface::DPlatformNativeInterface() :QPlatformNativeInterface() { } QFunctionPointer DPlatformNativeInterface::platformFunction(const QByteArray &function) const { if (!function.compare("_d_buildNativeSettings")) return reinterpret_cast(buildNativeSettings); return QPlatformNativeInterface::platformFunction(function); } ����������������dtkgui-6.7.46/tests/platform-plugin-test/dplatformnativeinterface.h���������������������������������0000664�0000000�0000000�00000000744�15226154130�0025601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMNATIVEINTERFACE_H #define DPLATFORMNATIVEINTERFACE_H #include #include class DPlatformNativeInterface : public QPlatformNativeInterface { public: DPlatformNativeInterface(); virtual QFunctionPointer platformFunction(const QByteArray &function) const; }; #endif // DPLATFORMNATIVEINTERFACE_H ����������������������������dtkgui-6.7.46/tests/platform-plugin-test/dplatformsettings.cpp��������������������������������������0000664�0000000�0000000�00000003031�15226154130�0024615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dplatformsettings.h" DGUI_BEGIN_NAMESPACE void DPlatformSettings::registerCallback(DPlatformSettings::PropertyChangeFunc func, void *handle) { Callback callback = { func, handle }; callback_links.push_back(callback); } void DPlatformSettings::removeCallbackForHandle(void *handle) { auto isCallbackForHandle = [handle](const Callback &cb) { return cb.handle == handle; }; callback_links.erase(std::remove_if(callback_links.begin(), callback_links.end(), isCallbackForHandle)); } void DPlatformSettings::registerSignalCallback(DPlatformSettings::SignalFunc func, void *handle) { SignalCallback callback = { func, handle }; signal_callback_links.push_back(callback); } void DPlatformSettings::removeSignalCallback(void *handle) { auto isCallbackForHandle = [handle](const SignalCallback &cb) { return cb.handle == handle; }; signal_callback_links.erase(std::remove_if(signal_callback_links.begin(), signal_callback_links.end(), isCallbackForHandle)); } void DPlatformSettings::handlePropertyChanged(const QByteArray &property, const QVariant &value) { for (auto callback : callback_links) { callback.func(property, value, callback.handle); } } void DPlatformSettings::handleNotify(const QByteArray &signal, qint32 data1, qint32 data2) { for (auto callback : signal_callback_links) { callback.func(signal, data1, data2, callback.handle); } } DGUI_END_NAMESPACE �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/dplatformsettings.h����������������������������������������0000664�0000000�0000000�00000003420�15226154130�0024264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DPLATFORMSETTINGS_H #define DPLATFORMSETTINGS_H #include "dtkgui_global.h" #include QT_BEGIN_NAMESPACE class QByteArray; QT_END_NAMESPACE DGUI_BEGIN_NAMESPACE class Q_DECL_HIDDEN DPlatformSettings { public: virtual ~DPlatformSettings() {} virtual bool initialized() const { return true; } virtual bool isEmpty() const { return false; } virtual bool contains(const QByteArray &property) const = 0; virtual QVariant setting(const QByteArray &property) const = 0; virtual void setSetting(const QByteArray &property, const QVariant &value) = 0; virtual QByteArrayList settingKeys() const = 0; virtual void emitSignal(const QByteArray &signal, qint32 data1, qint32 data2) = 0; typedef void (*PropertyChangeFunc)(const QByteArray &name, const QVariant &property, void *handle); void registerCallback(PropertyChangeFunc func, void *handle); void removeCallbackForHandle(void *handle); typedef void (*SignalFunc)(const QByteArray &signal, qint32 data1, qint32 data2, void *handle); void registerSignalCallback(SignalFunc func, void *handle); void removeSignalCallback(void *handle); protected: void handlePropertyChanged(const QByteArray &property, const QVariant &value); void handleNotify(const QByteArray &signal, qint32 data1, qint32 data2); struct Q_DECL_HIDDEN Callback { PropertyChangeFunc func; void *handle; }; struct Q_DECL_HIDDEN SignalCallback { SignalFunc func; void *handle; }; std::vector callback_links; std::vector signal_callback_links; }; DGUI_END_NAMESPACE #endif // DPLATFORMSETTINGS_H ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/dummysettings.cpp������������������������������������������0000664�0000000�0000000�00000003720�15226154130�0023765�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dummysettings.h" #include class Q_DECL_HIDDEN DummySettingsPrivate : public QObject { public: DummySettingsPrivate(DummySettings *q, const QString &domain, QObject *parent = nullptr); ~DummySettingsPrivate(); protected: QString domain; QByteArrayList keys; DummySettings *q_ptr = nullptr; bool initialized = true; Q_DECLARE_PUBLIC(DummySettings) }; DummySettingsPrivate::DummySettingsPrivate(DummySettings *q, const QString &domain, QObject *parent) : QObject(parent) , domain(domain) , q_ptr(q) { } DummySettingsPrivate::~DummySettingsPrivate() { } DummySettings::DummySettings(const QString &domain) :d_ptr(new DummySettingsPrivate(this, domain)) { } DummySettings::~DummySettings() { } bool DummySettings::initialized() const { Q_D(const DummySettings); return d->initialized; } bool DummySettings::isEmpty() const { Q_D(const DummySettings); return d->keys.isEmpty(); } bool DummySettings::contains(const QByteArray &property) const { Q_D(const DummySettings); return d->property(property.data()).isValid(); } QVariant DummySettings::setting(const QByteArray &property) const { Q_D(const DummySettings); return d->property(property.data()); } void DummySettings::setSetting(const QByteArray &property, const QVariant &value) { if (setting(property) == value) return; Q_D(DummySettings); if (!d->keys.contains(property)) d->keys << property; d->setProperty(property.data(), value); // call baseobject's propertychanged handlePropertyChanged(property, value); } QByteArrayList DummySettings::settingKeys() const { Q_D(const DummySettings); return d->keys; } void DummySettings::emitSignal(const QByteArray &signal, qint32 data1, qint32 data2) { qInfo() << "emitSignal[" << signal << "] "<< data1 << data2; } ������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/dummysettings.h��������������������������������������������0000664�0000000�0000000�00000001710�15226154130�0023427�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DUMMYSETTINGS_H #define DUMMYSETTINGS_H #include #include "dplatformsettings.h" DGUI_USE_NAMESPACE class DummySettingsPrivate; class Q_DECL_HIDDEN DummySettings : public DPlatformSettings { public: explicit DummySettings(const QString &domain = QString()); virtual ~DummySettings(); virtual bool initialized() const; virtual bool isEmpty() const; virtual bool contains(const QByteArray &property) const; virtual QVariant setting(const QByteArray &property) const; virtual void setSetting(const QByteArray &property, const QVariant &value); virtual QByteArrayList settingKeys() const; virtual void emitSignal(const QByteArray &signal, qint32 data1, qint32 data2); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(DummySettings) }; #endif // DUMMYSETTINGS_H ��������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/main.cpp���������������������������������������������������0000664�0000000�0000000�00000001321�15226154130�0021770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include "qminimalintegration.h" class MinimalIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimal.json") public: QPlatformIntegration *create(const QString&, const QStringList&) override; }; QPlatformIntegration *MinimalIntegrationPlugin::create(const QString& system, const QStringList& paramList) { if (!system.compare("minimal", Qt::CaseInsensitive)) return new MinimalIntegration(paramList); return nullptr; } #include "main.moc" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/minimal.json�����������������������������������������������0000664�0000000�0000000�00000000036�15226154130�0022663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "Keys": [ "minimal" ] } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/qminimalbackingstore.cpp�����������������������������������0000664�0000000�0000000�00000001505�15226154130�0025253�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "qminimalbackingstore.h" #include "qminimalintegration.h" #include "qscreen.h" #include #include #include MinimalBackingStore::MinimalBackingStore(QWindow *window) : QPlatformBackingStore(window) { } MinimalBackingStore::~MinimalBackingStore() { } QPaintDevice *MinimalBackingStore::paintDevice() { return &mImage; } void MinimalBackingStore::flush(QWindow *, const QRegion &, const QPoint &) { } void MinimalBackingStore::resize(const QSize &size, const QRegion &) { QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); if (mImage.size() != size) mImage = QImage(size, format); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/qminimalbackingstore.h�������������������������������������0000664�0000000�0000000�00000001243�15226154130�0024717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef QBACKINGSTORE_MINIMAL_H #define QBACKINGSTORE_MINIMAL_H #include #include #include class MinimalBackingStore : public QPlatformBackingStore { public: MinimalBackingStore(QWindow *window); ~MinimalBackingStore() override; QPaintDevice *paintDevice() override; void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override; void resize(const QSize &size, const QRegion &staticContents) override; private: QImage mImage; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/qminimalintegration.cpp������������������������������������0000664�0000000�0000000�00000005013�15226154130�0025121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "qminimalintegration.h" #include "qminimalbackingstore.h" #include "dplatformnativeinterface.h" #include #include #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0) #include #else #include #endif MinimalIntegration::MinimalIntegration(const QStringList ¶meters) { Q_UNUSED(parameters); m_primaryScreen = new MinimalScreen(); m_primaryScreen->mGeometry = QRect(0, 0, 240, 320); m_primaryScreen->mDepth = 32; m_primaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied; QWindowSystemInterface::handleScreenAdded(m_primaryScreen); } MinimalIntegration::~MinimalIntegration() { QWindowSystemInterface::handleScreenRemoved(m_primaryScreen); } QPlatformWindow *MinimalIntegration::createPlatformWindow(QWindow *window) const { Q_UNUSED(window); QPlatformWindow *w = new QPlatformWindow(window); w->requestActivateWindow(); return w; } QPlatformBackingStore *MinimalIntegration::createPlatformBackingStore(QWindow *window) const { return new MinimalBackingStore(window); } QAbstractEventDispatcher *MinimalIntegration::createEventDispatcher() const { return createUnixEventDispatcher(); } QPlatformServices *MinimalIntegration::services() const { if (!m_services) #if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0) m_services.reset(new QDesktopUnixServices); #else m_services.reset(new QGenericUnixServices); #endif return m_services.get(); } QPlatformNativeInterface *MinimalIntegration::nativeInterface() const { if (!m_nativeInterface) m_nativeInterface.reset(new DPlatformNativeInterface); return m_nativeInterface.get(); } QStringList MinimalIntegration::themeNames() const { QStringList list = QPlatformIntegration::themeNames(); const QByteArray desktop_session = qgetenv("DESKTOP_SESSION"); if (desktop_session.isEmpty() || desktop_session.startsWith("deepin")) list.prepend("deepin"); return list; } MinimalIntegration *MinimalIntegration::instance() { return static_cast(QGuiApplicationPrivate::platformIntegration()); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/platform-plugin-test/qminimalintegration.h��������������������������������������0000664�0000000�0000000�00000002746�15226154130�0024600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 Uniontech Software Technology Co.,Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef QPLATFORMINTEGRATION_MINIMAL_H #define QPLATFORMINTEGRATION_MINIMAL_H #include #include #include class MinimalScreen : public QPlatformScreen { public: MinimalScreen() : mDepth(32), mFormat(QImage::Format_ARGB32_Premultiplied) {} QRect geometry() const override { return mGeometry; } int depth() const override { return mDepth; } QImage::Format format() const override { return mFormat; } public: QRect mGeometry; int mDepth; QImage::Format mFormat; QSize mPhysicalSize; }; class MinimalIntegration : public QPlatformIntegration { public: explicit MinimalIntegration(const QStringList ¶meters); ~MinimalIntegration() override; QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; QAbstractEventDispatcher *createEventDispatcher() const override; QPlatformServices *services() const override; QPlatformNativeInterface *nativeInterface() const override; QStringList themeNames() const override; static MinimalIntegration *instance(); private: mutable QScopedPointer m_nativeInterface; mutable QScopedPointer m_services; MinimalScreen *m_primaryScreen; }; #endif ��������������������������dtkgui-6.7.46/tests/res.qrc�������������������������������������������������������������������������0000664�0000000�0000000�00000001625�15226154130�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ images/logo_icon.png images/logo_icon.svg images/dci_heart_dci_hover.webp images/dci_heart_dci_normal.webp images/dci_heart_dci_pressed.webp ../examples/animation-dci/dci_heart.dci ../examples/animation-dci/3depict.dci images/deepin/index.theme images/deepin/cs_rect_64.svg actions/icon_Layout_16px.svg dcis/selected_indicator.dci �����������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0015035�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_builtinengine.cpp��������������������������������������������������������0000664�0000000�0000000�00000013546�15226154130�0021116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #define private public #include "dbuiltiniconengine_p.h" #undef private DGUI_USE_NAMESPACE #define ICONNAME "icon_Layout" #define ICONSIZE 16 class GTEST_API_ ut_DBuiltinIconEngine : public testing::Test { protected: void SetUp() override; void TearDown() override; DBuiltinIconEngine *mIconEngine; }; void ut_DBuiltinIconEngine::SetUp() { mIconEngine = new DBuiltinIconEngine(ICONNAME); } void ut_DBuiltinIconEngine::TearDown() { delete mIconEngine; } QIconLoaderEngineEntry *firstEntry(const QThemeIconEntries &entries) { #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) QIconLoaderEngineEntry *entry = entries.first(); #else QIconLoaderEngineEntry *entry = entries.begin()->get(); #endif return entry; } TEST_F(ut_DBuiltinIconEngine, loadIcon) { const QThemeIconInfo &themeInfo = mIconEngine->loadIcon(ICONNAME, DGuiApplicationHelper::instance()->themeType()); ASSERT_EQ(themeInfo.iconName, ICONNAME); QIconLoaderEngineEntry *entry = firstEntry(themeInfo.entries); QString builtinActionPath = ":/icons/deepin/builtin/actions"; ASSERT_TRUE(entry->filename.contains(ICONNAME)); ASSERT_EQ(entry->dir.path, builtinActionPath); ASSERT_EQ(entry->dir.size, ICONSIZE); ASSERT_EQ(entry->dir.type, QIconDirInfo::Scalable); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) ASSERT_FALSE(entry->pixmap(QSize(ICONSIZE, ICONSIZE), QIcon::Normal, QIcon::On, 1.0).isNull()); #else ASSERT_FALSE(entry->pixmap(QSize(ICONSIZE, ICONSIZE), QIcon::Normal, QIcon::On).isNull()); #endif #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) for (auto item : themeInfo.entries) { delete item; } #endif } TEST_F(ut_DBuiltinIconEngine, actualSize) { QSize size(ICONSIZE, ICONSIZE); QSize iconSize = mIconEngine->actualSize(size, QIcon::Normal, QIcon::On); ASSERT_FALSE(iconSize.isEmpty()); QIconLoaderEngineEntry *entry = firstEntry(mIconEngine->m_info.entries); if (entry->dir.type == QIconDirInfo::Scalable) { ASSERT_EQ(iconSize, size); } else { bool isTrue = (iconSize.width() <= qMin(iconSize.width(), iconSize.height())) && (iconSize.height() <= qMin(iconSize.width(), iconSize.height())); ASSERT_TRUE(isTrue); } } TEST_F(ut_DBuiltinIconEngine, pixmap) { QPixmap iconenginePixmap = mIconEngine->pixmap(QSize(ICONSIZE, ICONSIZE), QIcon::Normal, QIcon::On); ASSERT_FALSE(iconenginePixmap.isNull()); } TEST_F(ut_DBuiltinIconEngine, paint) { QImage iconImage(QSize(ICONSIZE, ICONSIZE), QImage::Format_ARGB32); QPainter iconPainter(&iconImage); mIconEngine->paint(&iconPainter, QRect({0, 0}, iconImage.size()), QIcon::Normal, QIcon::On); ASSERT_FALSE(iconImage.isNull()); } TEST_F(ut_DBuiltinIconEngine, key) { ASSERT_EQ(mIconEngine->key(), "DBuiltinIconEngine"); } TEST_F(ut_DBuiltinIconEngine, clone) { auto clone = mIconEngine->clone(); ASSERT_FALSE(!clone); delete clone; } TEST_F(ut_DBuiltinIconEngine, read) { QByteArray data; uint key = 1; bool followSystemTheme = true; QString iconName = ICONNAME; QDataStream out(&data, QIODevice::WriteOnly); out << iconName << key << followSystemTheme; QDataStream in(&data, QIODevice::ReadOnly); mIconEngine->read(in); ASSERT_EQ(mIconEngine->m_iconName, iconName); ASSERT_EQ(mIconEngine->m_key, key); ASSERT_EQ(mIconEngine->m_followSystemTheme, followSystemTheme); } TEST_F(ut_DBuiltinIconEngine, write) { QByteArray data; QDataStream out(&data, QIODevice::WriteOnly); mIconEngine->write(out); uint key = 0; bool followSystemTheme = false; QString iconName; QDataStream in(&data, QIODevice::ReadOnly); in >> iconName >> key >> followSystemTheme; ASSERT_EQ(mIconEngine->m_iconName, iconName); ASSERT_EQ(mIconEngine->m_key, key); ASSERT_EQ(mIconEngine->m_followSystemTheme, followSystemTheme); } TEST_F(ut_DBuiltinIconEngine, iconName) { ASSERT_EQ(mIconEngine->iconName(), ICONNAME); } TEST_F(ut_DBuiltinIconEngine, ensureLoaded) { mIconEngine->ensureLoaded(); ASSERT_EQ(mIconEngine->m_key, DGuiApplicationHelper::instance()->themeType()); ASSERT_TRUE(mIconEngine->m_initialized); ASSERT_EQ(mIconEngine->m_info.iconName, ICONNAME); QIconLoaderEngineEntry *entry = firstEntry(mIconEngine->m_info.entries); QString builtinActionPath = ":/icons/deepin/builtin/actions"; ASSERT_TRUE(entry->filename.contains(ICONNAME)); ASSERT_EQ(entry->dir.path, builtinActionPath); ASSERT_EQ(entry->dir.size, ICONSIZE); ASSERT_EQ(entry->dir.type, QIconDirInfo::Scalable); } TEST_F(ut_DBuiltinIconEngine, hasIcon) { mIconEngine->ensureLoaded(); ASSERT_TRUE(mIconEngine->hasIcon()); } TEST_F(ut_DBuiltinIconEngine, virtual_hook) { void *arg; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QIconEngine::AvailableSizesArgument data; arg = reinterpret_cast(&data); mIconEngine->virtual_hook(QIconEngine::AvailableSizesHook, arg); ASSERT_FALSE(data.sizes.isEmpty()); QString icon_name; arg = reinterpret_cast(&icon_name); mIconEngine->virtual_hook(QIconEngine::IconNameHook, arg); ASSERT_EQ(icon_name, ICONNAME); #endif bool isNull = true; arg = reinterpret_cast(&isNull); mIconEngine->virtual_hook(QIconEngine::IsNullHook, arg); ASSERT_FALSE(isNull); QIconEngine::ScaledPixmapArgument pixmapData; // å�‚数值会在函数内部进行判断,需è¦�åˆ�始化å�Žä¼ å…¥ 并判断函数是å�¦æ‰§è¡Œæˆ�功 pixmapData.size = QSize(ICONSIZE, ICONSIZE); pixmapData.scale = 1; arg = reinterpret_cast(&pixmapData); mIconEngine->virtual_hook(QIconEngine::ScaledPixmapHook, arg); ASSERT_FALSE(pixmapData.pixmap.isNull()); } ����������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dciiconengine.cpp��������������������������������������������������������0000664�0000000�0000000�00000004762�15226154130�0021060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include #include #include #include "dciiconengine_p.h" DGUI_USE_NAMESPACE class GTEST_API_ ut_DDciIconEngine : public testing::Test { protected: void SetUp() override; void TearDown() override; DDciIconEngine *mIconEngine = nullptr; }; void ut_DDciIconEngine::SetUp() { mIconEngine = new DDciIconEngine("test_selected_indicator"); } void ut_DDciIconEngine::TearDown() { delete mIconEngine; } TEST_F(ut_DDciIconEngine, actualSize) { QSize size(32, 32); QSize iconSize = mIconEngine->actualSize(size, QIcon::Normal, QIcon::On); ASSERT_FALSE(iconSize.isEmpty()); ASSERT_EQ(iconSize, QSize(16, 16)); // 该图标å�ªæœ‰16这个大å°�。。 } TEST_F(ut_DDciIconEngine, pixmap) { QPixmap iconenginePixmap = mIconEngine->pixmap(QSize(32, 32), QIcon::Normal, QIcon::On); ASSERT_FALSE(iconenginePixmap.isNull()); } TEST_F(ut_DDciIconEngine, paint) { QImage iconImage(QSize(32, 32), QImage::Format_ARGB32); QPainter iconPainter(&iconImage); mIconEngine->paint(&iconPainter, QRect({0, 0}, iconImage.size()), QIcon::Normal, QIcon::On); ASSERT_FALSE(iconImage.isNull()); } TEST_F(ut_DDciIconEngine, key) { QIcon icon(new DDciIconEngine("test_selected_indicator")); ASSERT_EQ(icon.data_ptr()->engine->key(), "DDciIconEngine"); } TEST_F(ut_DDciIconEngine, clone) { auto clone = mIconEngine->clone(); ASSERT_FALSE(!clone); delete clone; } TEST_F(ut_DDciIconEngine, read) { QByteArray data; QString iconName = "test_selected_indicator"; QString iconThemeName = DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName(); QDataStream out(&data, QIODevice::WriteOnly); out << iconThemeName << iconName; QDataStream in(&data, QIODevice::ReadOnly); mIconEngine->read(in); ASSERT_EQ(mIconEngine->iconName(), iconName); } TEST_F(ut_DDciIconEngine, write) { QByteArray data; QDataStream out(&data, QIODevice::WriteOnly); mIconEngine->write(out); QString iconName, iconThemeName; QDataStream in(&data, QIODevice::ReadOnly); in >> iconThemeName >> iconName ; ASSERT_EQ(mIconEngine->iconName(), iconName); } TEST_F(ut_DDciIconEngine, iconName) { ASSERT_EQ(mIconEngine->iconName(), "test_selected_indicator"); } ��������������dtkgui-6.7.46/tests/src/ut_ddciicon.cpp�������������������������������������������������������������0000664�0000000�0000000�00000002057�15226154130�0020031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "ddciicon.h" #include DGUI_USE_NAMESPACE class GTEST_API_ ut_DDciIcon : public DTest { public: ut_DDciIcon() : icon(QStringLiteral(":/images/dci_heart.dci")) {} ~ut_DDciIcon() override {} DDciIcon icon; }; TEST_F(ut_DDciIcon, isNull) { ASSERT_FALSE(icon.isNull()); } TEST_F(ut_DDciIcon, actualSize) { DDciIconMatchResult res = icon.matchIcon(64, DDciIcon::Light, DDciIcon::Normal); int size = icon.actualSize(res); ASSERT_EQ(size, 100); } TEST_F(ut_DDciIcon, pixmap) { EXPECT_EQ(icon.pixmap(1, 0, DDciIcon::Light).size().height(), 100); // invalid size 0 EXPECT_EQ(icon.pixmap(1, 64, DDciIcon::Light).size().height(), 64); EXPECT_EQ(icon.pixmap(1.25, 64, DDciIcon::Light).size().height(), 80); // 64 * 1.25 EXPECT_EQ(icon.pixmap(1, 100, DDciIcon::Light).size().height(), 100); EXPECT_EQ(icon.pixmap(1, 256, DDciIcon::Light).size().height(), 256); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_ddciiconpalette.cpp������������������������������������������������������0000664�0000000�0000000�00000005570�15226154130�0021413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "ddciiconpalette.h" #include #include #include DGUI_USE_NAMESPACE static QVariant property(const DDciIconPalette &pa, const char *name) { const QMetaObject *meta = &pa.staticMetaObject; int id = meta->indexOfProperty(name); if (id < 0) return QVariant(); QMetaProperty p = meta->property(id); if (!p.isReadable()) qWarning("%s::property: Property \"%s\" invalid or does not exist", meta->className(), name); return p.readOnGadget(&pa); } static bool setProperty(DDciIconPalette &pa, const char *name, const QVariant &var) { const QMetaObject *meta = &pa.staticMetaObject; int id = meta->indexOfProperty(name); if (id < 0) { qWarning("%s::setProperty: Property \"%s\" invalid," "not support dynamic property..", meta->className(), name); return false; } QMetaProperty p = meta->property(id); if (!p.isWritable()) qWarning("%s::setProperty: Property \"%s\" invalid," " read-only or does not exist", meta->className(), name); return p.writeOnGadget(&pa, var); } TEST(ut_DDciIconPalette, color) { DDciIconPalette pa(Qt::red, Qt::green, Qt::black, Qt::white); #define testColor(role, setFunc,color1, color2) do { \ Q_ASSERT(color1!=color2); \ ASSERT_EQ(pa.role(), color1); \ ASSERT_EQ(property(pa, QT_STRINGIFY(role)), color1); \ pa.setFunc(color2); \ ASSERT_EQ(pa.role(), color2); \ ASSERT_EQ(property(pa, QT_STRINGIFY(role)), color2); \ setProperty(pa, #role, QColor(color1)); \ ASSERT_EQ(pa.role(), color1); \ ASSERT_EQ(property(pa, QT_STRINGIFY(role)), color1); \ } while(false); testColor(foreground, setForeground, QColor(Qt::red), QColor(Qt::green)); testColor(background, setBackground, QColor(Qt::green), QColor(Qt::red)); testColor(highlight, setHighlight,QColor(Qt::black), QColor(Qt::white)); testColor(highlightForeground, setHighlightForeground, QColor(Qt::white), QColor(Qt::black)); } TEST(ut_DDciIconPalette, convertToString_convertFromString_operator) { DDciIconPalette pa(Qt::red, Qt::green, Qt::black, Qt::white); // convertToString QString str = DDciIconPalette::convertToString(pa); // convertFromString auto ap = DDciIconPalette::convertFromString(str); // operator != && == ASSERT_FALSE(pa != ap); } TEST(ut_DDciIconPalette, fromQPalette) { DDciIconPalette pa(Qt::red, Qt::green, Qt::black, Qt::white); QPalette qpa; qpa.setColor(QPalette::WindowText, Qt::red); qpa.setColor(QPalette::Window, Qt::green); qpa.setColor(QPalette::Highlight, Qt::black); qpa.setColor(QPalette::HighlightedText, Qt::white); ASSERT_EQ(pa, DDciIconPalette::fromQPalette(qpa)); } ����������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_ddciiconplayer.cpp�������������������������������������������������������0000664�0000000�0000000�00000027407�15226154130�0021254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "ddciicon.h" #include "ddciiconplayer.h" #include #include #include #include #include #include DGUI_USE_NAMESPACE static void image_dye(QImage &image, const QColor &color) { QPainter pa(&image); pa.setCompositionMode(QPainter::CompositionMode_SourceIn); pa.fillRect(image.rect(), color); } TEST(ut_DDciIconImage, render) { DDciIcon icon(QStringLiteral(":/images/dci_heart.dci")); ASSERT_FALSE(icon.isNull()); { // normal auto result = icon.matchIcon(-1, DDciIcon::Light, DDciIcon::Normal); QImageReader reader(":/images/dci_heart_dci_normal.webp"); DDciIconImage image = icon.image(result, reader.size().width(), 1.0); ASSERT_FALSE(image.isNull()); ASSERT_TRUE(image.hasPalette()); QImage image1 = image.toImage(DDciIconPalette(Qt::red)); QImage image2 = reader.read().convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } { // hover auto result = icon.matchIcon(-1, DDciIcon::Light, DDciIcon::Hover); QImageReader reader(":/images/dci_heart_dci_hover.webp"); DDciIconImage image = icon.image(result, reader.size().width(), 1.0); ASSERT_FALSE(image.isNull()); ASSERT_TRUE(reader.canRead()); ASSERT_TRUE(image.supportsAnimation()); ASSERT_TRUE(reader.supportsAnimation()); ASSERT_TRUE(image.atBegin()); ASSERT_EQ(image.loopCount(), reader.loopCount()); ASSERT_EQ(image.maxImageCount(), reader.imageCount()); while (!image.atEnd()) { QImage image1 = image.toImage(); QImage image2 = reader.read().convertToFormat(image1.format()); ASSERT_EQ(image1, image2); ASSERT_EQ(image.currentImageDuration(), reader.nextImageDelay()); ASSERT_TRUE(image.jumpToNextImage()); } } { // pressed auto result = icon.matchIcon(-1, DDciIcon::Light, DDciIcon::Pressed); QImageReader reader(":/images/dci_heart_dci_pressed.webp"); DDciIconImage image = icon.image(result, reader.size().width(), 1.0); ASSERT_FALSE(image.isNull()); ASSERT_TRUE(reader.canRead()); ASSERT_TRUE(image.supportsAnimation()); ASSERT_TRUE(reader.supportsAnimation()); ASSERT_TRUE(image.atBegin()); ASSERT_EQ(image.loopCount(), reader.loopCount()); ASSERT_EQ(image.maxImageCount(), reader.imageCount()); while (!image.atEnd()) { QImage image1 = image.toImage(); QImage image2 = reader.read().convertToFormat(image1.format()); ASSERT_EQ(image1, image2); ASSERT_EQ(image.currentImageDuration(), reader.nextImageDelay()); ASSERT_TRUE(image.jumpToNextImage()); } } } class GTEST_API_ ut_DDciIconPlayer : public DTest { protected: ut_DDciIconPlayer() : update_signal_spy(&player, &DDciIconPlayer::updated) {} void SetUp() override; void TearDown() override; DDciIconPlayer player; QSignalSpy update_signal_spy; }; void ut_DDciIconPlayer::SetUp() { DDciIcon icon(QStringLiteral(":/images/dci_heart.dci")); ASSERT_FALSE(icon.isNull()); player.setIcon(icon); player.setTheme(DDciIcon::Light); player.setIconSize(200); player.setDevicePixelRatio(1.0); player.setPalette(DDciIconPalette(Qt::red)); qputenv("D_DTK_DCI_PLAYER_IGNORE_ANIMATION_LOOP", "1"); } void ut_DDciIconPlayer::TearDown() { qunsetenv("D_DTK_DCI_PLAYER_IGNORE_ANIMATION_LOOP"); } TEST_F(ut_DDciIconPlayer, play) { QImageReader reader(":/images/dci_heart_dci_hover.webp"); update_signal_spy.clear(); player.play(DDciIcon::Hover); while (update_signal_spy.wait(100)); ASSERT_EQ(update_signal_spy.count(), reader.imageCount()); } TEST_F(ut_DDciIconPlayer, state) { player.abort(); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); QSignalSpy state_changed_signal_spy(&player, &DDciIconPlayer::stateChanged); player.play(DDciIcon::Hover); ASSERT_EQ(player.state(), DDciIconPlayer::Busy); ASSERT_TRUE(state_changed_signal_spy.wait(2000)); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); ASSERT_EQ(state_changed_signal_spy.count(), 2); player.play(DDciIcon::Pressed); ASSERT_EQ(player.state(), DDciIconPlayer::Busy); player.stop(); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); ASSERT_EQ(state_changed_signal_spy.count(), 4); player.setMode(DDciIcon::Normal); player.setMode(DDciIcon::Pressed); ASSERT_TRUE(update_signal_spy.wait(100)); ASSERT_EQ(player.state(), DDciIconPlayer::Busy); player.abort(); ASSERT_FALSE(update_signal_spy.wait(100)); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); ASSERT_EQ(state_changed_signal_spy.count(), 6); player.setMode(DDciIcon::Normal); int idle_count = 0; while (update_signal_spy.wait(100)) if (player.state() == DDciIconPlayer::Idle) ++idle_count; ASSERT_EQ(idle_count, 1); ASSERT_EQ(state_changed_signal_spy.count(), 8); } TEST_F(ut_DDciIconPlayer, setMode) { QImageReader hover(":/images/dci_heart_dci_hover.webp"); QImageReader pressed(":/images/dci_heart_dci_pressed.webp"); player.setMode(DDciIcon::Normal); player.abort(); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); { // normal -> hover update_signal_spy.clear(); player.setMode(DDciIcon::Hover); while (update_signal_spy.wait(100)); ASSERT_EQ(update_signal_spy.count(), hover.imageCount()); } { // hover -> pressed update_signal_spy.clear(); player.setMode(DDciIcon::Pressed); while (update_signal_spy.wait(100)); ASSERT_EQ(update_signal_spy.count(), pressed.imageCount()); } { // pressed -> hover update_signal_spy.clear(); player.setMode(DDciIcon::Hover); while (update_signal_spy.wait(100)); // the animation is stop in the hover's last image, so needs +1 ASSERT_EQ(update_signal_spy.count(), pressed.imageCount() + 1); } { // hover -> normal update_signal_spy.clear(); player.setMode(DDciIcon::Normal); while (update_signal_spy.wait(100)); // the animation is stop in the normal state, so needs +1 ASSERT_EQ(update_signal_spy.count(), hover.imageCount() + 1); } { // normal -> pressed update_signal_spy.clear(); player.setMode(DDciIcon::Pressed); while (update_signal_spy.wait(100)); ASSERT_EQ(update_signal_spy.count(), hover.imageCount() + pressed.imageCount()); } { // pressed -> normal update_signal_spy.clear(); player.setMode(DDciIcon::Normal); while (update_signal_spy.wait(100)); // the animation is stop in the normal state, so needs +1 ASSERT_EQ(update_signal_spy.count(), hover.imageCount() + pressed.imageCount() + 1); } { player.setMode(DDciIcon::Normal); player.abort(); // hover -> disabled update_signal_spy.clear(); player.setMode(DDciIcon::Hover); while (update_signal_spy.wait(100)) { player.setMode(DDciIcon::Disabled); } ASSERT_EQ(update_signal_spy.count(), 2); QImageReader normal(":/images/dci_heart_dci_normal.webp"); QImage image1 = player.currentImage(); QImage image2 = normal.read().convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } { update_signal_spy.clear(); // disable -> pressed player.setMode(DDciIcon::Pressed); update_signal_spy.wait(100); ASSERT_EQ(update_signal_spy.count(), 1); QImageReader normal(":/images/dci_heart_dci_normal.webp"); QImage image1 = player.currentImage(); QImage image2 = normal.read().convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } } TEST_F(ut_DDciIconPlayer, animationInvertedOrderAndContinue) { QImageReader hover(":/images/dci_heart_dci_hover.webp"); QImageReader pressed(":/images/dci_heart_dci_pressed.webp"); player.setMode(DDciIcon::Normal); player.abort(); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); QVector> images; while (hover.canRead()) { const QImage &img = hover.read(); images.append({img, hover.nextImageDelay()}); } while (pressed.canRead()) { const QImage &img = pressed.read(); images.append({img, pressed.nextImageDelay()}); } update_signal_spy.clear(); player.setMode(DDciIcon::Hover); int lastImageIndex = -1; while (update_signal_spy.count() < hover.imageCount() / 2 && update_signal_spy.wait(100)) { QImage image1 = player.currentImage(); auto i = images[++lastImageIndex]; QImage image2 = i.first.convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } player.setMode(DDciIcon::Normal); ASSERT_TRUE(update_signal_spy.wait(0)); do { ASSERT_TRUE(lastImageIndex > -2); // the last image is normal if (lastImageIndex < 0) { QImageReader normal(":/images/dci_heart_dci_normal.webp"); QImage image1 = player.currentImage(); QImage image2 = normal.read().convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); break; } ASSERT_TRUE(lastImageIndex < images.count()); QImage image1 = player.currentImage(); auto i = images[lastImageIndex]; QImage image2 = i.first.convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } while (update_signal_spy.wait(images[lastImageIndex--].second + 1)); ASSERT_EQ(lastImageIndex, -1); } TEST_F(ut_DDciIconPlayer, animationSequentially) { QImageReader hover(":/images/dci_heart_dci_hover.webp"); QImageReader pressed(":/images/dci_heart_dci_pressed.webp"); player.setMode(DDciIcon::Normal); player.abort(); ASSERT_EQ(player.state(), DDciIconPlayer::Idle); QVector> images; while (hover.canRead()) { const QImage &img = hover.read(); images.append({img, hover.nextImageDelay()}); } while (pressed.canRead()) { const QImage &img = pressed.read(); images.append({img, pressed.nextImageDelay()}); } update_signal_spy.clear(); player.setMode(DDciIcon::Hover); player.setMode(DDciIcon::Pressed); int lastImageIndex = 0; while (update_signal_spy.wait(100)) { ASSERT_TRUE(lastImageIndex < images.count()); QImage image1 = player.currentImage(); auto i = images[lastImageIndex++]; QImage image2 = i.first.convertToFormat(image1.format()); image2.setDevicePixelRatio(1.0); if (lastImageIndex <= hover.imageCount()) // the pressed image is not have palette image_dye(image2, Qt::red); ASSERT_EQ(image1, image2); } ASSERT_EQ(lastImageIndex, images.count()); } TEST_F(ut_DDciIconPlayer, nonAnimationImage) { DDciIcon icon(QStringLiteral(":/images/3depict.dci")); ASSERT_FALSE(icon.isNull()); DDciIconPlayer player; update_signal_spy.clear(); player.setIcon(icon); update_signal_spy.wait(1000); ASSERT_EQ(update_signal_spy.count(), 1); ASSERT_FALSE(player.currentImage().isNull()); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dfiledrag.cpp������������������������������������������������������������0000664�0000000�0000000�00000004403�15226154130�0020173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dfiledragcommon_p.h" #include "dfiledrag.h" #include "dfiledragserver.h" #include "dfiledragclient.h" #include #include #include #include #include DGUI_USE_NAMESPACE TEST(ut_DFileDrag, filedrag) { qRegisterMetaType("DFileDragState"); QObject source; QScopedPointer s(new DFileDragServer()); QMimeData *m = new QMimeData(); // QMimeData will delete on ~DFileDrag~QDrag QScopedPointer drag(new DFileDrag(&source, s.data())); drag->setMimeData(m); ASSERT_TRUE(DFileDragClient::checkMimeData(m)); { QSignalSpy spy(s.data(), &DFileDragServer::targetDataChanged); DFileDragClient::setTargetData(m, "Key0", "Value0"); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); ASSERT_EQ(s->targetData("Key0"), QVariant("Value0")); } { QUrl url = QUrl::fromLocalFile("/tmp/xxx"); QSignalSpy spy(drag.data(), &DFileDrag::targetUrlChanged); DFileDragClient::setTargetUrl(m, url); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); ASSERT_EQ(drag->targetUrl(), url); } // client will delete on serverDestroyed DFileDragClient *c = new DFileDragClient(m); { ASSERT_EQ(c->progress(), 0); QSignalSpy spy(c, &DFileDragClient::progressChanged); s->setProgress(30); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); ASSERT_EQ(c->progress(), 30); } { ASSERT_EQ(c->state(), 0); QSignalSpy spy(c, &DFileDragClient::stateChanged); s->setState(DFileDragState::Running); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); ASSERT_EQ(c->state(), DFileDragState::Running); } { QSignalSpy spy(c, &DFileDragClient::serverDestroyed); // destroy server to emit serverDestroyed s.reset(); waitforSpy(spy, 1000); ASSERT_TRUE(spy.count() > 0); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dfontmanager.cpp���������������������������������������������������������0000664�0000000�0000000�00000005100�15226154130�0020712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dfontmanager.h" #include DGUI_USE_NAMESPACE TEST(ut_DFontManager, StaticFunction) { enum { FontSize = 18 }; QFont tF = DFontManager::get(FontSize, qApp->font()); ASSERT_EQ(tF.pixelSize(), FontSize); ASSERT_EQ(DFontManager::fontPixelSize(tF), FontSize); tF.setPointSizeF(FontSize); ASSERT_TRUE(DFontManager::fontPixelSize(tF) > 0); } class GTEST_API_ TDFontManager : public DTestWithParam { protected: void SetUp(); void TearDown(); DFontManager *manager; }; INSTANTIATE_TEST_CASE_P(DFontManager, TDFontManager, testing::Range(int(DFontManager::T1), int(DFontManager::NSizeTypes))); void TDFontManager::SetUp() { manager = new DFontManager; } void TDFontManager::TearDown() { delete manager; } TEST_P(TDFontManager, testGetFont) { int param = GetParam(); QFont font = manager->get(DFontManager::SizeType(param), qApp->font()); ASSERT_EQ(font.pixelSize(), manager->fontPixelSize(DFontManager::SizeType(param))); manager->setBaseFont(qApp->font()); ASSERT_EQ(manager->baseFont(), qApp->font()); font = manager->get(DFontManager::SizeType(param)); ASSERT_EQ(font.pixelSize(), manager->fontPixelSize(DFontManager::SizeType(param))); manager->resetBaseFont(); ASSERT_NE(manager->baseFont(), qApp->font()); manager->setFontPixelSize(DFontManager::SizeType(param), param); ASSERT_EQ(manager->fontPixelSize(DFontManager::SizeType(param)), param); } TEST_F(TDFontManager, testFontSize) { manager->setBaseFont(qApp->font()); ASSERT_EQ(manager->t1().pixelSize(), manager->fontPixelSize(DFontManager::T1)); ASSERT_EQ(manager->t2().pixelSize(), manager->fontPixelSize(DFontManager::T2)); ASSERT_EQ(manager->t3().pixelSize(), manager->fontPixelSize(DFontManager::T3)); ASSERT_EQ(manager->t4().pixelSize(), manager->fontPixelSize(DFontManager::T4)); ASSERT_EQ(manager->t5().pixelSize(), manager->fontPixelSize(DFontManager::T5)); ASSERT_EQ(manager->t6().pixelSize(), manager->fontPixelSize(DFontManager::T6)); ASSERT_EQ(manager->t7().pixelSize(), manager->fontPixelSize(DFontManager::T7)); ASSERT_EQ(manager->t8().pixelSize(), manager->fontPixelSize(DFontManager::T8)); ASSERT_EQ(manager->t9().pixelSize(), manager->fontPixelSize(DFontManager::T9)); ASSERT_EQ(manager->t10().pixelSize(), manager->fontPixelSize(DFontManager::T10)); ASSERT_EQ(manager->t11().pixelSize(), manager->fontPixelSize(DFontManager::T11)); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dforeignwindow.cpp�������������������������������������������������������0000664�0000000�0000000�00000003172�15226154130�0021301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dforeignwindow.h" #include #include #include DGUI_BEGIN_NAMESPACE #define WmClass "_d_WmClass" #define ProcessId "_d_ProcessId" class GTEST_API_ TDForeignWindow : public DTest { protected: virtual void SetUp() { const QVector ¤tIdList = DWindowManagerHelper::instance()->currentWorkspaceWindowIdList(); foreignWindows.clear(); for (const auto ¤tId : currentIdList) { foreignWindows.append(DForeignWindow::fromWinId(currentId)); } } virtual void TearDown() { qDeleteAll(foreignWindows); foreignWindows.clear(); } QList foreignWindows; }; TEST_F(TDForeignWindow, wmClass) { for (auto foreignWindow : foreignWindows) ASSERT_NE(foreignWindow->wmClass(), QString()); } TEST_F(TDForeignWindow, pid) { for (auto foreignWindow : foreignWindows) ASSERT_NE(foreignWindow->pid(), 0); } TEST_F(TDForeignWindow, event) { QDynamicPropertyChangeEvent wmevent(WmClass); QDynamicPropertyChangeEvent pidevent(ProcessId); for (auto foreignWindow : foreignWindows) { QSignalSpy wmspy(foreignWindow, SIGNAL(wmClassChanged())); ASSERT_TRUE(foreignWindow->event(&wmevent)); ASSERT_EQ(wmspy.count(), 1); QSignalSpy pidspy(foreignWindow, SIGNAL(pidChanged())); ASSERT_TRUE(foreignWindow->event(&pidevent)); ASSERT_EQ(pidspy.count(), 1); } } DGUI_END_NAMESPACE ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dguiapplicationhelper.cpp������������������������������������������������0000664�0000000�0000000�00000011657�15226154130�0022637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #define private public #include "dguiapplicationhelper_p.h" #include "dguiapplicationhelper.h" #undef private #include #include DGUI_BEGIN_NAMESPACE class TDGuiApplicationHelper : public DTest { protected: virtual void SetUp() { helper = DGuiApplicationHelper::instance(); helper_d = helper->d_func(); /* read write */ readWriteDatas << DGuiApplicationHelper::Attribute::UseInactiveColorGroup << DGuiApplicationHelper::Attribute::ColorCompositing; /* read only */ readOnlyDatas << DGuiApplicationHelper::Attribute::IsDeepinPlatformTheme << DGuiApplicationHelper::Attribute::IsDXcbPlatform << DGuiApplicationHelper::Attribute::IsXWindowPlatform << DGuiApplicationHelper::Attribute::IsTableEnvironment << DGuiApplicationHelper::Attribute::IsDeepinEnvironment; } DGuiApplicationHelper *helper = nullptr; DGuiApplicationHelperPrivate *helper_d = nullptr; QList readWriteDatas; QList readOnlyDatas; }; TEST_F(TDGuiApplicationHelper, testFunction) { QColor testColor(Qt::red); QColor adjustedColor = helper->adjustColor(testColor, 0, 0, 0, 0, 0, 0, -20); ASSERT_NE(testColor, adjustedColor); ASSERT_TRUE(adjustedColor.isValid()); QColor disBlendColor = Qt::black; QColor blendedColor = helper->blendColor(testColor, disBlendColor); ASSERT_NE(testColor, blendedColor); ASSERT_TRUE(blendedColor.isValid()); DPalette tPalette; helper->generatePaletteColor(tPalette, QPalette::Window, DGuiApplicationHelper::ColorType::LightType); ASSERT_EQ(tPalette.brush(QPalette::Disabled, QPalette::Window), tPalette.brush(QPalette::Normal, QPalette::Window)); tPalette.setColor(DPalette::Window, Qt::black); helper->generatePaletteColor(tPalette, QPalette::Highlight, DGuiApplicationHelper::ColorType::DarkType); ASSERT_TRUE(tPalette.highlight().color().isValid()); // åˆ�始化调色æ�¿ä¸ºé»˜è®¤å€¼ helper->generatePalette(tPalette); ASSERT_EQ(helper->isXWindowPlatform(), DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsXWindowPlatform)); ASSERT_EQ(helper->isTabletEnvironment(), DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTableEnvironment)); ASSERT_TRUE(helper->applicationTheme()); ASSERT_TRUE(helper->systemTheme()); ASSERT_NE(helper->applicationPalette(), tPalette); qGuiApp->setAttribute(Qt::AA_SetPalette, false); helper->setPaletteType(DGuiApplicationHelper::DarkType); ASSERT_NE(helper->applicationPalette(), tPalette); helper->setApplicationPalette(tPalette); ASSERT_EQ(helper->applicationPalette(), tPalette); ASSERT_TRUE(helper->fontManager()); ASSERT_EQ(helper->toColorType(QColor(Qt::white)), DGuiApplicationHelper::LightType); ASSERT_EQ(helper->toColorType(QColor(Qt::black)), DGuiApplicationHelper::DarkType); ASSERT_EQ(helper->themeType(), DGuiApplicationHelper::DarkType); ASSERT_EQ(helper->paletteType(), DGuiApplicationHelper::DarkType); } TEST_F(TDGuiApplicationHelper, adjustColor_NoChange) { QColor testColor(Qt::red); QColor adjustedColor = helper->adjustColor(testColor, 0, 0, 0, 0, 0, 0, 0); ASSERT_EQ(testColor, adjustedColor); testColor = QColor::fromHsl(100, 100, 100, 100); adjustedColor = helper->adjustColor(testColor, 0, 0, 0, 0, 0, 0, 0); ASSERT_EQ(testColor, adjustedColor); } TEST_F(TDGuiApplicationHelper, AttributeReadWrite) { QMap oldData; for (const DGuiApplicationHelper::Attribute attribute : readWriteDatas) { oldData[attribute] = helper->testAttribute(attribute); } for (const DGuiApplicationHelper::Attribute attribute : readWriteDatas) { helper->setAttribute(attribute, !oldData[attribute]); EXPECT_EQ(helper->testAttribute(attribute), !oldData[attribute]); } } TEST_F(TDGuiApplicationHelper, AttributeReadOnly) { QMap oldData; for (const DGuiApplicationHelper::Attribute attribute : readOnlyDatas) { oldData[attribute] = helper->testAttribute(attribute); } for (const DGuiApplicationHelper::Attribute attribute : readOnlyDatas) { helper->setAttribute(attribute, !oldData[attribute]); EXPECT_EQ(helper->testAttribute(attribute), oldData[attribute]); } } TEST_F(TDGuiApplicationHelper, loadTranslator) { EXPECT_EQ(QProcess::tr("No program defined"), "No program defined"); DGuiApplicationHelper::loadTranslator({QLocale("zh_CN")}); EXPECT_EQ(QProcess::tr("No program defined"), "没有定义程åº�"); qInfo() << QCoreApplication::translate("TDGuiApplicationHelper", "test-translation"); } DGUI_END_NAMESPACE ���������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dicon.cpp����������������������������������������������������������������0000664�0000000�0000000�00000003252�15226154130�0017347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include #include DGUI_USE_NAMESPACE TEST(ut_DIcon, pixmap) { QIcon icon = QIcon::fromTheme("dde", QIcon(":/images/logo_icon.png")); ASSERT_FALSE(icon.isNull()); DIcon dicon(icon); QSize size(32, 32); qreal devicePixelRatio = qApp->devicePixelRatio(); // D_DXCB_DISABLE_OVERRIDE_HIDPI=1 QT_SCALE_FACTOR=1.25 ASSERT_FLOAT_EQ(devicePixelRatio, 1.25); // 默认å�•元测试未开å�¯ AA_UseHighDpiPixmaps, 这时 pixmap 获å�–çš„ devicePixelRatio 为 1.0 // 图片大å°�也就是设置大å°� 32x32 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ASSERT_FALSE(QGuiApplication::testAttribute(Qt::AA_UseHighDpiPixmaps)); #endif ASSERT_EQ(icon.pixmap(size).size(), size); // å¼€å�¯ AA_UseHighDpiPixmaps 之å�Ž pixmap 的大å°�å’Œ qApp 缩放有关 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); ASSERT_EQ(icon.pixmap(size).size(), size * devicePixelRatio); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, false); ASSERT_EQ(dicon.pixmap(size, -1).size(), size * devicePixelRatio); ASSERT_EQ(dicon.pixmap(size, 1.0).size(), size); ASSERT_EQ(dicon.pixmap(size, 1.75).size(), size * 1.75); #else // DIcon 在 Qt6 下行为应和 QIcon 这个接å�£ä¸€è‡´ ASSERT_EQ(dicon.pixmap(size, -1).size(), icon.pixmap(size, -1).size()); ASSERT_EQ(dicon.pixmap(size, 1.0).size(), icon.pixmap(size, 1.0).size()); ASSERT_EQ(dicon.pixmap(size, 1.75).size(), icon.pixmap(size, 1.75).size()); #endif } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_diconproxyengine.cpp�����������������������������������������������������0000664�0000000�0000000�00000007643�15226154130�0021647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include #define private public #include "diconproxyengine_p.h" #undef private DGUI_USE_NAMESPACE /* bool read(QDataStream &in) override; bool write(QDataStream &out) const override; private: void virtual_hook(int id, void *data) override; */ class GTEST_API_ ut_DIconProxyEngine : public testing::Test { protected: void SetUp() override; void TearDown() override; DIconProxyEngine *mIconEngine = nullptr; QSize s64 = QSize(64, 64); }; void ut_DIconProxyEngine::SetUp() { mIconEngine = new DIconProxyEngine("selected_indicator" ,DIconTheme::DontFallbackToQIconFromTheme); } void ut_DIconProxyEngine::TearDown() { delete mIconEngine; } TEST_F(ut_DIconProxyEngine, key_proxyKey) { EXPECT_EQ(mIconEngine->key(), QLatin1String("DIconProxyEngine")); EXPECT_EQ(mIconEngine->proxyKey(), QLatin1String("DBuiltinIconEngine")); } TEST_F(ut_DIconProxyEngine, themeName) { QString themeName = DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName(); EXPECT_EQ(mIconEngine->themeName(), themeName); } TEST_F(ut_DIconProxyEngine, iconName) { EXPECT_EQ(mIconEngine->iconName(), "selected_indicator"); } TEST_F(ut_DIconProxyEngine, paint) { QImage img(s64, QImage::Format_ARGB32_Premultiplied); { img.fill(Qt::transparent); QPainter p(&img); mIconEngine->paint(&p, QRect({0, 0}, s64), QIcon::Normal, QIcon::On); } QImage img1(s64, QImage::Format_ARGB32_Premultiplied); { img1.fill(Qt::transparent); QPainter p(&img1); ASSERT_TRUE(mIconEngine->m_iconEngine); mIconEngine->m_iconEngine->paint(&p, QRect({0, 0}, s64), QIcon::Normal, QIcon::On); } ASSERT_TRUE(img == img1); } TEST_F(ut_DIconProxyEngine, actualSize) { ASSERT_TRUE(mIconEngine->m_iconEngine); QSize s1 = mIconEngine->actualSize(s64, QIcon::Normal, QIcon::On); QSize s2 = mIconEngine->m_iconEngine->actualSize(s64, QIcon::Normal, QIcon::On); ASSERT_TRUE(s1 == s2); } TEST_F(ut_DIconProxyEngine, pixmap) { ASSERT_TRUE(mIconEngine->m_iconEngine); ASSERT_EQ(mIconEngine->pixmap(s64, QIcon::Normal, QIcon::On).toImage(), mIconEngine->m_iconEngine->pixmap(s64, QIcon::Normal, QIcon::On).toImage()); } TEST_F(ut_DIconProxyEngine, clone) { QScopedPointer clone(mIconEngine->clone()); ASSERT_EQ(clone->key(), mIconEngine->key()); ASSERT_EQ(clone->iconName(), mIconEngine->iconName()); } TEST_F(ut_DIconProxyEngine, read_write) { QByteArray data; { QDataStream out(&data, QIODevice::WriteOnly); mIconEngine->write(out); } QString iconName, themeName; { QDataStream in(&data, QIODevice::ReadOnly); in >> iconName >> themeName; ASSERT_EQ(themeName, mIconEngine->themeName()); ASSERT_EQ(iconName, mIconEngine->iconName()); } { auto engine = new DIconProxyEngine("selected_indicator" ,DIconTheme::DontFallbackToQIconFromTheme); QIcon icon_write(engine); QDataStream out(&data, QIODevice::WriteOnly); out << icon_write; QIcon icon_read; QDataStream in(&data, QIODevice::ReadOnly); in >> icon_read; ASSERT_TRUE(icon_read.data_ptr()->engine); EXPECT_EQ(icon_read.data_ptr()->engine->key(), engine->key()); EXPECT_EQ(icon_read.data_ptr()->engine->iconName(), engine->iconName()); } } TEST_F(ut_DIconProxyEngine, virtual_hook) { ASSERT_TRUE(mIconEngine->m_iconEngine); bool data1 = false, data2 = false; mIconEngine->virtual_hook(QIconEngine::IsNullHook, &data1); mIconEngine->m_iconEngine->virtual_hook(QIconEngine::IsNullHook, &data2); ASSERT_EQ(data1, data2); } ���������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dicontheme.cpp�����������������������������������������������������������0000664�0000000�0000000�00000003210�15226154130�0020364�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "DIconTheme" #include DGUI_USE_NAMESPACE TEST(ut_DIconTheme, builtinIcon) { const QIcon icon1 = DIconTheme::findQIcon("edit"); // 内置的图标主题中必然存在 edit 这个图标 ASSERT_FALSE(icon1.isNull()); ASSERT_TRUE(DIconTheme::isBuiltinIcon(icon1)); const QIcon icon2 = DIconTheme::findQIcon("edit", DIconTheme::IgnoreBuiltinIcons); // icon2 å�ªå�¯èƒ½æ˜¯ä»Žå¤–部找到的图标,ä¸�会与 icon1 相å�Œ ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey()); #ifndef DTK_DISABLE_LIBXDG if (!icon2.isNull()) { ASSERT_TRUE(DIconTheme::isXdgIcon(icon2)); } #endif } TEST(ut_DIconTheme, cachedTheme) { const QIcon icon1 = DIconTheme::cached()->findQIcon("edit"); // 内置的图标主题中必然存在 edit 这个图标 ASSERT_FALSE(icon1.isNull()); ASSERT_TRUE(DIconTheme::isBuiltinIcon(icon1)); const QIcon icon2 = DIconTheme::cached()->findQIcon("edit", DIconTheme::IgnoreBuiltinIcons); // icon2 å�ªå�¯èƒ½æ˜¯ä»Žå¤–部找到的图标,ä¸�会与 icon1 相å�Œ ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey()); #ifndef DTK_DISABLE_LIBXDG if (!icon2.isNull()) { ASSERT_TRUE(DIconTheme::isXdgIcon(icon2)); } #endif const QIcon icon1_cached1 = DIconTheme::cached()->findQIcon("edit"); ASSERT_EQ(icon1_cached1.cacheKey(), icon1.cacheKey()); DIconTheme::cached()->clear(); const QIcon icon1_cached2 = DIconTheme::cached()->findQIcon("edit"); ASSERT_NE(icon1_cached2.cacheKey(), icon1.cacheKey()); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dimagehandler.cpp��������������������������������������������������������0000664�0000000�0000000�00000023176�15226154130�0021046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dimagehandler.h" #include #include #include #include #include DGUI_USE_NAMESPACE class TDImageHandler : public DTest { public: static void SetUpTestCase(); static void TearDownTestCase(); static bool canLoadFreeImage; static bool canLoadLibRaw; static int tmpImageWidth; static int tmpImageHeight; static QString tmpFileName; protected: void SetUp(); void TearDown(); DImageHandler *handler; }; bool TDImageHandler::canLoadFreeImage = false; bool TDImageHandler::canLoadLibRaw = false; int TDImageHandler::tmpImageWidth = 300; int TDImageHandler::tmpImageHeight = 200; QString TDImageHandler::tmpFileName = QString("/tmp/TDImageHandler_shared_test.png"); void TDImageHandler::SetUpTestCase() { // Always false if build without libfreeimage and libraw. #ifndef DTK_DISABLE_EX_IMAGE_FORMAT QLibrary freeImage("freeimage", "3"); if (!freeImage.isLoaded()) { canLoadFreeImage = freeImage.load(); if (canLoadFreeImage) { freeImage.unload(); } } QLibrary libraw("libraw"); if (!libraw.isLoaded()) { canLoadLibRaw = libraw.load(); if (canLoadLibRaw) { freeImage.unload(); } } #endif QImage image(tmpImageWidth, tmpImageHeight, QImage::Format_ARGB32); image.fill(Qt::red); image.save(tmpFileName); } void TDImageHandler::TearDownTestCase() { if (QFile::exists(tmpFileName)) { QFile::remove(tmpFileName); } } void TDImageHandler::SetUp() { handler = new DImageHandler; } void TDImageHandler::TearDown() { delete handler; } TEST_F(TDImageHandler, testSetFileName) { handler->setFileName(tmpFileName); ASSERT_EQ(tmpFileName, handler->fileName()); } TEST_F(TDImageHandler, testReadImage) { handler->setFileName(tmpFileName); QImage image = handler->readImage(); ASSERT_EQ(QSize(tmpImageWidth, tmpImageHeight), image.size()); } TEST_F(TDImageHandler, testThumbnail) { handler->setFileName(tmpFileName); QImage image = handler->thumbnail(QSize(20, 20), Qt::IgnoreAspectRatio); ASSERT_EQ(QSize(20, 20), image.size()); } TEST_F(TDImageHandler, testImageFormat) { handler->setFileName(tmpFileName); ASSERT_EQ(handler->imageFormat(), QString("PNG")); handler->setFileName("/tmp/ut_parsefilesuffix.bmp"); ASSERT_EQ(handler->imageFormat(), QString("BMP")); } TEST_F(TDImageHandler, testImageSize) { ASSERT_EQ(QSize(0, 0), handler->imageSize()); handler->setFileName(tmpFileName); ASSERT_EQ(QSize(tmpImageWidth, tmpImageHeight), handler->imageSize()); } TEST_F(TDImageHandler, testImageSizeWithSVG) { QByteArray svgCode(" "); QString tmpFilePath("/tmp/TDImageHandler_testImageSizeWithSVG.svg"); QFile tmpFile(tmpFilePath); ASSERT_TRUE(tmpFile.open(QFile::WriteOnly)); tmpFile.write(svgCode); tmpFile.close(); handler->setFileName(tmpFilePath); EXPECT_EQ(QSize(300, 300), handler->imageSize()); tmpFile.remove(); } TEST_F(TDImageHandler, testFindAllMetaData) { handler->setFileName(tmpFileName); if (canLoadFreeImage) { ASSERT_FALSE(handler->findAllMetaData().isEmpty()); } else { ASSERT_TRUE(handler->findAllMetaData().isEmpty()); } } TEST_F(TDImageHandler, testClearCache) { ASSERT_TRUE(handler->readImage().isNull()); ASSERT_FALSE(handler->lastError().isEmpty()); handler->clearCache(); ASSERT_TRUE(handler->lastError().isEmpty()); } TEST_F(TDImageHandler, testSaveImage) { QString tmpSaveFileName("/tmp/TDImageHandler_testSaveImage.jpg"); handler->setFileName(tmpFileName); ASSERT_TRUE(handler->saveImage(tmpSaveFileName, "JPG")); ASSERT_TRUE(QFile::exists(tmpSaveFileName)); QFile::remove(tmpSaveFileName); } TEST_F(TDImageHandler, testRotateImage) { QImage image(300, 200, QImage::Format_ARGB32); image.fill(Qt::red); ASSERT_TRUE(handler->rotateImage(image, 90)); ASSERT_EQ(QSize(200, 300), image.size()); } TEST_F(TDImageHandler, testRotateImageFile) { ASSERT_TRUE(handler->rotateImageFile(tmpFileName, 90)); handler->setFileName(tmpFileName); ASSERT_EQ(QSize(tmpImageHeight, tmpImageWidth), handler->imageSize()); ASSERT_TRUE(handler->rotateImageFile(tmpFileName, -90)); handler->clearCache(); ASSERT_EQ(QSize(tmpImageWidth, tmpImageHeight), handler->imageSize()); } TEST_F(TDImageHandler, testIsReadable) { ASSERT_FALSE(handler->isReadable()); handler->setFileName(tmpFileName); ASSERT_TRUE(handler->isReadable()); handler->setFileName("/tmp/ut_testIsReadable.error_suffix"); ASSERT_FALSE(handler->isReadable()); } TEST_F(TDImageHandler, testIsWriteable) { ASSERT_FALSE(handler->isWriteable()); handler->setFileName(tmpFileName); ASSERT_TRUE(handler->isWriteable()); handler->setFileName("/tmp/ut_testIsWriteable.error_suffix"); ASSERT_FALSE(handler->isWriteable()); } TEST_F(TDImageHandler, testIsRotatable) { ASSERT_FALSE(handler->isRotatable()); handler->setFileName(tmpFileName); ASSERT_TRUE(handler->isRotatable()); } TEST_F(TDImageHandler, testSupportFormats) { QStringList supportFormats = DImageHandler::supportFormats(); QByteArrayList qtSupport = QImageReader::supportedImageFormats(); for (const QByteArray &support : qtSupport) { ASSERT_TRUE(supportFormats.contains(QString::fromUtf8(support).toUpper())); } if (canLoadFreeImage) { ASSERT_TRUE(supportFormats.contains("TIF")); ASSERT_TRUE(supportFormats.contains("PBMRAW")); } if (canLoadLibRaw) { ASSERT_TRUE(supportFormats.contains("RAW")); ASSERT_TRUE(supportFormats.contains("MRW")); } } TEST_F(TDImageHandler, testDetectImageFormat) { QString suffix = DImageHandler::detectImageFormat(tmpFileName); ASSERT_EQ(suffix, QString("PNG")); } TEST_F(TDImageHandler, testColorFilter) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::red); ASSERT_NE(image, DImageHandler::oldColorFilter(image)); ASSERT_NE(image, DImageHandler::warmColorFilter(image)); ASSERT_NE(image, DImageHandler::coolColorFilter(image)); ASSERT_NE(image, DImageHandler::grayScaleColorFilter(image)); ASSERT_NE(image, DImageHandler::antiColorFilter(image)); ASSERT_NE(image, DImageHandler::metalColorFilter(image)); } TEST_F(TDImageHandler, testBilateralFilter) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::white); QPainter painter(&image); painter.setPen(QPen(QColor(Qt::black))); painter.drawLine(0, 150, 300, 150); painter.end(); image.setPixelColor(150, 155, QColor(Qt::black)); // The color at point 150,155 will be smoother. image = DImageHandler::bilateralFilter(image, 0.02, 100); ASSERT_NE(image.pixelColor(150, 155), QColor(Qt::black)); } TEST_F(TDImageHandler, testBinaryzation) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(QColor(0xEEEEEE)); QImage scaleImage = DImageHandler::binaryzation(image); ASSERT_EQ(scaleImage.pixelColor(0, 0), QColor(Qt::white)); image.fill(QColor(0x0E0E0E)); scaleImage = DImageHandler::binaryzation(image); ASSERT_EQ(scaleImage.pixelColor(0, 0), QColor(Qt::black)); } TEST_F(TDImageHandler, testGrayScale) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::red); QImage scaleImage = DImageHandler::grayScale(image); QColor color = scaleImage.pixelColor(0, 0); ASSERT_EQ(color.red(), color.blue()); ASSERT_EQ(color.red(), color.green()); } TEST_F(TDImageHandler, testChangeLightAndContrast) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::red); QImage scaleImage = DImageHandler::changeLightAndContrast(image, 0, 0); ASSERT_EQ(scaleImage.pixelColor(0, 0), QColor(Qt::black)); } TEST_F(TDImageHandler, testChangeBrightness) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::gray); QImage scaleImage = DImageHandler::changeBrightness(image, 100); ASSERT_GT(scaleImage.pixel(0, 0), image.pixel(0, 0)); } TEST_F(TDImageHandler, testChangeTransparency) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::gray); QImage scaleImage = DImageHandler::changeTransparency(image, 100); ASSERT_EQ(scaleImage.pixelColor(0, 0).alpha(), 100); } TEST_F(TDImageHandler, testChangeStauration) { QImage image(300, 300, QImage::Format_ARGB32); image.fill(Qt::gray); int oldSaturatuin = image.pixelColor(0, 0).saturation(); QImage scaleImage = DImageHandler::changeStauration(image, oldSaturatuin + 100); ASSERT_GT(scaleImage.pixelColor(0, 0).saturation(), oldSaturatuin); } TEST_F(TDImageHandler, testFlip) { QColor oldColor(Qt::red); QColor newColor(Qt::blue); QImage image(300, 300, QImage::Format_ARGB32); image.fill(oldColor); image.setPixelColor(0, 0, newColor); QImage horizontalImage = DImageHandler::flipHorizontal(image); ASSERT_NE(image, horizontalImage); ASSERT_EQ(image, horizontalImage.mirrored(true, false)); QImage verticalImage = DImageHandler::flipVertical(image); ASSERT_NE(image, verticalImage); ASSERT_EQ(image, verticalImage.mirrored(false, true)); } TEST_F(TDImageHandler, testReplacePointColor) { QColor oldColor(Qt::red); QColor newColor(Qt::blue); QImage image(300, 300, QImage::Format_ARGB32); image.fill(oldColor); QImage replaceImage = DImageHandler::replacePointColor(image, oldColor, newColor); ASSERT_FALSE(replaceImage.isNull()); ASSERT_EQ(replaceImage.pixelColor(0, 0), newColor); }��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dnativesettings.cpp������������������������������������������������������0000664�0000000�0000000�00000003611�15226154130�0021465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #define private public #include "dnativesettings.h" #undef private #include #include #include #include DGUI_USE_NAMESPACE DCORE_USE_NAMESPACE class GTEST_API_ ut_DNativeSettings : public testing::Test { public: static void SetUpTestSuite(); static void TearDownTestSuite(); static DNativeSettings *settings; }; DNativeSettings *ut_DNativeSettings::settings = nullptr; void ut_DNativeSettings::SetUpTestSuite() { settings = new DNativeSettings(0, "ut_dnativesettings"); } void ut_DNativeSettings::TearDownTestSuite() { delete settings; } TEST_F(ut_DNativeSettings, allKeys) { ASSERT_EQ(settings->allKeys(), QByteArrayList({"Net/ThemeName", "Qt/ActiveColor", "Net/IconThemeName", "DTK/WindowRadius"})); } TEST_F(ut_DNativeSettings, valid) { ASSERT_TRUE(settings->isValid()); } TEST_F(ut_DNativeSettings, get_set) { ASSERT_EQ(settings->getSetting("Net/ThemeName").toString(), "deepin"); settings->setSetting("Net/ThemeName", "deepin-themeName"); ASSERT_EQ(settings->getSetting("Net/ThemeName").toString(), "deepin-themeName"); } TEST_F(ut_DNativeSettings, signal) { { QSignalSpy spy(settings, &DNativeSettings::propertyChanged); settings->setSetting("Qt/ActiveColor", QColor(Qt::green)); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); } { QSignalSpy spy(settings, &DNativeSettings::allKeysChanged); settings->__setAllKeys({"Net/ThemeName", "Qt/ActiveColor"}); ASSERT_TRUE(QTest::qWaitFor([&spy](){ return spy.count() > 0; }, 1000)); } } �����������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dpalette.cpp�������������������������������������������������������������0000664�0000000�0000000�00000007314�15226154130�0020060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include "test.h" #include "dpalette.h" DGUI_USE_NAMESPACE class TDPalette : public DTestWithParam { protected: void SetUp(); void testAttribute(int cgCount, int ctCount); DPalette palette; }; INSTANTIATE_TEST_CASE_P(DPalette, TDPalette, ::testing::Range(0, 12)); void TDPalette::SetUp() { DGuiApplicationHelper::instance()->generatePalette(palette, DGuiApplicationHelper::LightType); } TEST_P(TDPalette, testFunction) { // 测试属性设置和属性获å�–函数能够正常调用且返回正确数值 enum {ColorGroupCount = 6}; int ctGroup = GetParam(); for (int i = 0; i < ColorGroupCount; ++i) { QColor color = palette.color(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup)); ASSERT_TRUE(color.isValid()); QBrush brush = palette.brush(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup)); ASSERT_TRUE(brush.color().isValid()); color = palette.color(DPalette::ColorType(ctGroup)); ASSERT_TRUE(color.isValid()); palette.setColor(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup), Qt::black); color = palette.color(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup)); ASSERT_EQ(color, Qt::black); palette.setBrush(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup), QBrush(Qt::blue)); brush = palette.brush(DPalette::ColorGroup(i), DPalette::ColorType(ctGroup)); ASSERT_EQ(brush.color(), Qt::blue); } palette.setColor(DPalette::ColorType(ctGroup), Qt::white); QColor color = palette.color(DPalette::ColorType(ctGroup)); ASSERT_EQ(color, Qt::white); palette.setBrush(DPalette::ColorType(ctGroup), QBrush(Qt::blue)); QBrush brush = palette.brush(DPalette::ColorType(ctGroup)); ASSERT_EQ(brush.color(), Qt::blue); } TEST_F(TDPalette, testColorFunction) { // 测试默认的调色æ�¿é¢œè‰²æœ‰æ•ˆ QBrush brush = palette.itemBackground(); ASSERT_TRUE(brush.color().isValid()); brush = palette.textTitle(); ASSERT_TRUE(brush.color().isValid()); brush = palette.textTips(); ASSERT_TRUE(brush.color().isValid()); brush = palette.textWarning(); ASSERT_TRUE(brush.color().isValid()); brush = palette.textLively(); ASSERT_TRUE(brush.color().isValid()); brush = palette.lightLively(); ASSERT_TRUE(brush.color().isValid()); brush = palette.darkLively(); ASSERT_TRUE(brush.color().isValid()); brush = palette.frameBorder(); ASSERT_TRUE(brush.color().isValid()); brush = palette.placeholderText(); ASSERT_TRUE(brush.color().isValid()); brush = palette.frameShadowBorder(); ASSERT_TRUE(brush.color().isValid()); #ifndef QT_NO_DATASTREAM QByteArray inArray; QDataStream in(&inArray, QIODevice::WriteOnly); // in.setVersion(QDataStream::Qt_5_11); // 直接调用左移è¿�算符会出现二异性 先直接执行一次生æˆ�结果 in << static_cast(palette); for (int i = 0; i < DPalette::NColorGroups; ++i) { for (int j = 0; j < DPalette::NColorTypes; ++j) { in << palette.brush(DPalette::ColorGroup(i), DPalette::ColorType(j)); } } ASSERT_FALSE(inArray.isEmpty()); DPalette tp; QDataStream out(&inArray, QIODevice::ReadOnly); out >> tp; ASSERT_EQ(palette, tp); #endif #ifndef QT_NO_DEBUG_STREAM QByteArray debugData; QBuffer debugBuffer(&debugData); ASSERT_TRUE(debugBuffer.open(QIODevice::WriteOnly)); QDebug(&debugBuffer) << palette; debugBuffer.close(); EXPECT_FALSE(debugData.isEmpty()); #endif } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dplatformhandle.cpp������������������������������������������������������0000664�0000000�0000000�00000025703�15226154130�0021424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include #include "dplatformhandle.h" #include "dwindowmanagerhelper.h" #define DXCB_PLUGIN_KEY "dxcb" #define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb" #define SETWMWALLPAPERPARAMETER "_d_setWmWallpaperParameter" #define CLIENTLEADER "_d_clientLeader" #define WINDOWRADIUS "_d_windowRadius" #define BORDERWIDTH "_d_borderWidth" #define BORDRCOLOR "_d_borderColor" #define SHADOWRADIUS "_d_shadowRadius" #define SHADOWOFFSET "_d_shadowOffset" #define SHADOWCOLOR "_d_shadowColor" #define CLIPPATH "_d_clipPath" #define FRAMEMASK "_d_frameMask" #define FRAMEMARGINS "_d_frameMargins" #define TRANSLUCENTBACKGROUND "_d_translucentBackground" #define ENABLESYSTEMRESIZE "_d_enableSystemResize" #define ENABLESYSTEMMOVE "_d_enableSystemMove" #define ENABLEBLURWINDOW "_d_enableBlurWindow" #define AUTOINPUTMASKBYCLIPPATH "_d_autoINPUTMASKBYCLIPPATH" #define REALWINDOWID "_d_real_content_window" DGUI_USE_NAMESPACE class TDPlatformHandle : public testing::Test { protected: void SetUp(); void TearDown(); QWindow *window; DPlatformHandle *pHandle; }; void TDPlatformHandle::SetUp() { window = new QWindow; window->create(); pHandle = new DPlatformHandle(window); ASSERT_TRUE(pHandle); } void TDPlatformHandle::TearDown() { delete window; delete pHandle; } TEST_F(TDPlatformHandle, testFunction) { if (!pHandle || qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; qDebug() << "pluginVersion is " << DPlatformHandle::pluginVersion(); EXPECT_EQ(DPlatformHandle::isDXcbPlatform(), (qApp->platformName() == DXCB_PLUGIN_KEY || qApp->property(DXCB_PLUGIN_SYMBOLIC_PROPERTY).toBool())); (DPlatformHandle::enableDXcbForWindow(window)); (DPlatformHandle::enableDXcbForWindow(window, true)); qInfo() << "TDPlatformHandle(isEnabledDXcb):" << DPlatformHandle::isEnabledDXcb(window); if (DPlatformHandle::isEnabledDXcb(window)) { EXPECT_TRUE(DPlatformHandle::setEnabledNoTitlebarForWindow(window, true)); EXPECT_TRUE(DPlatformHandle::setEnabledNoTitlebarForWindow(window, false)); } QVector wmAreaVector; wmAreaVector << dMakeWMBlurArea(0, 0, 20, 20, 4, 4); if (DWindowManagerHelper::instance()->hasBlurWindow()) { EXPECT_TRUE(pHandle->setWindowBlurAreaByWM(window, wmAreaVector)); QPainterPath pPath; pPath.addRect({0, 0, 20, 20}); EXPECT_TRUE(pHandle->setWindowBlurAreaByWM(window, {pPath})); EXPECT_TRUE(pHandle->setWindowBlurAreaByWM(wmAreaVector)); EXPECT_TRUE(pHandle->setWindowBlurAreaByWM({pPath})); } if (qApp->platformFunction(SETWMWALLPAPERPARAMETER)) { EXPECT_TRUE(pHandle->setWindowWallpaperParaByWM(window, {0, 0, 20, 20}, DPlatformHandle::FollowScreen, DPlatformHandle::PreserveAspectFit)); } else { EXPECT_FALSE(pHandle->setWindowWallpaperParaByWM(window, {0, 0, 20, 20}, DPlatformHandle::FollowScreen, DPlatformHandle::PreserveAspectFit)); } if (qApp->platformFunction(CLIENTLEADER)) { ASSERT_TRUE(DPlatformHandle::windowLeader()); } else { ASSERT_FALSE(DPlatformHandle::windowLeader()); } DPlatformHandle::setDisableWindowOverrideCursor(window, true); QVariant windowRadius = window->property(WINDOWRADIUS); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (windowRadius.isValid() && windowRadius.canConvert()) { #else if (windowRadius.isValid() && windowRadius.canConvert(QVariant::Int)) { #endif ASSERT_EQ(pHandle->windowRadius(), windowRadius.toInt()); } QVariant borderWidth = window->property(BORDERWIDTH); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (borderWidth.isValid() && borderWidth.canConvert()) { #else if (borderWidth.isValid() && borderWidth.canConvert(QVariant::Int)) { #endif ASSERT_EQ(pHandle->borderWidth(), borderWidth.toInt()); } else { ASSERT_EQ(pHandle->borderWidth(), 0); } QVariant borderColor = window->property(BORDRCOLOR); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (borderColor.isValid() && borderColor.canConvert()) { #else if (borderColor.isValid() && borderColor.canConvert(QVariant::Color)) { #endif ASSERT_EQ(pHandle->borderColor(), borderColor.value()); } else { ASSERT_FALSE(pHandle->borderColor().isValid()); } QVariant shadowRadius = window->property(SHADOWRADIUS); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (shadowRadius.isValid() && shadowRadius.canConvert()) { #else if (shadowRadius.isValid() && shadowRadius.canConvert(QVariant::Int)) { #endif ASSERT_EQ(pHandle->shadowRadius(), shadowRadius.toInt()); } else { ASSERT_FALSE(pHandle->borderColor().isValid()); } QVariant shadowOffset = window->property(SHADOWOFFSET); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (shadowOffset.isValid() && shadowOffset.canConvert()) { #else if (shadowOffset.isValid() && shadowOffset.canConvert(QVariant::Point)) { #endif ASSERT_EQ(pHandle->shadowOffset(), shadowOffset.value()); } else { ASSERT_TRUE(pHandle->shadowOffset().isNull()); } QVariant shadowColor = window->property(SHADOWCOLOR); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (shadowColor.isValid() && shadowColor.canConvert()) { #else if (shadowColor.isValid() && shadowColor.canConvert(QVariant::Color)) { #endif ASSERT_EQ(pHandle->shadowColor(), shadowColor.value()); } else { ASSERT_FALSE(pHandle->shadowColor().isValid()); } QVariant clipPath = window->property(CLIPPATH); if (clipPath.isValid() && !clipPath.value().isEmpty()) { ASSERT_EQ(pHandle->clipPath(), clipPath.value()); } else { ASSERT_TRUE(pHandle->clipPath().isEmpty()); } QVariant frameMask = window->property(FRAMEMASK); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (frameMask.isValid() && frameMask.canConvert()) { #else if (frameMask.isValid() && frameMask.canConvert(QVariant::Region)) { #endif ASSERT_EQ(pHandle->frameMask(), frameMask.value()); } else { ASSERT_TRUE(pHandle->frameMask().isEmpty()); } QVariant frameMargins = window->property(FRAMEMARGINS); if (frameMargins.isValid() && !frameMargins.value().isNull()) { ASSERT_EQ(pHandle->frameMargins(), frameMargins.value()); } else { ASSERT_TRUE(pHandle->frameMargins().isNull()); } QVariant translucentBackground = window->property(TRANSLUCENTBACKGROUND); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (translucentBackground.isValid() && translucentBackground.canConvert()) { #else if (translucentBackground.isValid() && translucentBackground.canConvert(QVariant::Bool)) { #endif ASSERT_EQ(pHandle->translucentBackground(), translucentBackground.toBool()); } else { ASSERT_FALSE(pHandle->translucentBackground()); } QVariant enableSystemResize = window->property(ENABLESYSTEMRESIZE); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (enableSystemResize.isValid() && enableSystemResize.canConvert()) { #else if (enableSystemResize.isValid() && enableSystemResize.canConvert(QVariant::Bool)) { #endif ASSERT_EQ(pHandle->enableSystemResize(), enableSystemResize.toBool()); } else { ASSERT_FALSE(pHandle->enableSystemResize()); } QVariant enableSystemMove = window->property(ENABLESYSTEMMOVE); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (enableSystemMove.isValid() && enableSystemMove.canConvert()) { #else if (enableSystemMove.isValid() && enableSystemMove.canConvert(QVariant::Bool)) { #endif ASSERT_EQ(pHandle->enableSystemMove(), enableSystemMove.toBool()); } else { ASSERT_FALSE(pHandle->enableSystemMove()); } QVariant enableBlurWindow = window->property(ENABLEBLURWINDOW); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (enableBlurWindow.isValid() && enableBlurWindow.canConvert()) { #else if (enableBlurWindow.isValid() && enableBlurWindow.canConvert(QVariant::Bool)) { #endif ASSERT_EQ(pHandle->enableBlurWindow(), enableBlurWindow.toBool()); } else { ASSERT_FALSE(pHandle->enableBlurWindow()); } QVariant autoInputMaskByClipPath = window->property(AUTOINPUTMASKBYCLIPPATH); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert()) { #else if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert(QVariant::Bool)) { #endif ASSERT_EQ(pHandle->autoInputMaskByClipPath(), autoInputMaskByClipPath.toBool()); } else { ASSERT_FALSE(pHandle->autoInputMaskByClipPath()); } QVariant realWindowId = window->property(REALWINDOWID); if (enableBlurWindow.isValid() && enableBlurWindow.value() != 0) { ASSERT_EQ(pHandle->realWindowId(), enableBlurWindow.value()); } else { ASSERT_FALSE(pHandle->realWindowId()); } } TEST_F(TDPlatformHandle, testSlots) { enum { TESTBORDERWIDTH = 4, TESTOFFSET = 6, TESTRADIUS = 8 }; if (pHandle) { pHandle->setWindowRadius(TESTRADIUS); ASSERT_EQ(pHandle->windowRadius(), TESTRADIUS); pHandle->setBorderWidth(TESTBORDERWIDTH); ASSERT_EQ(pHandle->borderWidth(), TESTBORDERWIDTH); pHandle->setBorderColor(Qt::black); ASSERT_EQ(pHandle->borderColor(), Qt::black); pHandle->setShadowRadius(TESTRADIUS); ASSERT_EQ(pHandle->shadowRadius(), TESTRADIUS); pHandle->setShadowOffset({TESTOFFSET, TESTOFFSET}); ASSERT_EQ(pHandle->shadowOffset(), QPoint(TESTOFFSET, TESTOFFSET)); pHandle->setShadowColor(Qt::blue); ASSERT_EQ(pHandle->shadowColor(), Qt::blue); QPainterPath pPath; pPath.addRect({0, 0, 20, 20}); pHandle->setClipPath(pPath); ASSERT_EQ(pHandle->clipPath(), pPath); pHandle->setFrameMask(QRegion(0, 0, 10, 10)); ASSERT_EQ(pHandle->frameMask(), QRegion(0, 0, 10, 10)); pHandle->setTranslucentBackground(true); ASSERT_TRUE(pHandle->translucentBackground()); pHandle->setEnableSystemResize(true); ASSERT_TRUE(pHandle->enableSystemResize()); pHandle->setEnableSystemMove(true); ASSERT_TRUE(pHandle->enableSystemMove()); pHandle->setEnableBlurWindow(true); ASSERT_TRUE(pHandle->enableBlurWindow()); pHandle->setAutoInputMaskByClipPath(true); ASSERT_TRUE(pHandle->autoInputMaskByClipPath()); } } TEST_F(TDPlatformHandle, wmAreaDebug) { DPlatformHandle::WMBlurArea area = dMakeWMBlurArea(0, 0, 20, 20); QByteArray data; QBuffer buf(&data); ASSERT_TRUE(buf.open(QIODevice::WriteOnly)); QDebug tDebug(&buf); tDebug << area; buf.close(); ASSERT_FALSE(data.isEmpty()); } �������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dplatformtheme.cpp�������������������������������������������������������0000664�0000000�0000000�00000014073�15226154130�0021271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include "dguiapplicationhelper.h" #define private public #include "dplatformtheme.h" #include "dplatformtheme_p.h" #undef private DGUI_USE_NAMESPACE class TDPlatformTheme : public testing::Test { protected: void SetUp(); void TearDown(); QWidget *widget; DPlatformTheme *theme; DPlatformThemePrivate *theme_d; }; void TDPlatformTheme::SetUp() { widget = new QWidget; widget->createWinId(); //widget->show(); ASSERT_TRUE(widget->windowHandle()); theme = new DPlatformTheme(quint32(widget->windowHandle()->winId()), widget); theme_d = theme->d_func(); } void TDPlatformTheme::TearDown() { delete widget; } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) TEST_F(TDPlatformTheme, testFunction) { ASSERT_TRUE(theme_d->theme); ASSERT_EQ(theme->parentTheme(), theme_d->parent); ASSERT_TRUE(theme->isValid()); DPalette tPalette = theme->palette(); ASSERT_EQ(theme->fetchPalette(tPalette), tPalette); } #endif #define TEST_THEME_NAME(TYPE) \ QByteArrayLiteral("Test_Name_About_").append(TYPE) #define ASSERT_EQ_BY_VALUE(SetFunc,Func,Param) \ theme->SetFunc(Param); \ ASSERT_EQ(theme->Func(),Param); \ #define ASSERT_EQ_COLOR(SetFunc,Func,Param) \ ASSERT_EQ_BY_VALUE(SetFunc,Func,Param); \ #define ASSERT_EQ_BY_NAME(SetFunc,Func,Param) \ theme->SetFunc(TEST_THEME_NAME(Param)); \ ASSERT_EQ(theme->Func(),TEST_THEME_NAME(Param)); TEST_F(TDPlatformTheme, testSetFunction) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; if (!theme->isValid()) { qDebug() << "PlatformTheme is not valid"; return; } enum { TEST_COLOR = Qt::blue, TEST_DATA = 50 }; ASSERT_EQ_BY_VALUE(setCursorBlinkTime, cursorBlinkTime, TEST_DATA); ASSERT_EQ_BY_VALUE(setCursorBlinkTimeout, cursorBlinkTimeout, TEST_DATA); ASSERT_EQ_BY_VALUE(setCursorBlink, cursorBlink, true) ASSERT_EQ_BY_VALUE(setDoubleClickDistance, doubleClickDistance, TEST_DATA); ASSERT_EQ_BY_VALUE(setDoubleClickTime, doubleClickTime, TEST_DATA) ASSERT_EQ_BY_VALUE(setDndDragThreshold, dndDragThreshold, TEST_DATA); ASSERT_EQ_BY_NAME(setThemeName, themeName, "Theme"); ASSERT_EQ_BY_NAME(setIconThemeName, iconThemeName, "Icon"); ASSERT_EQ_BY_NAME(setSoundThemeName, soundThemeName, "Sound"); ASSERT_EQ_BY_NAME(setFontName, fontName, "Font"); ASSERT_EQ_BY_NAME(setMonoFontName, monoFontName, "MonoFont"); ASSERT_EQ_BY_NAME(setGtkFontName, gtkFontName, "GtkFont"); ASSERT_EQ_BY_VALUE(setFontPointSize, fontPointSize, TEST_DATA); ASSERT_EQ_BY_VALUE(setActiveColor, activeColor, TEST_COLOR); #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) ASSERT_EQ_COLOR(setWindow, window, TEST_COLOR); ASSERT_EQ_BY_VALUE(setWindowText, windowText, TEST_COLOR); ASSERT_EQ_BY_VALUE(setBase, base, TEST_COLOR); ASSERT_EQ_BY_VALUE(setAlternateBase, alternateBase, TEST_COLOR); ASSERT_EQ_BY_VALUE(setToolTipBase, toolTipBase, TEST_COLOR); ASSERT_EQ_BY_VALUE(setToolTipText, toolTipText, TEST_COLOR); ASSERT_EQ_BY_VALUE(setText, text, TEST_COLOR); ASSERT_EQ_BY_VALUE(setButton, button, TEST_COLOR); ASSERT_EQ_BY_VALUE(setButtonText, buttonText, TEST_COLOR); ASSERT_EQ_BY_VALUE(setBrightText, brightText, TEST_COLOR); ASSERT_EQ_BY_VALUE(setLight, light, TEST_COLOR); ASSERT_EQ_BY_VALUE(setMidlight, midlight, TEST_COLOR); ASSERT_EQ_BY_VALUE(setDark, dark, TEST_COLOR); ASSERT_EQ_BY_VALUE(setMid, mid, TEST_COLOR); ASSERT_EQ_BY_VALUE(setShadow, shadow, TEST_COLOR); ASSERT_EQ_BY_VALUE(setHighlight, highlight, TEST_COLOR); ASSERT_EQ_BY_VALUE(setLink, link, TEST_COLOR); ASSERT_EQ_BY_VALUE(setLinkVisited, linkVisited, TEST_COLOR); ASSERT_EQ_BY_VALUE(setItemBackground, itemBackground, TEST_COLOR); ASSERT_EQ_BY_VALUE(setTextTitle, textTitle, TEST_COLOR); ASSERT_EQ_BY_VALUE(setTextTips, textTips, TEST_COLOR); ASSERT_EQ_BY_VALUE(setTextWarning, textWarning, TEST_COLOR); ASSERT_EQ_BY_VALUE(setTextLively, textLively, TEST_COLOR); ASSERT_EQ_BY_VALUE(setLightLively, lightLively, TEST_COLOR); ASSERT_EQ_BY_VALUE(setDarkLively, darkLively, TEST_COLOR); ASSERT_EQ_BY_VALUE(setFrameBorder, frameBorder, TEST_COLOR); ASSERT_EQ_BY_VALUE(setWindowRadius, windowRadius, TEST_DATA / 10); #endif } #if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) TEST_F(TDPlatformTheme, palette) { DPalette pa = theme->palette(); ASSERT_EQ(theme->window(), pa.window().color()); ASSERT_EQ(theme->windowText(), pa.windowText().color()); ASSERT_EQ(theme->base(), pa.base().color()); ASSERT_EQ(theme->alternateBase(), pa.alternateBase().color()); ASSERT_EQ(theme->toolTipBase(), pa.toolTipBase().color()); ASSERT_EQ(theme->toolTipText(), pa.toolTipText().color()); ASSERT_EQ(theme->text(), pa.text().color()); ASSERT_EQ(theme->button(), pa.button().color()); ASSERT_EQ(theme->buttonText(), pa.buttonText().color()); ASSERT_EQ(theme->brightText(), pa.brightText().color()); ASSERT_EQ(theme->light(), pa.light().color()); ASSERT_EQ(theme->midlight(), pa.midlight().color()); ASSERT_EQ(theme->dark(), pa.dark().color()); ASSERT_EQ(theme->mid(), pa.mid().color()); ASSERT_EQ(theme->shadow(), pa.shadow().color()); ASSERT_EQ(theme->highlight(), pa.highlight().color()); ASSERT_EQ(theme->highlightedText(), pa.highlightedText().color()); ASSERT_EQ(theme->link(), pa.link().color()); ASSERT_EQ(theme->linkVisited(), pa.linkVisited().color()); ASSERT_EQ(theme->itemBackground(), pa.itemBackground().color()); ASSERT_EQ(theme->textTitle(), pa.textTitle().color()); ASSERT_EQ(theme->textTips(), pa.textTips().color()); ASSERT_EQ(theme->textWarning(), pa.textWarning().color()); ASSERT_EQ(theme->textLively(), pa.textLively().color()); ASSERT_EQ(theme->lightLively(), pa.lightLively().color()); ASSERT_EQ(theme->darkLively(), pa.darkLively().color()); ASSERT_EQ(theme->frameBorder(), pa.frameBorder().color()); } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dregionmonitor.cpp�������������������������������������������������������0000664�0000000�0000000�00000014125�15226154130�0021313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dregionmonitor.h" #include "private/dregionmonitor_p.h" #include #include #include DGUI_BEGIN_NAMESPACE class TDRegionMonitor : public DTest { protected: virtual void SetUp() { regionMonitor = new DRegionMonitor(nullptr); } virtual void TearDown() { delete regionMonitor; } DRegionMonitor *regionMonitor = nullptr; }; TEST_F(TDRegionMonitor, registerRegion) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; regionMonitor->registerRegion(); ASSERT_TRUE(regionMonitor->registered()); } TEST_F(TDRegionMonitor, registered) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_FALSE(regionMonitor->registered()); } TEST_F(TDRegionMonitor, watchedRegion) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_EQ(regionMonitor->watchedRegion(), QRegion()); } TEST_F(TDRegionMonitor, coordinateType) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_EQ(regionMonitor->coordinateType(), DRegionMonitor::ScaleRatio); } TEST_F(TDRegionMonitor, registerRegionArg) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_EQ(regionMonitor->watchedRegion(), QRegion()); QRegion r(0, 0, 600, 400); regionMonitor->registerRegion(r); ASSERT_EQ(regionMonitor->watchedRegion(), r); } TEST_F(TDRegionMonitor, unregisterRegion) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; regionMonitor->registerRegion(); ASSERT_TRUE(regionMonitor->registered()); regionMonitor->unregisterRegion(); ASSERT_FALSE(regionMonitor->registered()); } TEST_F(TDRegionMonitor, setWatchedRegion) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_EQ(regionMonitor->watchedRegion(), QRegion()); QRegion r(0, 0, 600, 400); regionMonitor->setWatchedRegion(r); ASSERT_EQ(regionMonitor->watchedRegion(), r); } TEST_F(TDRegionMonitor, setCoordinateType) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_EQ(regionMonitor->coordinateType(), DRegionMonitor::ScaleRatio); regionMonitor->setCoordinateType(DRegionMonitor::Original); ASSERT_EQ(regionMonitor->coordinateType(), DRegionMonitor::Original); } TEST_F(TDRegionMonitor, registerFlags) { #ifndef QT_NO_DEBUG_STREAM enum { TestRegionFlag = (DRegionMonitor::Motion | DRegionMonitor::Button) }; regionMonitor->setRegisterFlags(DRegionMonitor::RegisterdFlag(TestRegionFlag)); ASSERT_EQ(regionMonitor->registerFlags(), TestRegionFlag); #endif } TEST_F(TDRegionMonitor, privateFunctions) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; DRegionMonitorPrivate *region_d = regionMonitor->d_func(); ASSERT_TRUE(region_d); regionMonitor->registerRegion(); ASSERT_TRUE(region_d->registered()); region_d->registerMonitorRegion(); ASSERT_FALSE(region_d->registerKey.isEmpty()); region_d->watchedRegion = {0, 0, 30, 30}; region_d->registerMonitorRegion(); ASSERT_FALSE(region_d->registerKey.isEmpty()); region_d->unregisterMonitorRegion(); ASSERT_TRUE(region_d->registerKey.isEmpty()); enum { TestFlag = 1 | 2, TestPos = 20 }; const QString testKey = "Key_Enter"; QSignalSpy btnPressSpy(regionMonitor, SIGNAL(buttonPress(const QPoint &, const int))); region_d->_q_ButtonPress(TestFlag, TestPos, TestPos, region_d->registerKey); ASSERT_EQ(btnPressSpy.count(), 1); auto pressArguments = btnPressSpy.takeFirst(); ASSERT_EQ(pressArguments.at(0).toPoint(), region_d->deviceScaledCoordinate({TestPos, TestPos}, qApp->devicePixelRatio())); ASSERT_EQ(pressArguments.at(1).toInt(), TestFlag); QSignalSpy btnreleaseSpy(regionMonitor, SIGNAL(buttonRelease(const QPoint &, const int))); region_d->_q_ButtonRelease(TestFlag, TestPos, TestPos, region_d->registerKey); ASSERT_EQ(btnreleaseSpy.count(), 1); auto releaseArguments = btnreleaseSpy.takeFirst(); ASSERT_EQ(releaseArguments.at(0).toPoint(), region_d->deviceScaledCoordinate({TestPos, TestPos}, qApp->devicePixelRatio())); ASSERT_EQ(releaseArguments.at(1).toInt(), TestFlag); QSignalSpy cursorMoveSpy(regionMonitor, SIGNAL(cursorMove(const QPoint &))); region_d->_q_CursorMove(TestPos, TestPos, region_d->registerKey); ASSERT_EQ(cursorMoveSpy.count(), 1); auto curMoveArguments = cursorMoveSpy.takeFirst(); ASSERT_EQ(curMoveArguments.at(0).toPoint(), region_d->deviceScaledCoordinate({TestPos, TestPos}, qApp->devicePixelRatio())); QSignalSpy cursorEnterSpy(regionMonitor, SIGNAL(cursorEnter(const QPoint &))); region_d->_q_CursorEnter(TestPos, TestPos, region_d->registerKey); ASSERT_EQ(cursorEnterSpy.count(), 1); auto curEnterArguments = cursorEnterSpy.takeFirst(); ASSERT_EQ(curEnterArguments.at(0).toPoint(), region_d->deviceScaledCoordinate({TestPos, TestPos}, qApp->devicePixelRatio())); QSignalSpy cursorLeaveSpy(regionMonitor, SIGNAL(cursorLeave(const QPoint &))); region_d->_q_CursorLeave(TestPos, TestPos, region_d->registerKey); ASSERT_EQ(cursorLeaveSpy.count(), 1); auto curLeaveArguments = cursorLeaveSpy.takeFirst(); ASSERT_EQ(curLeaveArguments.at(0).toPoint(), region_d->deviceScaledCoordinate({TestPos, TestPos}, qApp->devicePixelRatio())); QSignalSpy keyPressSpy(regionMonitor, SIGNAL(keyPress(const QString &))); region_d->_q_KeyPress(testKey, TestPos, TestPos, region_d->registerKey); ASSERT_EQ(keyPressSpy.count(), 1); auto keyPressArguments = keyPressSpy.takeFirst(); ASSERT_EQ(keyPressArguments.at(0).toString(), testKey); QSignalSpy keyReleaseSpy(regionMonitor, SIGNAL(keyRelease(const QString &))); region_d->_q_KeyRelease(testKey, TestPos, TestPos, region_d->registerKey); ASSERT_EQ(keyReleaseSpy.count(), 1); auto keyReleaseArguments = keyReleaseSpy.takeFirst(); ASSERT_EQ(keyReleaseArguments.at(0).toString(), testKey); } DGUI_END_NAMESPACE �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dsvgrenderer.cpp���������������������������������������������������������0000664�0000000�0000000�00000006200�15226154130�0020741�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dsvgrenderer.h" #include "test.h" #include #include #include #include #include DGUI_USE_NAMESPACE TEST(ut_DSvgRenderer, testInit) { DSvgRenderer svg_1; DSvgRenderer svg_2(QStringLiteral(":/images/logo_icon.svg")); ASSERT_FALSE(svg_1.isValid()); ASSERT_TRUE(svg_2.isValid()); QFile file(":/images/logo_icon.svg"); if (!file.open(QFile::ReadOnly)) return; QByteArray data = file.readAll(); DSvgRenderer svg_3(data); ASSERT_TRUE(svg_3.isValid()); } class TDSvgRenderer : public DTest { protected: void SetUp(); void TearDown(); DSvgRenderer *renderer; bool canLoad; }; void TDSvgRenderer::SetUp() { QLibrary rsvg("rsvg-2", "2"); if (!rsvg.isLoaded()) { canLoad = rsvg.load(); if (canLoad) { rsvg.unload(); } } renderer = new DSvgRenderer; } void TDSvgRenderer::TearDown() { delete renderer; } TEST_F(TDSvgRenderer, testLoad) { if (!canLoad) return; ASSERT_TRUE(renderer->load(QStringLiteral(":/images/logo_icon.svg"))); ASSERT_TRUE(renderer->isValid()); ASSERT_FALSE(renderer->defaultSize().isEmpty()); ASSERT_FALSE(renderer->viewBox().isEmpty()); ASSERT_FALSE(renderer->viewBoxF().isEmpty()); } static bool testPixmapHasData(const QPixmap &pixmap) { QImage image = pixmap.toImage(); image.reinterpretAsFormat(QImage::Format_RGB32); const QRgb *bits = reinterpret_cast(image.constBits()); const QRgb *end = bits + qulonglong(image.sizeInBytes()) / sizeof(QRgb); return !std::all_of(bits, end, [](QRgb r) { return r == QColor(Qt::green).rgb(); }); } #define TestRenderID QStringLiteral("#tittlebar") #define TestRenderID_NotExist QStringLiteral("#TestRsvg_notexist") TEST_F(TDSvgRenderer, testRender) { if (!canLoad) return; enum { TestPixmapSize = 16 }; ASSERT_TRUE(renderer->load(QString(":/images/logo_icon.svg"))); QPixmap tPixmap(QSize(TestPixmapSize, TestPixmapSize)); tPixmap.fill(Qt::green); QPainter tPainter(&tPixmap); renderer->render(&tPainter); ASSERT_TRUE(testPixmapHasData(tPixmap)); tPixmap.fill(Qt::green); ASSERT_FALSE(testPixmapHasData(tPixmap)); renderer->render(&tPainter, TestRenderID); ASSERT_TRUE(testPixmapHasData(tPixmap)); tPixmap.fill(Qt::green); ASSERT_FALSE(testPixmapHasData(tPixmap)); ASSERT_TRUE(renderer->elementExists(TestRenderID)); ASSERT_FALSE(renderer->elementExists(TestRenderID_NotExist)); ASSERT_FALSE(renderer->boundsOnElement(TestRenderID).isEmpty()); ASSERT_TRUE(renderer->boundsOnElement(TestRenderID_NotExist).isEmpty()); renderer->render(&tPainter, {0, 0, TestPixmapSize, TestPixmapSize}); ASSERT_TRUE(testPixmapHasData(tPixmap)); tPixmap.fill(Qt::green); ASSERT_FALSE(testPixmapHasData(tPixmap)); ASSERT_FALSE(renderer->toImage({TestPixmapSize, TestPixmapSize}).isNull()); ASSERT_FALSE(renderer->toImage({TestPixmapSize, TestPixmapSize}, TestRenderID).isNull()); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dtaskbarcontrol.cpp������������������������������������������������������0000664�0000000�0000000�00000003241�15226154130�0021445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dtaskbarcontrol.h" #include #include DGUI_USE_NAMESPACE // 由于需è¦�å�‘é€�dbus接å�£ 使用打桩类进行 class MockDTaskbarControl : public DTaskbarControl { public: using DTaskbarControl::DTaskbarControl; MOCK_METHOD1(sendMessage, void(const QVariantMap &)); }; class TDTaskbarControl : public DTest { protected: void SetUp(); void TearDown(); MockDTaskbarControl *control; }; void TDTaskbarControl::SetUp() { control = new MockDTaskbarControl; } void TDTaskbarControl::TearDown() { delete control; } TEST_F(TDTaskbarControl, testFunction) { enum { ProgressTestValue = 1 }; EXPECT_CALL(*control, sendMessage(testing::_)).Times(testing::AtLeast(1)); QSignalSpy valueChangedSpy(control, SIGNAL(progressChanged(double))); control->setProgress(true, ProgressTestValue); ASSERT_EQ(valueChangedSpy.count(), 1); QSignalSpy visibleChangedSpy(control, SIGNAL(progressVisibleChanged(bool))); control->setProgress(false, ProgressTestValue); ASSERT_EQ(visibleChangedSpy.count(), 1); QSignalSpy counterChangedSpy(control, SIGNAL(counterChanged(int))); control->setCounter(true, 1); ASSERT_EQ(control->counter(), 1); ASSERT_EQ(counterChangedSpy.count(), 1); QSignalSpy counterVisibleSpy(control, SIGNAL(counterVisibleChanged(bool))); control->setCounter(false, 1); ASSERT_EQ(counterVisibleSpy.count(), 1); control->setUrgency(true); control->setCounterVisible(true); ASSERT_EQ(control->counterVisible(), true); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dthumbnailprovider.cpp���������������������������������������������������0000664�0000000�0000000�00000007625�15226154130�0022165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dthumbnailprovider.h" #include #include #include #include #include #include #include #include #include DGUI_BEGIN_NAMESPACE #ifndef UT_DThumbnailProviderPrivate #define UT_DThumbnailProviderPrivate class DThumbnailProviderPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate { public: DThumbnailProviderPrivate(DThumbnailProvider *qq); void init(); QString sizeToFilePath(DThumbnailProvider::Size size) const; QString errorString; // MAX qint64 defaultSizeLimit = INT64_MAX; QHash sizeLimitHash; QMimeDatabase mimeDatabase; static QSet hasThumbnailMimeHash; struct ProduceInfo { QFileInfo fileInfo; DThumbnailProvider::Size size; DThumbnailProvider::CallBack callback; }; QQueue produceQueue; QSet> discardedProduceInfos; bool running = true; QWaitCondition waitCondition; QReadWriteLock dataReadWriteLock; D_DECLARE_PUBLIC(DThumbnailProvider) }; #endif DGUI_END_NAMESPACE DGUI_USE_NAMESPACE class TDThumbnailProvider : public DTest { protected: void SetUp(); void TearDown(); DThumbnailProvider *provider; DThumbnailProviderPrivate *provider_d; }; void TDThumbnailProvider::SetUp() { provider = DThumbnailProvider::instance(); provider_d = provider->d_func(); } void TDThumbnailProvider::TearDown() { // gtest会释放é�™æ€�部分数æ�® 导致å�Œé‡�释放程åº�崩溃这里手动将数æ�®æ¸…空防止崩溃事情å�‘生 provider_d->hasThumbnailMimeHash.clear(); } #define TESTRES_PATH ":/images/logo_icon.svg" #define TESTRES_PATH_1 "no_exist" TEST_F(TDThumbnailProvider, TestCreate) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; QFileInfo fi(TESTRES_PATH); QSignalSpy finishedSpy(provider, SIGNAL(createThumbnailFinished(const QString &, const QString &))); QString ret = provider->createThumbnail(fi, DThumbnailProvider::Normal); ASSERT_FALSE(ret.isEmpty()); ASSERT_EQ(finishedSpy.count(), 1); ASSERT_FALSE(provider->thumbnailFilePath(fi, DThumbnailProvider::Normal).isEmpty()); QFileInfo fi_notexisted(TESTRES_PATH_1); QSignalSpy failedSpy(provider, SIGNAL(createThumbnailFailed(const QString &))); ret = provider->createThumbnail(fi_notexisted, DThumbnailProvider::Normal); ASSERT_TRUE(ret.isEmpty()); ASSERT_EQ(finishedSpy.count(), 1); ASSERT_FALSE(provider->errorString().isEmpty()); ASSERT_TRUE(provider->thumbnailFilePath(fi_notexisted, DThumbnailProvider::Normal).isEmpty()); } TEST_F(TDThumbnailProvider, testAttribute) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; ASSERT_TRUE(provider->hasThumbnail(QFileInfo(TESTRES_PATH))); enum { TEST_DEFALUTSIZELIMIT = 25 }; provider->setDefaultSizeLimit(TEST_DEFALUTSIZELIMIT); ASSERT_EQ(provider->defaultSizeLimit(), TEST_DEFALUTSIZELIMIT); QMimeDatabase base; auto type = base.mimeTypeForFile(TESTRES_PATH); provider->setSizeLimit(type, TEST_DEFALUTSIZELIMIT); ASSERT_EQ(provider->sizeLimit(type), TEST_DEFALUTSIZELIMIT); } void testCallBack(const QString &) { return; } TEST_F(TDThumbnailProvider, TestProducrQueue) { provider_d->running = true; provider->appendToProduceQueue(QFileInfo(TESTRES_PATH), DThumbnailProvider::Small); provider->appendToProduceQueue(QFileInfo(TESTRES_PATH), DThumbnailProvider::Large, &testCallBack); ASSERT_FALSE(provider_d->produceQueue.isEmpty()); provider->removeInProduceQueue(QFileInfo(TESTRES_PATH), DThumbnailProvider::Small); ASSERT_FALSE(provider_d->discardedProduceInfos.isEmpty()); provider_d->running = false; } �����������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dwindowgroupleader.cpp���������������������������������������������������0000664�0000000�0000000�00000003017�15226154130�0022157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include "dwindowgroupleader.h" #include #include #include DGUI_USE_NAMESPACE class TDWindowGroupLeader : public DTest { protected: void SetUp(); void TearDown(); DWindowGroupLeader *groupLeader; QWindow *window1; QWindow *window2; }; void TDWindowGroupLeader::SetUp() { groupLeader = new DWindowGroupLeader; window1 = new QWindow; window2 = new QWindow; window1->create(); window2->create(); } void TDWindowGroupLeader::TearDown() { delete groupLeader; delete window1; delete window2; } TEST_F(TDWindowGroupLeader, testFunctions) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; // 测试多ç§�情况添加windowæ—¶æ•°æ�®æ˜¯å�¦æ­£å¸¸ groupLeader->addWindow(window1); groupLeader->addWindow(window2); qDebug() << "addWindow 1 & 2"; qDebug() << "groupLeaderId" << groupLeader->groupLeaderId(); qDebug() << "groupLeaderId" << groupLeader->clientLeaderId(); groupLeader->removeWindow(window1); qDebug() << "removeWindow 1"; qDebug() << "groupLeaderId" << groupLeader->groupLeaderId(); qDebug() << "groupLeaderId" << groupLeader->clientLeaderId(); groupLeader->removeWindow(window2); qDebug() << "removeWindow 2"; qDebug() << "groupLeaderId" << groupLeader->groupLeaderId(); qDebug() << "groupLeaderId" << groupLeader->clientLeaderId(); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_dwindowmanagerhelper.cpp�������������������������������������������������0000664�0000000�0000000�00000010515�15226154130�0022461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "test.h" #include #include "dwindowmanagerhelper.h" #include "dforeignwindow.h" DGUI_USE_NAMESPACE class TDWindowMangerHelper : public DTest { protected: void SetUp(); DWindowManagerHelper *wm_helper; }; void TDWindowMangerHelper::SetUp() { wm_helper = DWindowManagerHelper::instance(); } TEST_F(TDWindowMangerHelper, testStaticFunction) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; QWidget *w = new QWidget; w->createWinId(); //w->show(); ASSERT_TRUE(w->windowHandle()); enum { TestMotifFunction = DWindowManagerHelper::FUNC_RESIZE | DWindowManagerHelper::FUNC_MOVE, TestAllMotifFunction = DWindowManagerHelper::FUNC_ALL}; enum { TestDecorations = DWindowManagerHelper::DECOR_BORDER | DWindowManagerHelper::DECOR_RESIZEH, TestAllDecorations = DWindowManagerHelper::DECOR_ALL }; // 测试é�™æ€�函数测试是å�¦æ­£å¸¸ DWindowManagerHelper::setMotifFunctions(w->windowHandle(), DWindowManagerHelper::MotifFunctions(TestMotifFunction)); DWindowManagerHelper::MotifFunctions mFuncs = DWindowManagerHelper::getMotifFunctions(w->windowHandle()); if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) { ASSERT_EQ(mFuncs, TestMotifFunction); } else { qDebug() << "not support other wm"; } mFuncs = DWindowManagerHelper::setMotifFunctions(w->windowHandle(), DWindowManagerHelper::MotifFunctions(TestAllMotifFunction), true); ASSERT_EQ(mFuncs, TestAllMotifFunction); DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestDecorations)); DWindowManagerHelper::MotifDecorations mDecos = DWindowManagerHelper::getMotifDecorations(w->windowHandle()); if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) { ASSERT_EQ(mDecos, TestDecorations); } mDecos = DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestAllDecorations), true); if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) { ASSERT_EQ(mDecos, TestAllDecorations); } // 没有崩溃则测试æˆ�功 enum { TestWindowType = DWindowManagerHelper::DesktopType | DWindowManagerHelper::MenuType }; DWindowManagerHelper::setWmWindowTypes(w->windowHandle(), DWindowManagerHelper::WmWindowTypes(TestWindowType)); DWindowManagerHelper::setWmClassName(QByteArrayLiteral("TestWmClass")); DWindowManagerHelper::popupSystemWindowMenu(w->windowHandle()); delete w; } TEST_F(TDWindowMangerHelper, testFunctions) { if (qgetenv("QT_QPA_PLATFORM").contains("offscreen")) return; qDebug() << wm_helper->windowManagerNameString() << "\nhas blur window:" << wm_helper->hasBlurWindow() << "\nhas composite:" << wm_helper->hasComposite() << "\nhas not titlebar:" << wm_helper->hasNoTitlebar(); // ASSERT_TRUE(wm_helper->hasWallpaperEffect()); // ASSERT_FALSE(wm_helper->windowManagerNameString().isEmpty()); if (wm_helper->windowManagerNameString().contains(QStringLiteral("DeepinGala"))) { ASSERT_EQ(wm_helper->windowManagerName(), DWindowManagerHelper::DeepinWM); } else if (wm_helper->windowManagerNameString().contains(QStringLiteral("KWin"))) { ASSERT_EQ(wm_helper->windowManagerName(), DWindowManagerHelper::KWinWM); } else { ASSERT_EQ(wm_helper->windowManagerName(), DWindowManagerHelper::OtherWM); } if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) { ASSERT_FALSE(wm_helper->allWindowIdList().isEmpty()); ASSERT_FALSE(wm_helper->currentWorkspaceWindowIdList().isEmpty()); ASSERT_FALSE(wm_helper->currentWorkspaceWindows().isEmpty()); ASSERT_TRUE(wm_helper->windowFromPoint(wm_helper->currentWorkspaceWindows().first()->position())); } else { qDebug() << "allWindowIdList count:" << wm_helper->allWindowIdList().count() << "\ncurrentWorkspaceWindowIdList count:" << wm_helper->currentWorkspaceWindowIdList().count() << "\ncurrentWorkspaceWindows count:" << wm_helper->currentWorkspaceWindows().count() << "\nwindowFromPoint:" << wm_helper->windowFromPoint(QPoint()); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/src/ut_xdgiconproxyengine.cpp���������������������������������������������������0000664�0000000�0000000�00000013561�15226154130�0022202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include #include #include #include #include #include #include #define private public #include "xdgiconproxyengine_p.h" #include #undef private DGUI_USE_NAMESPACE class GTEST_API_ ut_XdgIconProxyEngine : public testing::Test { protected: void SetUp() override; void TearDown() override; XdgIconProxyEngine *mIconEngine = nullptr; QSize s64 = QSize(64, 64); }; void ut_XdgIconProxyEngine::SetUp() { // :/icons/deepin/xxx.svg QIconLoader::instance()->setThemeName("deepin"); mIconEngine = new XdgIconProxyEngine(new XdgIconLoaderEngine("cs_rect_64")); } void ut_XdgIconProxyEngine::TearDown() { delete mIconEngine; } TEST_F(ut_XdgIconProxyEngine, entryCacheKey) { ScalableEntry *entry = reinterpret_cast(QRandomGenerator::global()->generate()); QSet keySet; for (int i = QIcon::Normal; i <= QIcon::Selected; ++i) { for (int j = QIcon::On; j <= QIcon::Off; ++j) { quint64 key = XdgIconProxyEngine::entryCacheKey(entry, QIcon::Mode(i), QIcon::State(j)); quint64 calKey = quint64(entry) ^ (quint64(i) << 56) ^ (quint64(j) << 48); EXPECT_EQ(key, calKey); // conflict check EXPECT_FALSE(keySet.contains(key)); keySet.insert(key); } } } /* cs_rect_64.svg * +-------------+-------------+ * | | | * | Highlight | Text | * | | | * +-------------+-------------+ */ void testHighlightColor(const QPalette &pa, const QImage &img) { EXPECT_FALSE(img.isNull()); // QColor(AHSL) && QColor(ARGB) ? EXPECT_EQ(pa.highlight().color().toRgb(), img.pixelColor(QPoint(16, 16)).name()); } void testWindowTextColor(const QPalette &pa, const QImage &img) { EXPECT_FALSE(img.isNull()); EXPECT_EQ(pa.windowText().color(), img.pixelColor(QPoint(48, 16))); } void testHighlightedTextColor(const QPalette &pa, const QImage &img) { EXPECT_FALSE(img.isNull()); EXPECT_EQ(pa.highlightedText().color(), img.pixelColor(QPoint(48, 16))); } TEST_F(ut_XdgIconProxyEngine, pixmapByEntry) { QPalette pa = qApp->palette(); // ensureLoaded EXPECT_EQ(s64, mIconEngine->actualSize(s64, QIcon::Normal, QIcon::On)); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QIconLoaderEngineEntry *entry = mIconEngine->engine->entryForSize(s64); #else QIconLoaderEngineEntry *entry = mIconEngine->engine->entryForSize(mIconEngine->engine->m_info, s64); #endif ASSERT_TRUE(entry); QPixmap normalPix = mIconEngine->pixmapByEntry(entry, s64, QIcon::Normal, QIcon::On); testWindowTextColor(pa, normalPix.toImage()); QPixmap selectPix = mIconEngine->pixmapByEntry(entry, s64, QIcon::Selected, QIcon::On); testHighlightedTextColor(pa, selectPix.toImage()); testHighlightColor(pa, normalPix.toImage()); } TEST_F(ut_XdgIconProxyEngine, paint) { QPalette pa = qApp->palette(); QImage img(s64, QImage::Format_ARGB32_Premultiplied); { img.fill(Qt::transparent); QPainter p(&img); mIconEngine->paint(&p, QRect(QPoint(0, 0), s64),QIcon::Normal, QIcon::On); testHighlightColor(pa, img); testWindowTextColor(pa, img); } { img.fill(Qt::transparent); QPainter p(&img); mIconEngine->paint(&p, QRect(QPoint(0, 0), s64),QIcon::Selected, QIcon::On); testHighlightColor(pa, img); testHighlightedTextColor(pa, img); } } TEST_F(ut_XdgIconProxyEngine, pixmap) { QPalette pa = qApp->palette(); QPixmap normalPix = mIconEngine->pixmap(s64, QIcon::Normal, QIcon::On); testWindowTextColor(pa, normalPix.toImage()); QPixmap selectPix = mIconEngine->pixmap(s64, QIcon::Selected, QIcon::On); testHighlightColor(pa, selectPix.toImage()); testHighlightedTextColor(pa, selectPix.toImage()); } TEST_F(ut_XdgIconProxyEngine, addPixmap_addFile) { QString fileName(":/icons/deepin/actions/64/cs_rect_64.svg"); // XdgIconLoaderEngine did not implement these methods mIconEngine->addPixmap(QPixmap(fileName), QIcon::Normal, QIcon::On); mIconEngine->addFile(fileName, s64, QIcon::Normal, QIcon::On); } TEST_F(ut_XdgIconProxyEngine, key) { ASSERT_EQ(mIconEngine->key(), QLatin1String("XdgIconProxyEngine")); } TEST_F(ut_XdgIconProxyEngine, actualSize) { EXPECT_EQ(s64, mIconEngine->actualSize(s64, QIcon::Normal, QIcon::On)); } TEST_F(ut_XdgIconProxyEngine, clone) { QScopedPointer clone(mIconEngine->clone()); ASSERT_EQ(clone->key(), mIconEngine->key()); ASSERT_EQ(clone->iconName(), mIconEngine->iconName()); } TEST_F(ut_XdgIconProxyEngine, read_write) { QByteArray data; { QDataStream out(&data, QIODevice::WriteOnly); mIconEngine->write(out); } QString iconName; { QDataStream in(&data, QIODevice::ReadOnly); in >> iconName; ASSERT_EQ("cs_rect_64", iconName); } iconName = "test_icon_name"; { QDataStream out(&data, QIODevice::WriteOnly); out << iconName; } { QDataStream in(&data, QIODevice::ReadOnly); mIconEngine->read(in); ASSERT_EQ(mIconEngine->engine->m_iconName, iconName); // iconName() not implement ASSERT_EQ(mIconEngine->iconName(), ""); ASSERT_EQ(mIconEngine->engine->iconName(), ""); } } TEST_F(ut_XdgIconProxyEngine, virtual_hook) { #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) { QIconEngine::ScaledPixmapArgument scalePixmapArg = { s64, QIcon::Normal, QIcon::On, 1.25, QPixmap() }; mIconEngine->virtual_hook(QIconEngine::ScaledPixmapHook, &scalePixmapArg); ASSERT_EQ(scalePixmapArg.pixmap.size(), s64); } #endif } �����������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/test-recoverage.sh��������������������������������������������������������������0000775�0000000�0000000�00000001622�15226154130�0017705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/bash # SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later set -ex BUILD_DIR=`pwd`/../build/tests/ HTML_DIR=${BUILD_DIR}/html XML_DIR=${BUILD_DIR}/report export ASAN_OPTIONS="halt_on_error=0" # back to project directroy cd .. cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DBUILD_EXAMPLE=OFF -DBUILD_DOCS=OFF -DEnableCov=ON cmake --build build --target ut-DtkGui -j$(nproc) cd $BUILD_DIR ./ut-DtkGui --gtest_output=xml:${XML_DIR}/report_dtkgui.xml lcov -d ../ -c -o coverage_all.info lcov --remove coverage_all.info "*/tests/*" "*/usr/include*" "*build-ut/src*" --output-file coverage.info cd .. genhtml -o $HTML_DIR $BUILD_DIR/coverage.info && mv ${BUILD_DIR}/html/index.html ${BUILD_DIR}/html/cov_dtkgui.html test -e ${BUILD_DIR}/asan.log* && mv ${BUILD_DIR}/asan.log* ${BUILD_DIR}/asan_dtkgui.log || touch ${BUILD_DIR}/asan_dtkgui.log ��������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tests/test.h��������������������������������������������������������������������������0000664�0000000�0000000�00000001020�15226154130�0015367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef TEST_H #define TEST_H #include class DTest : public ::testing::Test { }; template class DTestWithParam : public ::testing::TestWithParam { }; template bool waitforSpy(T &spy, int timeout = 5000) { int times = timeout / 10 + 1; while(!spy.wait(10)) { if (--times <= 1) break; } return times > 1; } #endif // TEST_H ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/toolGenerate/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0015534�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/toolGenerate/dconfig2cpp/�������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0017732�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/toolGenerate/dconfig2cpp/org_deepin_dtk_ui_preference.hpp�����������������������������0000664�0000000�0000000�00000020314�15226154130�0026313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/** * This file is generated by dconfig2cpp. * Command line arguments: ./dconfig2cpp -p ./dtkgui/toolGenerate/dconfig2cpp ./dtkgui/misc/org.deepin.dtk.ui.preference.json * Generation time: 2025-01-14T10:54:59 * JSON file version: 1.0 * * WARNING: DO NOT MODIFY THIS FILE MANUALLY. * If you need to change the content, please modify the dconfig2cpp tool. */ #ifndef ORG_DEEPIN_DTK_UI_PREFERENCE_H #define ORG_DEEPIN_DTK_UI_PREFERENCE_H #include #include #include #include #include #include class org_deepin_dtk_ui_preference : public QObject { Q_OBJECT Q_PROPERTY(double themeType READ themeType WRITE setThemeType NOTIFY themeTypeChanged) Q_PROPERTY(double titlebarHeight READ titlebarHeight WRITE setTitlebarHeight NOTIFY titlebarHeightChanged) public: explicit org_deepin_dtk_ui_preference(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) : QObject(parent) { if (!thread->isRunning()) { qWarning() << QStringLiteral("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); QMetaObject::invokeMethod(worker, [=]() { auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); if (!config) { qWarning() << QStringLiteral("Failed to create DConfig instance."); worker->deleteLater(); return; } config->moveToThread(QThread::currentThread()); initialize(config); worker->deleteLater(); }); } explicit org_deepin_dtk_ui_preference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) : QObject(parent) { if (!thread->isRunning()) { qWarning() << QStringLiteral("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); QMetaObject::invokeMethod(worker, [=]() { auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); if (!config) { qWarning() << QStringLiteral("Failed to create DConfig instance."); worker->deleteLater(); return; } config->moveToThread(QThread::currentThread()); initialize(config); worker->deleteLater(); }); } explicit org_deepin_dtk_ui_preference(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) : QObject(parent) { if (!thread->isRunning()) { qWarning() << QStringLiteral("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); QMetaObject::invokeMethod(worker, [=]() { auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); if (!config) { qWarning() << QStringLiteral("Failed to create DConfig instance."); worker->deleteLater(); return; } config->moveToThread(QThread::currentThread()); initialize(config); worker->deleteLater(); }); } explicit org_deepin_dtk_ui_preference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) : QObject(parent) { if (!thread->isRunning()) { qWarning() << QStringLiteral("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); QMetaObject::invokeMethod(worker, [=]() { auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); if (!config) { qWarning() << QStringLiteral("Failed to create DConfig instance."); worker->deleteLater(); return; } config->moveToThread(QThread::currentThread()); initialize(config); worker->deleteLater(); }); } ~org_deepin_dtk_ui_preference() { if (m_config.loadRelaxed()) { m_config.loadRelaxed()->deleteLater(); } } double themeType() const { return p_themeType; } void setThemeType(const double &value) { auto oldValue = p_themeType; p_themeType = value; markPropertySet(0); if (auto config = m_config.loadRelaxed()) { QMetaObject::invokeMethod(config, [this, value]() { m_config.loadRelaxed()->setValue(QStringLiteral("themeType"), value); }); } if (p_themeType != oldValue) { Q_EMIT themeTypeChanged(); } } double titlebarHeight() const { return p_titlebarHeight; } void setTitlebarHeight(const double &value) { auto oldValue = p_titlebarHeight; p_titlebarHeight = value; markPropertySet(1); if (auto config = m_config.loadRelaxed()) { QMetaObject::invokeMethod(config, [this, value]() { m_config.loadRelaxed()->setValue(QStringLiteral("titlebarHeight"), value); }); } if (p_titlebarHeight != oldValue) { Q_EMIT titlebarHeightChanged(); } } Q_SIGNALS: void themeTypeChanged(); void titlebarHeightChanged(); private: void initialize(DTK_CORE_NAMESPACE::DConfig *config) { Q_ASSERT(!m_config.loadRelaxed()); m_config.storeRelaxed(config); if (testPropertySet(0)) { config->setValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); } else { updateValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); } if (testPropertySet(1)) { config->setValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); } else { updateValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); } connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { updateValue(key); }, Qt::DirectConnection); } void updateValue(const QString &key, const QVariant &fallback = QVariant()) { Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); const QVariant &value = m_config.loadRelaxed()->value(key, fallback); if (key == QStringLiteral("themeType")) { auto newValue = qvariant_cast(value); QMetaObject::invokeMethod(this, [this, newValue]() { if (p_themeType != newValue) { p_themeType = newValue; Q_EMIT themeTypeChanged(); } }); return; } if (key == QStringLiteral("titlebarHeight")) { auto newValue = qvariant_cast(value); QMetaObject::invokeMethod(this, [this, newValue]() { if (p_titlebarHeight != newValue) { p_titlebarHeight = newValue; Q_EMIT titlebarHeightChanged(); } }); return; } } inline void markPropertySet(const int index) { if (index < 32) { m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); return; } Q_UNREACHABLE(); } inline bool testPropertySet(const int index) const { if (index < 32) { return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); } Q_UNREACHABLE(); } QAtomicPointer m_config = nullptr; double p_themeType { 0 }; double p_titlebarHeight { -1 }; QAtomicInteger m_propertySetStatus0 = 0; }; #endif // ORG_DEEPIN_DTK_UI_PREFERENCE_H ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tools/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0014244�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tools/CMakeLists.txt������������������������������������������������������������������0000664�0000000�0000000�00000000317�15226154130�0017005�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������add_subdirectory(deepin-gui-settings) add_subdirectory(dci-image-converter) add_subdirectory(dci-icon-theme) add_subdirectory(dde-kwin-debug) add_subdirectory(image-handler) add_subdirectory(dci-iconfinder) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tools/dci-icon-theme/�����������������������������������������������������������������0000775�0000000�0000000�00000000000�15226154130�0017031�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dtkgui-6.7.46/tools/dci-icon-theme/CMakeLists.txt���������������������������������������������������0000664�0000000�0000000�00000000717�15226154130�0021576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������set(BIN_NAME dci-icon-theme) set(TARGET_NAME ${BIN_NAME}${DTK_NAME_SUFFIX}) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent REQUIRED) add_executable(${TARGET_NAME} main.cpp ) target_link_libraries(${TARGET_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Concurrent ${LIB_NAME} ) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN_NAME}) install(TARGETS ${TARGET_NAME} DESTINATION "${TOOL_INSTALL_DIR}") �������������������������������������������������dtkgui-6.7.46/tools/dci-icon-theme/README.md��������������������������������������������������������0000664�0000000�0000000�00000006324�15226154130�0020315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# dci-icon-theme ```` Usage: dci-icon-theme [options] ~/dci-png-icons dci-icon-theme tool is a command tool that generate dci icons from common icons. For example, the tool is used in the following ways: dci-icon-theme /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95 dci-icon-theme -m *.png /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95 dci-icon-theme --fix-dark-theme