Compare commits

...

29 Commits

Author SHA1 Message Date
github-actions[bot] 46e6d5e8e5 chore: New release 5.7.25
Log:
2025-10-30 13:59:58 +00:00
github-actions[bot] 84b0b917b9 chore: New release 5.7.24
Log:
2025-10-16 12:11:59 +00:00
yeshanshan 840b931148 fix: sync with qt5platform-plugins
https://github.com/linuxdeepin/qt5platform-plugins/pull/305
2025-10-16 13:41:10 +08:00
ComixHe 8e85a7cd54 feat: support Qt 6.10
Signed-off-by: ComixHe <heyuming@deepin.org>
2025-10-11 13:17:44 +08:00
yeshanshan 14c291e1ef fix: prevent thread-safety issue in D-Bus config manager
1. Store D-Bus object path in local variable to avoid potential thread-
safety issues
2. The original code used QDBusObjectPath directly which could be
modified by other threads sharing the same systemBus connection
3. This ensures the path value remains consistent throughout the config
manager initialization process
4. Also fixed inconsistent logging macro usage (cfLog vs cfLog())

Log: Fixed potential thread-safety issue in configuration manager
initialization

Influence:
1. Test configuration manager initialization under multi-threaded
scenarios
2. Verify D-Bus communication stability when multiple threads access
systemBus
3. Ensure config manager creation works correctly in concurrent
environments
4. Test application startup and config loading in multi-process
scenarios

fix: 修复 D-Bus 配置管理器中的线程安全问题

1. 将 D-Bus 对象路径存储在局部变量中以避免潜在的线程安全问题
2. 原代码直接使用 QDBusObjectPath,可能被共享同一 systemBus 连接的其他线
程修改
3. 确保路径值在配置管理器初始化过程中保持一致
4. 同时修复了不一致的日志宏使用(cfLog vs cfLog())

Log: 修复配置管理器初始化中的潜在线程安全问题

Influence:
1. 在多线程场景下测试配置管理器初始化
2. 验证多线程访问 systemBus 时的 D-Bus 通信稳定性
3. 确保在并发环境中正确创建配置管理器
4. 测试多进程场景下的应用程序启动和配置加载

PMS: BUG-335523
2025-10-10 17:10:40 +08:00
wjyrich dbf42d7701 fix: replace rmdir with rename for directory operations
Changed rmdir to rename when handling directory operations in trash
manager
The original code used rmdir to remove directories which could fail if
directory is not empty
Using rename operation instead allows moving directories to trash
location while preserving contents
This fixes potential data loss when trashing non-empty directories

fix: 将目录操作中的 rmdir 替换为 rename

在回收站管理器中处理目录操作时将 rmdir 改为 rename
原始代码使用 rmdir 删除目录,如果目录不为空则会失败
使用 rename 操作可以将目录移动到回收站位置同时保留内容
这修复了清空非空目录时可能出现的数据丢失问题
2025-09-29 13:30:11 +08:00
github-actions[bot] b7f1f8afef chore: New release 5.7.23
Log:
2025-09-25 17:44:36 +08:00
yeshanshan c5be272ad8 fix: fix dconfig static variable release issue
Fixed dconfig exit crash caused by static variable destruction order
1. Added null pointer check before accessing m_config in updateValue
method to prevent accessing destroyed objects
2. Added m_config.storeRelaxed(nullptr) in destructor to clear the
atomic pointer
3. Added early return checks in connect and updateValue methods when
config is null
4. Updated default value for p_rules to use proper unicode string
literal

The issue occurred because static dconfig objects were being destroyed
after the QCoreApplication instance, leading to attempts to access
already destroyed DConfig objects during cleanup. The fix ensures proper
null checking and pointer cleanup to prevent crashes during application
exit.

Log: Fixed application exit crash related to dconfig static variables

Influence:
1. Test application normal startup and shutdown
2. Verify dconfig functionality still works correctly
3. Test with multiple dconfig instances
4. Verify no crashes occur during application termination
5. Test configuration value changes and updates

fix: 修复dconfig静态变量释放导致的退出异常

修复了由静态变量销毁顺序引起的dconfig退出崩溃问题
1. 在updateValue方法中添加空指针检查,防止访问已销毁的对象
2. 在析构函数中添加m_config.storeRelaxed(nullptr)来清理原子指针
3. 在connect和updateValue方法中添加config为null时的提前返回检查
4. 更新p_rules的默认值为正确的unicode字符串字面量

问题出现在静态dconfig对象在QCoreApplication实例之后被销毁时,导致在清
理过程中尝试访问已销毁的DConfig对象。修复确保进行适当的空值检查和指针清
理,以防止应用程序退出时的崩溃。

Log: 修复了与dconfig静态变量相关的应用程序退出崩溃问题

Influence:
1. 测试应用程序正常启动和关闭
2. 验证dconfig功能仍然正常工作
3. 测试多个dconfig实例的情况
4. 验证应用程序终止时不会发生崩溃
5. 测试配置值更改和更新功能

PMS: BUG-324689
2025-09-25 15:26:44 +08:00
wangshaojun d2d91a87a3 feat: 增加服务器教育版和国防版
增加系统类型 服务器教育版 服务器国防版 枚举

Log: 增加服务器教育版和国防版
Task: https://pms.uniontech.com/task-view-381681.html
Influence: 系统类型
Change-Id: I2806d86ff42d31199fc7a144bf9e8b0fc69c5fcd
2025-09-25 13:37:27 +08:00
JiDe Zhang 440fca2efd fix: fix heap-use-after-free issue
The `QString::toUtf8().constData()` returns a pointer to the internal
data of a temporary `QByteArray` object. This `QByteArray` object
is immediately destroyed after the call to `constData()`, making the
returned pointer invalid. Subsequent uses of this pointer would result
in a heap-use-after-free error.

To fix this, the `QByteArray` object returned by `toUtf8()` is now
stored in a local variable, ensuring that the data it contains remains
valid for the duration of its scope.

Influence:
1. Run all existing D-Bus related tests to ensure the fix does not
introduce regressions.
2. Specifically test the scenarios where `DSGApplication::id()` is
called before `QCoreApplication` initialization.

fix: 修复堆释放后使用问题

`QString::toUtf8().constData()` 返回一个指向临时 `QByteArray` 对象内部数
据的指针。这个 `QByteArray` 对象在调用 `constData()` 后立即被销毁,导致
返回的指针无效。随后使用此指针会导致堆释放后使用错误。

为了解决这个问题,由 `toUtf8()` 返回的 `QByteArray` 对象现在存储在一个局
部变量中,从而确保其包含的数据在其作用域内保持有效。

Influence:
1. 运行所有现有的 D-Bus 相关测试,以确保此修复不会引入回归。
2. 专门测试在 `QCoreApplication` 初始化之前调用 `DSGApplication::id()`
的场景。
2025-09-23 17:54:45 +08:00
wjyrich bcd59cb836 fix: fix trash validation for symlinks
The condition for checking if a file can be moved to trash was
incorrectly rejecting symlinks that point to files on the same
filesystem as the trash directory. The original condition only allowed
moving files when the storage info matched the trash storage info, but
this failed for symlinks since their storage info differs from their
target.

The fix adds an additional check to allow symlinks when they are on
the same filesystem as the trash directory, ensuring proper trash
functionality for symbolic links while maintaining the original
validation for regular files.

fix: 修复符号链接的垃圾箱验证问题

原本检查文件是否能移动到垃圾箱的条件错误地拒绝了指向与垃圾箱目录相同文
件系统的符号链接。原始条件仅当存储信息与垃圾箱存储信息匹配时才允许移动文
件,但这对于符号链接会失败,因为它们的存储信息与其目标不同。

修复添加了额外检查,允许符号链接在与垃圾箱目录相同的文件系统上时通过验
证,确保符号链接的正常垃圾箱功能,同时保持对常规文件的原始验证。
2025-09-23 05:03:46 +00:00
Wang Zichong c9a2ad0b37 feat: DPinyin::firstLetters support set ToneStyle
允许为 firstLetters() 设置声调选项,便于获取完全不带声调的拼音首字母

Log:
2025-09-18 15:35:03 +08:00
Wang Yu efb8be8218 fix: add fallback type conversion in demarshall function
- Added else branch to handle non-QDBusArgument values with type conversion
- Improves property value handling when direct DBus unmarshalling is not applicable

Log: add fallback type conversion in demarshall function
pms: BUG-332055
2025-09-12 17:54:36 +08:00
github-actions[bot] fe1e9715a2 chore: New release 5.7.22
Log:
2025-09-04 20:06:39 +08:00
yeshanshan 39b91e4b79 fix: resolve non-reproducible DBUS code generation issue
Changed QSet to QStringList for annotations collection to ensure
deterministic output order
Added removeDuplicates() call to maintain uniqueness while preserving
order
This fixes non-reproducible builds caused by QSet's unpredictable
iteration order

Log: Fixed DBUS code generation reproducibility issue

Influence:
1. Verify DBUS interface code generation produces identical output for
same inputs
2. Test with multiple interface definitions containing annotations
3. Check build reproducibility across different systems

fix: 修复DBUS代码生成不可重复的问题

将注解集合从QSet改为QStringList以确保输出顺序确定性
添加removeDuplicates()调用在保持顺序的同时确保唯一性
修复了由于QSet迭代顺序不可预测导致的构建不可重复问题

Log: 修复了DBUS代码生成不可重复的问题

Influence:
1. 验证相同输入下DBUS接口代码生成是否产生相同输出
2. 测试包含多个注解的接口定义
3. 检查不同系统间的构建可重复性
2025-08-19 18:42:54 +08:00
github-actions[bot] 2ffc340446 chore: New release 5.7.21
Log:
2025-08-14 20:27:53 +08:00
yeshanshan 2cbf1b55d0 feat: add deprecation ignore support for DTK
Added D_IGNORE_DEPRECATIONS macro to suppress deprecation warnings in
DTK core
1. Define D_IGNORE_DEPRECATIONS for static library builds
2. Define D_IGNORE_DEPRECATIONS when building DTK core library
3. Added conditional compilation to skip deprecation attributes when
D_IGNORE_DEPRECATIONS is defined
4. Maintains backward compatibility while allowing projects to ignore
deprecated APIs

This change helps projects transition away from deprecated APIs without
immediate warning noise while maintaining the deprecation markers for
new development

Influence:
1. Test building with D_IGNORE_DEPRECATIONS defined to verify
deprecation warnings are suppressed
2. Test building without D_IGNORE_DEPRECATIONS to ensure deprecation
warnings still appear
3. Verify both static and dynamic library builds work correctly with
this change

feat: 添加DTK废弃接口忽略支持

新增D_IGNORE_DEPRECATIONS宏用于抑制DTK核心中的废弃警告
1. 为静态库构建定义D_IGNORE_DEPRECATIONS
2. 构建DTK核心库时定义D_IGNORE_DEPRECATIONS
3. 添加条件编译,当D_IGNORE_DEPRECATIONS定义时跳过废弃属性
4. 保持向后兼容性同时允许项目忽略废弃API

此变更帮助项目在不立即处理废弃警告的情况下逐步迁移废弃API,同时保留废弃
标记供新开发使用

Influence:
1. 测试定义D_IGNORE_DEPRECATIONS时的构建,验证废弃警告被抑制
2. 测试未定义D_IGNORE_DEPRECATIONS时的构建,确保废弃警告仍然显示
3. 验证静态库和动态库构建在此变更后都能正常工作
2025-08-14 11:36:15 +00:00
github-actions[bot] befdd9f0d2 chore: New release 5.7.20
Log:
2025-07-31 20:29:37 +08:00
yeshanshan e900940de3 fix: resolve compilation warnings and Qt6 compatibility issues
1. Replaced QScopedPointer with std::unique_ptr for better memory
management and consistency
2. Fixed time handling in DRecentManager for Qt6 by using QTimeZone
3. Added missing memory header for smart pointers

These changes address compiler warnings and ensure proper functionality
across both Qt5 and Qt6 versions, while modernizing the codebase with
standard C++ features.

fix: 修复编译警告和Qt6兼容性问题

1. 使用std::unique_ptr替代QScopedPointer以获得更好的内存管理和一致性
2. 在DRecentManager中修复Qt6的时间处理问题,使用QTimeZone
3. 添加缺失的memory头文件以支持智能指针

这些修改解决了编译器警告问题,并确保代码在Qt5和Qt6版本中都能正常工作,同
时使用标准C++特性使代码更现代化。
2025-07-28 18:22:26 +08:00
yeshanshan 97e66aaaf4 refactor: improve D-Bus resource management with RAII
1. Added custom deleters for D-Bus resources (DBusError, DBusConnection,
DBusMessage)
2. Replaced manual resource cleanup with std::unique_ptr RAII wrappers
3. Simplified error handling by removing repetitive cleanup code
4. Improved memory safety by ensuring resources are always released
5. Added detailed documentation for getId() function explaining the
libdbus-1 usage

The changes ensure proper resource management even in error cases and
make the code more maintainable by eliminating manual cleanup. This is
particularly important for D-Bus operations that may fail at multiple
points. The RAII approach prevents resource leaks and makes the code
more robust.

refactor: 使用 RAII 改进 D-Bus 资源管理

1. 为 D-Bus 资源(DBusError, DBusConnection, DBusMessage)添加自定义删除器
2. 使用 std::unique_ptr RAII 包装器替代手动资源清理
3. 通过移除重复的清理代码简化错误处理
4. 通过确保资源总是被释放来提高内存安全性
5. 为 getId() 函数添加详细文档说明 libdbus-1 的使用

这些变更确保了即使在错误情况下也能正确处理资源,并通过消除手动清理使代码
更易于维护。这对于可能在多个点失败的 D-Bus 操作尤为重要。RAII 方法防止了
资源泄漏并使代码更加健壮。
2025-07-08 17:10:57 +08:00
yeshanshan 80a5f3edce fix: use QCoreApplication for application name
Changed from using qApp->applicationName() to
QCoreApplication::applicationName() for getting the application name.
This provides better consistency and reliability as QCoreApplication is
the base class and ensures the method is always available, while qApp
macro might not be defined in all contexts. The change maintains the
same functionality but with more robust implementation.

fix: 使用 QCoreApplication 获取应用名称

将 qApp->applicationName() 改为 QCoreApplication::applicationName() 来获
取应用名称。这提供了更好的一致性和可靠性,因为 QCoreApplication 是基类并
确保方法始终可用,而 qApp 宏在某些上下文中可能未定义。此更改保持了相同的
功能但实现了更健壮的实现。
2025-07-08 10:33:19 +08:00
github-actions[bot] df43a12293 chore: New release 5.7.19
Log:
2025-07-03 13:22:37 +00:00
yeshanshan 5042e3af39 fix: add security hardening flags to build configuration
Added security hardening compiler and linker flags to the Debian build
rules
1. Enabled all hardening options via DEB_BUILD_MAINT_OPTIONS
2. Added -Wall warning flags for C/C++ compilation
3. Added secure linker flags including RELRO, immediate binding, and
noexecstack
4. These changes improve security by enabling modern compiler
protections and reducing potential attack surfaces

fix: 在构建配置中添加安全加固标志

在 Debian 构建规则中添加了安全加固的编译器和链接器标志
1. 通过 DEB_BUILD_MAINT_OPTIONS 启用所有加固选项
2. 为 C/C++ 编译添加 -Wall 警告标志
3. 添加安全的链接器标志包括 RELRO、立即绑定和 noexecstack
4. 这些更改通过启用现代编译器保护和减少潜在攻击面来提高安全性
2025-07-03 12:59:45 +00:00
yeshanshan 72c74eec4b refactor: replace QtDBus with libdbus-1 in dsgapplication
The changes replace QtDBus implementation with direct libdbus-1 calls
in dsgapplication.cpp for better control and performance. Key changes
include:
1. Added libdbus-1-dev as build dependency in debian/control
2. Updated CMakeLists.txt to find and link against libdbus-1
3. Implemented new utility functions checkDBusServiceActivatable and
callDBusIdentifyMethod using libdbus-1 API
4. Removed QtDBus dependencies and replaced with direct D-Bus calls
5. Added proper error handling and resource cleanup for D-Bus
connections

This change provides more direct control over D-Bus interactions
and removes QtDBus dependency overhead while maintaining the same
functionality.

refactor: 在 dsgapplication 中用 libdbus-1 替换 QtDBus

这些更改用直接的 libdbus-1 调用替换了 dsgapplication.cpp 中的 QtDBus 实
现,以获得更好的控制和性能。主要变更包括:
1. 在 debian/control 中添加了 libdbus-1-dev 作为构建依赖
2. 更新 CMakeLists.txt 以查找并链接 libdbus-1
3. 使用 libdbus-1 API 实现了新的实用函数 checkDBusServiceActivatable 和
callDBusIdentifyMethod
4. 移除了 QtDBus 依赖项并替换为直接的 D-Bus 调用
5. 为 D-Bus 连接添加了适当的错误处理和资源清理

此变更提供了对 D-Bus 交互更直接的控制,在保持相同功能的同时移除了 QtDBus
依赖开销。
2025-07-03 20:38:54 +08:00
github-actions[bot] 303f32e5c7 chore: New release 5.7.18
Log:
2025-06-27 17:18:10 +08:00
yeshanshan 374dca6299 fix: make version parameter optional in release workflow
1. Changed version parameter from required to optional in auto-
release.yml
2. Fixed spec file formatting for Version and Release fields
3. Added %{?dist} macro to Release field for better RPM compatibility

The changes make the release workflow more flexible by allowing version-
less releases when needed. The spec file formatting improvements ensure
consistency with RPM packaging standards, while the %{?dist} macro helps
with proper package distribution tagging.

fix: 在发布工作流中使版本参数可选

1. 在 auto-release.yml 中将版本参数从必填改为可选
2. 修复了 spec 文件中 Version 和 Release 字段的格式
3. 在 Release 字段中添加了 %{?dist} 宏以提升 RPM 兼容性

这些改动使得发布工作流在需要时可以更灵活地进行无版本发布。spec 文件的格
式改进确保了与 RPM 打包标准的一致性,而 %{?dist} 宏有助于正确的软件包分
发标记。
2025-06-27 16:43:48 +08:00
yeshanshan 7bf69bc64d fix: copy cachePrefix in DConfigFile copy constructor
1. Added missing copy of cachePrefix member when copying DConfigFile
objects
2. The cachePrefix was being lost during copy operations which could
lead to incorrect cache behavior
3. This ensures complete and proper copying of all cache-related data

fix: 在 DConfigFile 拷贝构造函数中复制 cachePrefix

1. 添加了对 cachePrefix 成员的拷贝操作,在复制 DConfigFile 对象时该成员
之前被遗漏
2. 之前拷贝操作会丢失 cachePrefix,可能导致缓存行为异常
3. 此修改确保所有缓存相关数据都能被完整正确地拷贝
2025-06-27 07:12:55 +00:00
yeshanshan 3446cbed57 fix: improve logging rules environment variable handling
1. Modified condition to check for both DTK_DISABLED_LOGGING_RULES and
QT_LOGGING_RULES environment variables
2. This change prevents logging rules from being initialized when either
variable is set
3. Ensures better compatibility with Qt's standard logging configuration
system
4. Maintains backward compatibility while adding support for standard Qt
logging control

fix: 改进日志规则环境变量处理

1. 修改条件以同时检查 DTK_DISABLED_LOGGING_RULES 和 QT_LOGGING_RULES 环
境变量
2. 当任一变量设置时,阻止日志规则初始化
3. 确保与 Qt 标准日志配置系统更好的兼容性
4. 在添加对标准 Qt 日志控制支持的同时保持向后兼容
2025-06-27 12:20:14 +08:00
github-actions[bot] 629c6ebe01 chore(rpm): New release 5.7.17
Log:
2025-06-19 10:21:56 +08:00
34 changed files with 573 additions and 75 deletions

View File

@ -5,7 +5,7 @@ on:
version: version:
description: 'Release version (e.g., 1.0.0)' description: 'Release version (e.g., 1.0.0)'
type: string type: string
required: true required: false
name: name:
description: 'The name of the person to release the version' description: 'The name of the person to release the version'
type: string type: string

View File

@ -1,3 +1,98 @@
# 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).
## [5.7.25] - 2025-10-30
## [5.7.24] - 2025-10-16
### Added
- Support Qt 6.10
### Fixed
- Replace rmdir with rename for directory operations
- Prevent thread-safety issue in D-Bus config manager
- Sync with qt5platform-plugins
## [5.7.23] - 2025-09-25
### Added
- Add fallback type conversion in demarshall function
### Changed
- Feat: DPinyin::firstLetters support set ToneStyle
- 增加服务器教育版和国防版
### Fixed
- Fix trash validation for symlinks
- Fix heap-use-after-free issue
- Fix dconfig static variable release issue
## [5.7.22] - 2025-09-04
### Fixed
- Resolve non-reproducible DBUS code generation issue
## [5.7.21] - 2025-08-14
### Added
- Add deprecation ignore support for DTK
## [5.7.20] - 2025-07-31
### Changed
- Improve D-Bus resource management with RAII
### Fixed
- Use QCoreApplication for application name
- Resolve compilation warnings and Qt6 compatibility issues
## [5.7.19] - 2025-07-03
### Added
- Add security hardening flags to build configuration
### Changed
- Replace QtDBus with libdbus-1 in dsgapplication
## [5.7.18] - 2025-06-27
### Fixed
- Improve logging rules environment variable handling
- Copy cachePrefix in DConfigFile copy constructor
- Make version parameter optional in release workflow
## [5.7.17] - 2025-06-18
### Added
- Feat(ci): add auto release
- Add license for VERSION.in
### Changed
- Support VERSION file
- Update .syncexclude
### Fixed
- .deepin@main -> .deepin@master
<a name="5.7.14"></a> <a name="5.7.14"></a>
## 5.7.14 (2025-04-12) ## 5.7.14 (2025-04-12)

View File

@ -1 +1 @@
5.7.15 5.7.25

View File

@ -1,6 +1,6 @@
# Maintainer: justforlxz <justforlxz@gmail.com> # Maintainer: justforlxz <justforlxz@gmail.com>
pkgname=dtkcore-git pkgname=dtkcore-git
pkgver=5.7.15 pkgver=5.7.25
pkgrel=1 pkgrel=1
sourcename=dtkcore sourcename=dtkcore
sourcetars=("$sourcename"_"$pkgver".tar.xz) sourcetars=("$sourcename"_"$pkgver".tar.xz)

54
debian/changelog vendored
View File

@ -1,3 +1,57 @@
dtkcore (5.7.25) unstable; urgency=medium
* Release 5.7.25
-- yeshanshan <yeshanshan@uniontech.com> Thu, 30 Oct 2025 21:47:32 +0800
dtkcore (5.7.24) unstable; urgency=medium
* Release 5.7.24
-- yeshanshan <yeshanshan@uniontech.com> Thu, 16 Oct 2025 19:45:57 +0800
dtkcore (5.7.23) unstable; urgency=medium
* Release 5.7.23
-- yeshanshan <packages@deepin.org> Thu, 25 Sep 2025 16:49:58 +0800
dtkcore (5.7.22) unstable; urgency=medium
* Release 5.7.22
-- yeshanshan <yeshanshan@uniontech.com> Thu, 04 Sep 2025 19:27:28 +0800
dtkcore (5.7.21) unstable; urgency=medium
* Release 5.7.21
-- yeshanshan <packages@deepin.org> Thu, 14 Aug 2025 19:47:41 +0800
dtkcore (5.7.20) unstable; urgency=medium
* Release 5.7.20
-- yeshanshan <yeshanshan@uniontech.com> Thu, 31 Jul 2025 20:00:27 +0800
dtkcore (5.7.19) unstable; urgency=medium
* Release 5.7.19
-- yeshanshan <yeshanshan@uniontech.com> Thu, 03 Jul 2025 21:11:07 +0800
dtkcore (5.7.18) unstable; urgency=medium
* Release 5.7.18
-- yeshanshan <yeshanshan@uniontech.com> Fri, 27 Jun 2025 17:07:16 +0800
dtkcore (5.7.17) unstable; urgency=medium
* Release 5.7.17
-- asterwyx <wangyixue@uniontech.com> Wed, 18 Jun 2025 18:01:08 +0800
dtkcore (5.7.16) unstable; urgency=medium dtkcore (5.7.16) unstable; urgency=medium
* fix: add missing UosMilitary edition type cases * fix: add missing UosMilitary edition type cases

2
debian/control vendored
View File

@ -5,7 +5,7 @@ Maintainer: Deepin Packages Builder <packages@deepin.com>
Build-Depends: debhelper-compat ( =12), pkg-config, Build-Depends: debhelper-compat ( =12), pkg-config,
qttools5-dev-tools, qttools5-dev, qtbase5-private-dev, doxygen, qttools5-dev-tools, qttools5-dev, qtbase5-private-dev, doxygen,
libgsettings-qt-dev, libgtest-dev, libdtkcommon-dev, cmake, libgsettings-qt-dev, libgtest-dev, libdtkcommon-dev, cmake,
libuchardet-dev, libicu-dev, libdtklog-dev libuchardet-dev, libicu-dev, libdtklog-dev, libdbus-1-dev
Standards-Version: 3.9.8 Standards-Version: 3.9.8
Package: libdtkcore5 Package: libdtkcore5

6
debian/rules vendored
View File

@ -4,6 +4,12 @@ include /usr/share/dpkg/default.mk
export QT_SELECT = qt5 export QT_SELECT = qt5
export DEB_CXXFLAGS_MAINT_APPEND = -Ofast export DEB_CXXFLAGS_MAINT_APPEND = -Ofast
# 安全编译参数
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
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
VERSION = $(DEB_VERSION_UPSTREAM) VERSION = $(DEB_VERSION_UPSTREAM)

View File

@ -79,6 +79,7 @@ public:
UosMilitaryS, // for Server UosMilitaryS, // for Server
UosDeviceEdition, UosDeviceEdition,
UosEducation, UosEducation,
UosDefense,
UosEditionCount // must at last UosEditionCount // must at last
}; };

View File

@ -35,9 +35,11 @@
#if defined(DTK_STATIC_LIB) #if defined(DTK_STATIC_LIB)
# define LIBDTKCORESHARED_EXPORT # define LIBDTKCORESHARED_EXPORT
# define D_IGNORE_DEPRECATIONS
#else #else
#if defined(LIBDTKCORE_LIBRARY) #if defined(LIBDTKCORE_LIBRARY)
# define LIBDTKCORESHARED_EXPORT Q_DECL_EXPORT # define LIBDTKCORESHARED_EXPORT Q_DECL_EXPORT
# define D_IGNORE_DEPRECATIONS
#else #else
# define LIBDTKCORESHARED_EXPORT Q_DECL_IMPORT # define LIBDTKCORESHARED_EXPORT Q_DECL_IMPORT
#endif #endif
@ -47,6 +49,10 @@
#define D_DECL_DEPRECATED_X(text) Q_DECL_HIDDEN #define D_DECL_DEPRECATED_X(text) Q_DECL_HIDDEN
#define D_DECL_DEPRECATED Q_DECL_HIDDEN #define D_DECL_DEPRECATED Q_DECL_HIDDEN
#else #else
#if defined(D_IGNORE_DEPRECATIONS)
#define D_DECL_DEPRECATED
#define D_DECL_DEPRECATED_X(text)
#else
#ifdef __GNUC__ #ifdef __GNUC__
#if __GNUC__ < 13 #if __GNUC__ < 13
#define D_DECL_DEPRECATED __attribute__((__deprecated__)) #define D_DECL_DEPRECATED __attribute__((__deprecated__))
@ -60,6 +66,7 @@
#define D_DECL_DEPRECATED_X Q_DECL_DEPRECATED_X #define D_DECL_DEPRECATED_X Q_DECL_DEPRECATED_X
#endif #endif
#endif #endif
#endif
#define DTK_VERSION_CHECK(major, minor, patch, build) ((major<<24)|(minor<<16)|(patch<<8)|build) #define DTK_VERSION_CHECK(major, minor, patch, build) ((major<<24)|(minor<<16)|(patch<<8)|build)
#define DTK_VERSION DTK_VERSION_CHECK(DTK_VERSION_MAJOR, DTK_VERSION_MINOR, DTK_VERSION_PATCH, DTK_VERSION_BUILD) #define DTK_VERSION DTK_VERSION_CHECK(DTK_VERSION_MAJOR, DTK_VERSION_MINOR, DTK_VERSION_PATCH, DTK_VERSION_BUILD)

View File

@ -26,6 +26,7 @@ QStringList LIBDTKCORESHARED_EXPORT pinyin(const QString& words, ToneStyle ts =
// support polyphonic // support polyphonic
QStringList LIBDTKCORESHARED_EXPORT firstLetters(const QString& words); QStringList LIBDTKCORESHARED_EXPORT firstLetters(const QString& words);
QStringList LIBDTKCORESHARED_EXPORT firstLetters(const QString& words, ToneStyle ts);
DCORE_END_NAMESPACE DCORE_END_NAMESPACE

View File

@ -1,5 +1,5 @@
Name: dtkcore Name: dtkcore
Version: 5.5.18 Version: 5.7.25
Release: 1%{?dist} Release: 1%{?dist}
Summary: Deepin tool kit core modules Summary: Deepin tool kit core modules
License: LGPLv3+ License: LGPLv3+

View File

@ -8,13 +8,20 @@ set(CMAKE_AUTORCC ON)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
find_package(Dtk${DTK_VERSION_MAJOR}Log REQUIRED) find_package(Dtk${DTK_VERSION_MAJOR}Log REQUIRED)
find_package(DBus1 REQUIRED)
if(LINUX) if(LINUX)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus)
if("${QT_VERSION_MAJOR}" STREQUAL "5")
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) #Dtk6 removed.
endif()
if(${QT_VERSION_MAJOR} EQUAL 5)
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) #Dtk6 removed.
elseif(${QT_VERSION_MAJOR} EQUAL 6)
if(${Qt6Core_VERSION} VERSION_GREATER_EQUAL 6.10.0)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS CorePrivate)
endif()
else()
message(FATAL_ERROR "Unsupported Qt version: ${QT_VERSION_MAJOR}")
endif()
endif() endif()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml)
find_package(DtkBuildHelper REQUIRED) find_package(DtkBuildHelper REQUIRED)
@ -24,6 +31,12 @@ find_package(ICU REQUIRED COMPONENTS uc)
pkg_check_modules(uchardet REQUIRED uchardet) pkg_check_modules(uchardet REQUIRED uchardet)
# end text encoding # end text encoding
# QObjectAutoMOC
set_property(SOURCE ../include/base/dsingleton.h PROPERTY SKIP_AUTOMOC ON)
if("${DTK_VERSION_MAJOR}" STREQUAL "6")
set_property(SOURCE ../include/util/dthreadutils.h PROPERTY SKIP_AUTOMOC ON)
endif()
# start base # start base
include(base/base.cmake) include(base/base.cmake)
# end base # end base
@ -114,6 +127,9 @@ target_compile_definitions(${LIB_NAME} PRIVATE
LIBDTKCORE_LIBRARY LIBDTKCORE_LIBRARY
) )
target_link_libraries(${LIB_NAME} PRIVATE
dbus-1
)
target_include_directories(${LIB_NAME} PRIVATE target_include_directories(${LIB_NAME} PRIVATE
${uchardet_INCLUDE_DIRS} ${uchardet_INCLUDE_DIRS}
) )

View File

@ -621,10 +621,20 @@ bool DDciFileEngine::supportsExtension(QAbstractFileEngine::Extension extension)
return extension == AtEndExtension; return extension == AtEndExtension;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
DDciFileEngine::TriStateResult DDciFileEngine::cloneTo(QAbstractFileEngine *target)
#else
bool DDciFileEngine::cloneTo(QAbstractFileEngine *target) bool DDciFileEngine::cloneTo(QAbstractFileEngine *target)
#endif
{ {
const QByteArray &data = file->dataRef(subfilePath); const QByteArray &data = file->dataRef(subfilePath);
return target->write(data.constData(), data.size()) == data.size(); auto ret = target->write(data.constData(), data.size()) == data.size();
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
return ret ? DDciFileEngine::TriStateResult::Success : DDciFileEngine::TriStateResult::Failed;
#else
return ret;
#endif
} }
bool DDciFileEngine::forceSave(bool writeFile) const bool DDciFileEngine::forceSave(bool writeFile) const

View File

@ -129,7 +129,11 @@ public:
ExtensionReturn *output = 0) override; ExtensionReturn *output = 0) override;
bool supportsExtension(Extension extension) const override; bool supportsExtension(Extension extension) const override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
TriStateResult cloneTo(QAbstractFileEngine *target) override;
#else
bool cloneTo(QAbstractFileEngine *target) override; bool cloneTo(QAbstractFileEngine *target) override;
#endif
private: private:
bool forceSave(bool writeFile = false) const; bool forceSave(bool writeFile = false) const;

View File

@ -173,13 +173,13 @@ public:
if (owner->appId == NoAppId) if (owner->appId == NoAppId)
return true; return true;
QScopedPointer<DConfigFile> file(new DConfigFile(NoAppId, owner->name, owner->subpath)); std::unique_ptr<DConfigFile> file(new DConfigFile(NoAppId, owner->name, owner->subpath));
const bool canFallbackToGeneric = !file->meta()->metaPath(prefix).isEmpty(); const bool canFallbackToGeneric = !file->meta()->metaPath(prefix).isEmpty();
if (canFallbackToGeneric) { if (canFallbackToGeneric) {
QScopedPointer<DConfigCache> cache(file->createUserCache(getuid())); std::unique_ptr<DConfigCache> cache(file->createUserCache(getuid()));
if (file->load(prefix) && cache->load(prefix)) { if (file->load(prefix) && cache->load(prefix)) {
genericConfigFile.reset(file.take()); genericConfigFile.reset(file.release());
genericConfigCache.reset(cache.take()); genericConfigCache.reset(cache.release());
} }
} }
return true; return true;
@ -326,15 +326,16 @@ public:
DSGConfig dsg_config(DSG_CONFIG, "/", QDBusConnection::systemBus()); DSGConfig dsg_config(DSG_CONFIG, "/", QDBusConnection::systemBus());
QDBusPendingReply<QDBusObjectPath> dbus_reply = dsg_config.acquireManager(owner->appId, owner->name, owner->subpath); QDBusPendingReply<QDBusObjectPath> dbus_reply = dsg_config.acquireManager(owner->appId, owner->name, owner->subpath);
const QDBusObjectPath dbus_path = dbus_reply.value(); const QDBusObjectPath dbus_path = dbus_reply.value();
if (dbus_reply.isError() || dbus_path.path().isEmpty()) { const auto path = dbus_path.path(); // 显式拷贝避免其它线程共用systemBus连接而修改dbus数据
if (dbus_reply.isError() || path.isEmpty()) {
qCWarning(cfLog, "Can't acquire config manager. error:\"%s\"", qPrintable(dbus_reply.error().message())); qCWarning(cfLog, "Can't acquire config manager. error:\"%s\"", qPrintable(dbus_reply.error().message()));
return false; return false;
} else { } else {
qCDebug(cfLog(), "dbus path=\"%s\"", qPrintable(dbus_path.path())); qCDebug(cfLog, "dbus path=\"%s\"", qPrintable(path));
config.reset(new DSGConfigManager(DSG_CONFIG_MANAGER, dbus_path.path(), config.reset(new DSGConfigManager(DSG_CONFIG_MANAGER, path,
QDBusConnection::systemBus(), owner->q_func())); QDBusConnection::systemBus(), owner->q_func()));
if (!config->isValid()) { if (!config->isValid()) {
qCWarning(cfLog(), "Can't acquire config path=\"%s\"", qPrintable(dbus_path.path())); qCWarning(cfLog, "Can't acquire config path=\"%s\"", qPrintable(path));
config.reset(); config.reset();
return false; return false;
} else { } else {
@ -370,7 +371,7 @@ public:
complexType >> list; complexType >> list;
QVariantList res; QVariantList res;
res.reserve(list.size()); res.reserve(list.size());
for (const auto &item : qAsConst(list)) { for (const auto &item : std::as_const(list)) {
res << decodeQDBusArgument(item); res << decodeQDBusArgument(item);
} }
return res; return res;

View File

@ -1407,6 +1407,7 @@ DConfigFile::DConfigFile(const DConfigFile &other)
D_D(DConfigFile); D_D(DConfigFile);
auto cache = new DConfigCacheImpl(d->configKey, InvalidUID, true); auto cache = new DConfigCacheImpl(d->configKey, InvalidUID, true);
cache->values = other.d_func()->globalCache->values; cache->values = other.d_func()->globalCache->values;
cache->cachePrefix = other.d_func()->globalCache->cachePrefix;
d->globalCache = cache; d->globalCache = cache;
} }

View File

@ -12,13 +12,10 @@
#include <QByteArray> #include <QByteArray>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QDBusUnixFileDescriptor>
#include <QDBusReply>
#include <QRegularExpression> #include <QRegularExpression>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QDBusConnectionInterface>
#include <DDBusInterface> #include <dbus/dbus.h>
#ifdef QT_DEBUG #ifdef QT_DEBUG
Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg") Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg")
@ -28,6 +25,198 @@ Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg", QtInfoMsg)
DCORE_BEGIN_NAMESPACE DCORE_BEGIN_NAMESPACE
// D-Bus resource deleters for RAII management
static void dbusErrorDeleter(DBusError *error) {
if (error) { dbus_error_free(error); delete error; }
}
static void dbusConnectionDeleter(DBusConnection *conn) {
if (conn) dbus_connection_unref(conn);
}
static void dbusMessageDeleter(DBusMessage *msg) {
if (msg) dbus_message_unref(msg);
}
// D-Bus utility functions using libdbus-1
static bool checkDBusServiceActivatable(const QByteArray &service)
{
auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter);
dbus_error_init(error.get());
DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, error.get());
if (dbus_error_is_set(error.get())) {
qCWarning(dsgApp) << "Failed to connect to session bus:" << error->message;
return false;
}
if (!connection) {
qCWarning(dsgApp) << "Failed to get session bus connection";
return false;
}
auto connGuard = std::unique_ptr<DBusConnection, void(*)(DBusConnection*)>(connection, dbusConnectionDeleter);
// Create method call to check if service is registered
DBusMessage *msg = dbus_message_new_method_call(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"NameHasOwner"
);
if (!msg) {
qCWarning(dsgApp) << "Failed to create D-Bus message";
return false;
}
auto msgGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(msg, dbusMessageDeleter);
{
const char *serviceName = service.constData();
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &serviceName, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to append arguments to D-Bus message";
return false;
}
}
// Send message and get reply
DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, msg, 1000, error.get());
msgGuard.reset(); // msg is consumed by the call
if (dbus_error_is_set(error.get())) {
qCWarning(dsgApp) << "D-Bus call failed:" << error->message;
return false;
}
if (!reply) {
qCWarning(dsgApp) << "No reply received from D-Bus";
return false;
}
auto replyGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply, dbusMessageDeleter);
dbus_bool_t hasOwner = FALSE;
if (!dbus_message_get_args(reply, error.get(), DBUS_TYPE_BOOLEAN, &hasOwner, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to parse D-Bus reply:" << error->message;
return false;
}
if (!hasOwner) {
return false;
}
// Check if service is activatable
DBusMessage *msg2 = dbus_message_new_method_call(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"ListActivatableNames"
);
if (!msg2) {
qCWarning(dsgApp) << "Failed to create ListActivatableNames message";
return false;
}
auto msg2Guard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(msg2, dbusMessageDeleter);
DBusMessage *reply2 = dbus_connection_send_with_reply_and_block(connection, msg2, 1000, error.get());
if (dbus_error_is_set(error.get())) {
qCWarning(dsgApp) << "ListActivatableNames call failed:" << error->message;
return false;
}
if (!reply2) {
return false;
}
auto reply2Guard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply2, dbusMessageDeleter);
DBusMessageIter iter, array_iter;
dbus_message_iter_init(reply2, &iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
return false;
}
dbus_message_iter_recurse(&iter, &array_iter);
bool found = false;
while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRING) {
const char *name;
dbus_message_iter_get_basic(&array_iter, &name);
if (service == name) {
found = true;
break;
}
dbus_message_iter_next(&array_iter);
}
return found;
}
static QByteArray callDBusIdentifyMethod(const QByteArray &serviceName, const QByteArray &path,
const QByteArray &interface, int pidfd)
{
auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter);
dbus_error_init(error.get());
DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, error.get());
if (dbus_error_is_set(error.get())) {
qCWarning(dsgApp) << "Failed to connect to session bus:" << error->message;
return QByteArray();
}
if (!connection) {
qCWarning(dsgApp) << "Failed to get session bus connection";
return QByteArray();
}
auto connGuard = std::unique_ptr<DBusConnection, void(*)(DBusConnection*)>(connection, dbusConnectionDeleter);
// Create method call - string data is now managed by caller
DBusMessage *msg = dbus_message_new_method_call(
serviceName.constData(),
path.constData(),
interface.constData(),
"Identify"
);
if (!msg) {
qCWarning(dsgApp) << "Failed to create D-Bus message";
return QByteArray();
}
auto msgGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(msg, dbusMessageDeleter);
// Append Unix file descriptor
if (!dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &pidfd, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to append Unix FD to D-Bus message";
return QByteArray();
}
// Send message and get reply
DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, msg, 5000, error.get());
msgGuard.reset(); // msg is consumed by the call
if (dbus_error_is_set(error.get())) {
qCWarning(dsgApp) << "Identify from AM failed:" << error->message;
return QByteArray();
}
if (!reply) {
qCWarning(dsgApp) << "No reply received from Identify method";
return QByteArray();
}
auto replyGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply, dbusMessageDeleter);
const char *result;
if (!dbus_message_get_args(reply, error.get(), DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to parse Identify reply:" << error->message;
return QByteArray();
}
QByteArray appId = QByteArray(result);
qCInfo(dsgApp) << "AppId is fetched from AM, and value is " << appId;
return appId;
}
static inline QByteArray getSelfAppId() { static inline QByteArray getSelfAppId() {
// The env is set by the application starter(eg, org.desktopspec.ApplicationManager service) // The env is set by the application starter(eg, org.desktopspec.ApplicationManager service)
QByteArray selfId = qgetenv("DSG_APP_ID"); QByteArray selfId = qgetenv("DSG_APP_ID");
@ -36,17 +225,9 @@ static inline QByteArray getSelfAppId() {
return DSGApplication::getId(QCoreApplication::applicationPid()); return DSGApplication::getId(QCoreApplication::applicationPid());
} }
static bool isServiceActivatable(const QString &service) static bool isServiceActivatable(const QByteArray &service)
{ {
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(service)) return checkDBusServiceActivatable(service);
return false;
const QDBusReply<QStringList> activatableNames = QDBusConnection::sessionBus().interface()->
callWithArgumentList(QDBus::AutoDetect,
QLatin1String("ListActivatableNames"),
QList<QVariant>());
return activatableNames.value().contains(service);
} }
// Format appId to valid. // Format appId to valid.
@ -91,6 +272,18 @@ QByteArray DSGApplication::id()
return result; return result;
} }
/**
* Get application ID for a given process ID
*
* This function has been updated to use libdbus-1 instead of Qt D-Bus to fix
* the bug(pms:BUG-278055) where calling this function before QCoreApplication
* initialization would fail. This is particularly important when the service
* is being started by D-Bus activation and DSGApplication::id() is called
* during early startup.
*
* @param pid Process ID to get the application ID for
* @return Application ID as QByteArray, or empty array on failure
*/
QByteArray DSGApplication::getId(qint64 pid) QByteArray DSGApplication::getId(qint64 pid)
{ {
if (!isServiceActivatable("org.desktopspec.ApplicationManager1")) { if (!isServiceActivatable("org.desktopspec.ApplicationManager1")) {
@ -104,21 +297,13 @@ QByteArray DSGApplication::getId(qint64 pid)
return QByteArray(); return QByteArray();
} }
DDBusInterface infc("org.desktopspec.ApplicationManager1", QByteArray appId = callDBusIdentifyMethod("org.desktopspec.ApplicationManager1",
"/org/desktopspec/ApplicationManager1", "/org/desktopspec/ApplicationManager1",
"org.desktopspec.ApplicationManager1"); "org.desktopspec.ApplicationManager1",
pidfd);
QDBusReply<QString> reply = infc.call("Identify", QVariant::fromValue(QDBusUnixFileDescriptor(pidfd)));
// see QDBusUnixFileDescriptor: The original file descriptor is not touched and must be closed by the user. // see QDBusUnixFileDescriptor: The original file descriptor is not touched and must be closed by the user.
close(pidfd); close(pidfd);
if (!reply.isValid()) {
qCWarning(dsgApp) << "Identify from AM failed." << reply.error().message();
return QByteArray();
}
const QByteArray appId = reply.value().toLatin1();
qCInfo(dsgApp) << "AppId is fetched from AM, and value is " << appId;
return appId; return appId;
} }

View File

@ -93,7 +93,14 @@ public:
struct OSBuild { struct OSBuild {
OSBuild():A(0), B(0), C(0), D(0), xyz(100){ OSBuild():A(0), B(0), C(0), D(0), xyz(100){
} }
uint A, B, C, D, E, xyz; // ABCDE.xyz
/* ABCDE.xyz模式
A B C D E x yz
线 线
1 1 1 1 1 1 2
------------------------- 09A~Z --------------------------- 1 00~99AA~ZZ
*/
uint A, B, C, D, E, xyz;
}; };
MinVersion minVersion; MinVersion minVersion;
@ -139,9 +146,12 @@ bool DSysInfoPrivate::splitA_BC_DMode()
minVersion.D = minv % 10; minVersion.D = minv % 10;
} else if (minorVersion.length() > 0) { } else if (minorVersion.length() > 0) {
const QString D = minorVersion.right(1); const QString D = minorVersion.right(1);
if (D.contains(QRegularExpression("[0-9A-Z]"))) { const QChar ch = D.at(0);
// 0-9...A-Z if (ch.isDigit()) {
minVersion.D = 10 + static_cast<uint>(D.data()->toLatin1() - 'A'); minVersion.D = static_cast<uint>(ch.unicode() - '0');
} else if (ch >= 'A' && ch <= 'Z') {
// 0-9...A-Z -> 10..35
minVersion.D = 10 + static_cast<uint>(ch.unicode() - 'A');
} else { } else {
qWarning() << "invalid minorVersion"; qWarning() << "invalid minorVersion";
minVersion.D = 0; minVersion.D = 0;
@ -266,19 +276,24 @@ bool DSysInfoPrivate::ensureOsVersion()
D_ASSET_EXIT(left.size() == 5, "OsBuild version(ls) invalid!"); D_ASSET_EXIT(left.size() == 5, "OsBuild version(ls) invalid!");
int idx = 0; int idx = 0;
osBuild.A = left.value(idx++, "0").toUInt(&ok); auto parseDigitOrAZ = [&](const QString &s, bool *outOk) -> uint {
if (s.isEmpty()) { if (outOk) *outOk = false; return 0u; }
const QChar ch = s.at(0);
if (ch.isDigit()) { if (outOk) *outOk = true; return static_cast<uint>(ch.unicode() - '0'); }
if (ch >= 'A' && ch <= 'Z') { if (outOk) *outOk = true; return static_cast<uint>(ch.toLatin1()); }
if (outOk) *outOk = false;
return 0u;
};
osBuild.A = parseDigitOrAZ(left.value(idx++, "0"), &ok);
D_ASSET_EXIT(ok, "OsBuild version(A) invalid!"); D_ASSET_EXIT(ok, "OsBuild version(A) invalid!");
osBuild.B = left.value(idx++, "0").toUInt(&ok); osBuild.B = parseDigitOrAZ(left.value(idx++, "0"), &ok);
D_ASSET_EXIT(ok, "OsBuild version(B) invalid!"); D_ASSET_EXIT(ok, "OsBuild version(B) invalid!");
osBuild.C = left.value(idx++, "0").toUInt(&ok); osBuild.C = parseDigitOrAZ(left.value(idx++, "0"), &ok);
if (!ok) { D_ASSET_EXIT(ok, "OsBuild version(C) invalid!");
auto c = left.value(idx-1, "0").toLatin1(); osBuild.D = parseDigitOrAZ(left.value(idx++, "0"), &ok);
D_ASSET_EXIT(c.size()>0, "OsBuild version(C) invalid!");
osBuild.C = uint(c.at(0));
}
osBuild.D = left.value(idx++, "0").toUInt(&ok);
D_ASSET_EXIT(ok, "OsBuild version(D) invalid!"); D_ASSET_EXIT(ok, "OsBuild version(D) invalid!");
osBuild.E = left.value(idx++, "0").toUInt(&ok); osBuild.E = parseDigitOrAZ(left.value(idx++, "0"), &ok);
D_ASSET_EXIT(ok, "OsBuild version(E) invalid!"); D_ASSET_EXIT(ok, "OsBuild version(E) invalid!");
// xyz // xyz
@ -682,10 +697,13 @@ DSysInfo::UosEdition DSysInfo::uosEditionType()
case 3: case 3:
return UosEuler; return UosEuler;
case 4: case 4:
case 9:
return UosMilitaryS; return UosMilitaryS;
case 5: case 5:
return UosDeviceEdition; return UosDeviceEdition;
case 9:
return UosEducation; // 服务器 教育版(UT-3-PP-PR-001_操作系统标识与产品版本号规范_20250905)
case 'A':
return UosDefense; // 服务器 国防版
default: default:
break; break;
} }

View File

@ -195,12 +195,21 @@ QAbstractFileEngine::FileFlags DCapFSFileEngine::fileFlags(QAbstractFileEngine::
return ret; return ret;
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
DCapFSFileEngine::TriStateResult DCapFSFileEngine::cloneTo(QAbstractFileEngine *target)
#else
bool DCapFSFileEngine::cloneTo(QAbstractFileEngine *target) bool DCapFSFileEngine::cloneTo(QAbstractFileEngine *target)
#endif
{ {
D_DC(DCapFSFileEngine); D_DC(DCapFSFileEngine);
const QString targetPath = target->fileName(DCapFSFileEngine::AbsolutePathName); const QString targetPath = target->fileName(DCapFSFileEngine::AbsolutePathName);
if (!d->canReadWrite(targetPath)) if (!d->canReadWrite(targetPath)) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
return DCapFSFileEngine::TriStateResult::Failed;
#else
return false; return false;
#endif
}
return QFSFileEngine::cloneTo(target); return QFSFileEngine::cloneTo(target);
} }

View File

@ -123,7 +123,7 @@ static bool renameFile(const QFileInfo &fileInfo, const QString &target, QString
} }
} }
if (!QDir().rmdir(fileInfo.filePath())) { if (!QDir().rename(fileInfo.filePath(), target)) {
if (errorString) { if (errorString) {
*errorString = QString("Cannot remove the %1 dir").arg(fileInfo.filePath()); *errorString = QString("Cannot remove the %1 dir").arg(fileInfo.filePath());
} }
@ -183,11 +183,13 @@ bool DTrashManager::moveToTrash(const QString &filePath, bool followSymlink)
} }
QDir trashDir(TRASH_FILES_PATH); QDir trashDir(TRASH_FILES_PATH);
QStorageInfo storageInfo(fileInfo.filePath()); if (followSymlink && fileInfo.isSymLink()) {
QStorageInfo trashStorageInfo(trashDir); QStorageInfo storageInfo(fileInfo.filePath());
QStorageInfo trashStorageInfo(trashDir);
if (storageInfo != trashStorageInfo) { if (storageInfo != trashStorageInfo) {
return false; return false;
}
} }
if (!trashDir.mkpath(TRASH_INFO_PATH)) { if (!trashDir.mkpath(TRASH_INFO_PATH)) {

View File

@ -48,7 +48,13 @@ public:
#endif #endif
bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
FileFlags fileFlags(FileFlags type) const override; FileFlags fileFlags(FileFlags type) const override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
TriStateResult cloneTo(QAbstractFileEngine *target) override;
#else
bool cloneTo(QAbstractFileEngine *target) override; bool cloneTo(QAbstractFileEngine *target) override;
#endif
bool setSize(qint64 size) override; bool setSize(qint64 size) override;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override; QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1) #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1)

View File

@ -72,7 +72,7 @@ dconfig_org_deepin_dtk_preference *DLogManagerPrivate::createDConfig(const QStri
void DLogManagerPrivate::initLoggingRules() void DLogManagerPrivate::initLoggingRules()
{ {
if (qEnvironmentVariableIsSet("DTK_DISABLED_LOGGING_RULES")) if (qEnvironmentVariableIsSet("DTK_DISABLED_LOGGING_RULES") || qEnvironmentVariableIsSet("QT_LOGGING_RULES"))
return; return;
// 1. 未指定 fallbackId 时,以 dsgAppId 为准 // 1. 未指定 fallbackId 时,以 dsgAppId 为准
@ -213,7 +213,7 @@ QString DLogManager::getlogFilePath()
if (!QDir(cachePath).exists()) { if (!QDir(cachePath).exists()) {
QDir(cachePath).mkpath(cachePath); QDir(cachePath).mkpath(cachePath);
} }
instance()->d_func()->m_logPath = instance()->joinPath(cachePath, QString("%1.log").arg(qApp->applicationName())); instance()->d_func()->m_logPath = instance()->joinPath(cachePath, QString("%1.log").arg(QCoreApplication::applicationName()));
} }
return QDir::toNativeSeparators(DLogManager::instance()->d_func()->m_logPath); return QDir::toNativeSeparators(DLogManager::instance()->d_func()->m_logPath);

View File

@ -1,7 +1,7 @@
/** /**
* This file is generated by dconfig2cpp. * This file is generated by dconfig2cpp.
* Command line arguments: ./build5/tools/dconfig2cpp/dconfig2cpp /usr/share/dsg/configs/org.deepin.dtk.preference.json * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp /usr/share/dsg/configs/org.deepin.dtk.preference.json
* Generation time: 2025-05-08T16:56:17 * Generation time: 2025-08-20T15:40:55
* JSON file version: 1.0 * JSON file version: 1.0
* *
* WARNING: DO NOT MODIFY THIS FILE MANUALLY. * WARNING: DO NOT MODIFY THIS FILE MANUALLY.
@ -113,6 +113,7 @@ public:
~dconfig_org_deepin_dtk_preference() { ~dconfig_org_deepin_dtk_preference() {
if (m_config.loadRelaxed()) { if (m_config.loadRelaxed()) {
m_config.loadRelaxed()->deleteLater(); m_config.loadRelaxed()->deleteLater();
m_config.storeRelaxed(nullptr);
} }
} }
@ -565,6 +566,8 @@ private:
updateValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut)); updateValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut));
} }
if (!m_config.loadRelaxed())
return;
connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) {
updateValue(key); updateValue(key);
}, Qt::DirectConnection); }, Qt::DirectConnection);
@ -573,6 +576,8 @@ private:
Q_EMIT configInitializeSucceed(config); Q_EMIT configInitializeSucceed(config);
} }
void updateValue(const QString &key, const QVariant &fallback = QVariant()) { void updateValue(const QString &key, const QVariant &fallback = QVariant()) {
if (!m_config.loadRelaxed())
return;
Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread());
const QVariant &value = m_config.loadRelaxed()->value(key, fallback); const QVariant &value = m_config.loadRelaxed()->value(key, fallback);
if (key == QStringLiteral("autoDisplayFeature")) { if (key == QStringLiteral("autoDisplayFeature")) {
@ -738,8 +743,8 @@ private:
bool p_enableDtkAnimations { false }; bool p_enableDtkAnimations { false };
bool p_featureUpdated { false }; bool p_featureUpdated { false };
bool p_keyboardsearchDisabled { false }; bool p_keyboardsearchDisabled { false };
// Default value: "" // Default value: "*.debug=false"
QString p_rules { QLatin1String("") }; QString p_rules { QStringLiteral(u"\u002a\u002e\u0064\u0065\u0062\u0075\u0067\u003d\u0066\u0061\u006c\u0073\u0065") };
qlonglong p_scrollBarPolicy { 0 }; qlonglong p_scrollBarPolicy { 0 };
qlonglong p_sizeMode { 0 }; qlonglong p_sizeMode { 0 };
qlonglong p_themeType { 0 }; qlonglong p_themeType { 0 };

View File

@ -43,6 +43,13 @@ static QVariant demarshall(const QMetaProperty &metaProperty, const QVariant &va
if (value.userType() == qMetaTypeId<QDBusArgument>()) { if (value.userType() == qMetaTypeId<QDBusArgument>()) {
QDBusArgument dbusArg = value.value<QDBusArgument>(); QDBusArgument dbusArg = value.value<QDBusArgument>();
QDBusMetaType::demarshall(dbusArg, PropType(metaProperty), result.data()); QDBusMetaType::demarshall(dbusArg, PropType(metaProperty), result.data());
} else {
auto copy = value;
if (copy.convert(PropType(metaProperty))) {
result = copy;
} else {
qDebug() << "Failed to convert value type" << value.typeName() << "to property type" << metaProperty.typeName();
}
} }
return result; return result;

View File

@ -211,11 +211,23 @@ QStringList pinyin(const QString &words, ToneStyle ts, bool *ok)
\return pinyin first letters list of the words \return pinyin first letters list of the words
*/ */
QStringList firstLetters(const QString &words) QStringList firstLetters(const QString &words)
{
return firstLetters(words, TS_Tone);
}
/*!
\fn QStringList Dtk::Core::firstLetters(const QString &words)
\brief Convert Chinese characters to Pinyin firstLetters list
\brief with controllable tone style.
\return pinyin first letters list of the words
*/
QStringList firstLetters(const QString &words, ToneStyle ts)
{ {
QList<QStringList> result; QList<QStringList> result;
bool ok = false; bool ok = false;
for (const QChar &w : words) { for (const QChar &w : words) {
QStringList pys = pinyin(w, TS_Tone, &ok); QStringList pys = pinyin(w, ts, &ok);
if (!ok) { if (!ok) {
result << QStringList(w); result << QStringList(w);
continue; continue;

View File

@ -13,6 +13,7 @@
#include <QUrl> #include <QUrl>
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
#include <QStringConverter> #include <QStringConverter>
#include <QTimeZone>
#endif #endif
DCORE_BEGIN_NAMESPACE DCORE_BEGIN_NAMESPACE
@ -67,7 +68,11 @@ bool DRecentManager::addItem(const QString &uri, DRecentData &data)
QFile file(RECENT_PATH); QFile file(RECENT_PATH);
file.open(QIODevice::ReadWrite | QIODevice::Text); file.open(QIODevice::ReadWrite | QIODevice::Text);
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QString dateTime = QDateTime::currentDateTime().toTimeZone(QTimeZone::UTC).toString(Qt::ISODate);
#else
QString dateTime = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate); QString dateTime = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
#endif
QDomDocument doc; QDomDocument doc;
if (!doc.setContent(&file)) { if (!doc.setContent(&file)) {

View File

@ -229,7 +229,21 @@ bool DVtableHook::hasVtable(const void *obj)
{ {
quintptr **_obj = (quintptr**)(obj); quintptr **_obj = (quintptr**)(obj);
return objToGhostVfptr.contains(_obj); // 验证 vtable 是否匹配
quintptr *ghost_vtable = objToGhostVfptr.value(obj);
if (!ghost_vtable) {
return false;
}
// 检查当前对象的 vtable 指针是否指向我们记录的 ghost vtable
if (*_obj != adjustToEntry(ghost_vtable)) {
// vtable 不匹配,说明地址被重用了
qCDebug(vtableHook) << "hasVtable: vtable mismatch! Address reused by different object."
<< "obj:" << QString("0x%1").arg((quintptr)obj, 0, 16);
return false;
}
return true;
} }
void DVtableHook::resetVtable(const void *obj) void DVtableHook::resetVtable(const void *obj)

View File

@ -20,6 +20,12 @@ if(LINUX)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
if("${QT_VERSION_MAJOR}" STREQUAL "5") if("${QT_VERSION_MAJOR}" STREQUAL "5")
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt)
elseif(${QT_VERSION_MAJOR} EQUAL 6)
if(${Qt6Core_VERSION} VERSION_GREATER_EQUAL 6.10.0)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS CorePrivate)
endif()
else()
message(FATAL_ERROR "Unsupported Qt version: ${QT_VERSION_MAJOR}")
endif() endif()
endif() endif()
@ -28,6 +34,8 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Test) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Test)
find_package(GTest REQUIRED) find_package(GTest REQUIRED)
include(GoogleTest)
# for test.so # for test.so
set(TEST_SO_NAME vtabletest${DTK_VERSION_MAJOR}) set(TEST_SO_NAME vtabletest${DTK_VERSION_MAJOR})
add_subdirectory(./testso) add_subdirectory(./testso)
@ -110,4 +118,4 @@ target_include_directories( ${BIN_NAME} PUBLIC
./testso/ ./testso/
) )
add_test(NAME ${BIN_NAME} COMMAND ${BIN_NAME}) gtest_discover_tests(${BIN_NAME})

View File

@ -68,5 +68,11 @@ TEST_F(ut_DPinyin, firstLetters)
bool isPermutation = std::is_permutation(ls.begin() , ls.end(), letters.begin()); bool isPermutation = std::is_permutation(ls.begin() , ls.end(), letters.begin());
ASSERT_TRUE(isPermutation); ASSERT_TRUE(isPermutation);
QString words2("安全中心");
QStringList && result = firstLetters(words2, TS_NoneTone);
ASSERT_TRUE(result.count() == 1);
ASSERT_TRUE(result.constFirst() == "aqzx");
ASSERT_TRUE(result.constFirst() != firstLetters(words2).constFirst());
} }

View File

@ -3,6 +3,13 @@ set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
if(${QT_VERSION_MAJOR} EQUAL 6)
if(${Qt6Core_VERSION} VERSION_GREATER_EQUAL 6.10.0)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS CorePrivate)
endif()
endif()
add_definitions(-DDTK_NO_PROJECT) add_definitions(-DDTK_NO_PROJECT)
# start dci # start dci
include(../../src/dci/dci.cmake) include(../../src/dci/dci.cmake)

View File

@ -354,6 +354,7 @@ int main(int argc, char *argv[]) {
headerStream << " ~" << className << R"(() { headerStream << " ~" << className << R"(() {
if (m_config.loadRelaxed()) { if (m_config.loadRelaxed()) {
m_config.loadRelaxed()->deleteLater(); m_config.loadRelaxed()->deleteLater();
m_config.storeRelaxed(nullptr);
} }
} }
@ -458,6 +459,8 @@ int main(int argc, char *argv[]) {
headerStream << " }\n"; headerStream << " }\n";
} }
headerStream << R"( headerStream << R"(
if (!m_config.loadRelaxed())
return;
connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) {
updateValue(key); updateValue(key);
}, Qt::DirectConnection); }, Qt::DirectConnection);
@ -466,6 +469,8 @@ int main(int argc, char *argv[]) {
Q_EMIT configInitializeSucceed(config); Q_EMIT configInitializeSucceed(config);
} }
void updateValue(const QString &key, const QVariant &fallback = QVariant()) { void updateValue(const QString &key, const QVariant &fallback = QVariant()) {
if (!m_config.loadRelaxed())
return;
Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread());
const QVariant &value = m_config.loadRelaxed()->value(key, fallback); const QVariant &value = m_config.loadRelaxed()->value(key, fallback);
)"; )";

View File

@ -4,6 +4,12 @@ set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
if(${QT_VERSION_MAJOR} EQUAL 6)
if(${Qt6Core_VERSION} VERSION_GREATER_EQUAL 6.10.0)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS CorePrivate)
endif()
endif()
add_definitions(-DDTK_NO_PROJECT) add_definitions(-DDTK_NO_PROJECT)
# start dci # start dci
set(dci_SRCS set(dci_SRCS

View File

@ -5,6 +5,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus)
if(${QT_VERSION_MAJOR} EQUAL 6)
if (${Qt6DBus_VERSION} VERSION_GREATER_EQUAL 6.10.0)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBusPrivate)
endif()
endif()
add_executable(${BIN_NAME} add_executable(${BIN_NAME}
qdbusxml2cpp.cpp qdbusxml2cpp.cpp
) )

View File

@ -598,7 +598,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
<< endl; << endl;
} }
QSet<QString> annotations; QStringList annotations;
for (const QDBusIntrospection::Interface *interface : interfaces) { for (const QDBusIntrospection::Interface *interface : interfaces) {
for (const auto &method : interface->methods) { for (const auto &method : interface->methods) {
for (int i(0); i != method.outputArgs.size(); ++i) { for (int i(0); i != method.outputArgs.size(); ++i) {
@ -638,6 +638,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
} }
} }
annotations.removeDuplicates();
if (!skipIncludeAnnotations) { if (!skipIncludeAnnotations) {
for (const QString &annotation : annotations) { for (const QString &annotation : annotations) {
if (annotation.indexOf('<') == -1) { if (annotation.indexOf('<') == -1) {