Compare commits

..

22 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
30 changed files with 372 additions and 131 deletions

View File

@ -5,6 +5,60 @@ 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

View File

@ -1 +1 @@
5.7.19
5.7.25

View File

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

36
debian/changelog vendored
View File

@ -1,3 +1,39 @@
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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,10 +12,16 @@ find_package(DBus1 REQUIRED)
if(LINUX)
find_package(PkgConfig REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus)
if("${QT_VERSION_MAJOR}" STREQUAL "5")
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) #Dtk6 removed.
endif()
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()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml)
find_package(DtkBuildHelper REQUIRED)
@ -25,6 +31,12 @@ find_package(ICU REQUIRED COMPONENTS uc)
pkg_check_modules(uchardet REQUIRED uchardet)
# 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
include(base/base.cmake)
# end base

View File

@ -621,10 +621,20 @@ bool DDciFileEngine::supportsExtension(QAbstractFileEngine::Extension extension)
return extension == AtEndExtension;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
DDciFileEngine::TriStateResult DDciFileEngine::cloneTo(QAbstractFileEngine *target)
#else
bool DDciFileEngine::cloneTo(QAbstractFileEngine *target)
#endif
{
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

View File

@ -129,7 +129,11 @@ public:
ExtensionReturn *output = 0) 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;
#endif
private:
bool forceSave(bool writeFile = false) const;

View File

@ -173,13 +173,13 @@ public:
if (owner->appId == NoAppId)
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();
if (canFallbackToGeneric) {
QScopedPointer<DConfigCache> cache(file->createUserCache(getuid()));
std::unique_ptr<DConfigCache> cache(file->createUserCache(getuid()));
if (file->load(prefix) && cache->load(prefix)) {
genericConfigFile.reset(file.take());
genericConfigCache.reset(cache.take());
genericConfigFile.reset(file.release());
genericConfigCache.reset(cache.release());
}
}
return true;
@ -326,15 +326,16 @@ public:
DSGConfig dsg_config(DSG_CONFIG, "/", QDBusConnection::systemBus());
QDBusPendingReply<QDBusObjectPath> dbus_reply = dsg_config.acquireManager(owner->appId, owner->name, owner->subpath);
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()));
return false;
} else {
qCDebug(cfLog(), "dbus path=\"%s\"", qPrintable(dbus_path.path()));
config.reset(new DSGConfigManager(DSG_CONFIG_MANAGER, dbus_path.path(),
qCDebug(cfLog, "dbus path=\"%s\"", qPrintable(path));
config.reset(new DSGConfigManager(DSG_CONFIG_MANAGER, path,
QDBusConnection::systemBus(), owner->q_func()));
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();
return false;
} else {
@ -370,7 +371,7 @@ public:
complexType >> list;
QVariantList res;
res.reserve(list.size());
for (const auto &item : qAsConst(list)) {
for (const auto &item : std::as_const(list)) {
res << decodeQDBusArgument(item);
}
return res;

View File

@ -25,16 +25,28 @@ Q_LOGGING_CATEGORY(dsgApp, "dtk.core.dsg", QtInfoMsg)
DCORE_BEGIN_NAMESPACE
// D-Bus utility functions using libdbus-1
static bool checkDBusServiceActivatable(const QString &service)
{
DBusError error;
dbus_error_init(&error);
// D-Bus resource deleters for RAII management
static void dbusErrorDeleter(DBusError *error) {
if (error) { dbus_error_free(error); delete error; }
}
DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
qCWarning(dsgApp) << "Failed to connect to session bus:" << error.message;
dbus_error_free(&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;
}
@ -42,6 +54,7 @@ static bool checkDBusServiceActivatable(const QString &service)
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(
@ -53,86 +66,73 @@ static bool checkDBusServiceActivatable(const QString &service)
if (!msg) {
qCWarning(dsgApp) << "Failed to create D-Bus message";
dbus_connection_unref(connection);
return false;
}
auto msgGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(msg, dbusMessageDeleter);
const char *serviceName = service.toUtf8().constData();
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &serviceName, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to append arguments to D-Bus message";
dbus_message_unref(msg);
dbus_connection_unref(connection);
return false;
{
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);
dbus_message_unref(msg);
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)) {
qCWarning(dsgApp) << "D-Bus call failed:" << error.message;
dbus_error_free(&error);
dbus_connection_unref(connection);
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";
dbus_connection_unref(connection);
return false;
}
auto replyGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply, dbusMessageDeleter);
dbus_bool_t hasOwner = FALSE;
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &hasOwner, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to parse D-Bus reply:" << error.message;
dbus_error_free(&error);
dbus_message_unref(reply);
dbus_connection_unref(connection);
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;
}
dbus_message_unref(reply);
if (!hasOwner) {
dbus_connection_unref(connection);
return false;
}
// Check if service is activatable
msg = dbus_message_new_method_call(
DBusMessage *msg2 = dbus_message_new_method_call(
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"ListActivatableNames"
);
if (!msg) {
if (!msg2) {
qCWarning(dsgApp) << "Failed to create ListActivatableNames message";
dbus_connection_unref(connection);
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;
}
reply = dbus_connection_send_with_reply_and_block(connection, msg, 1000, &error);
dbus_message_unref(msg);
if (dbus_error_is_set(&error)) {
qCWarning(dsgApp) << "ListActivatableNames call failed:" << error.message;
dbus_error_free(&error);
dbus_connection_unref(connection);
return false;
}
if (!reply) {
dbus_connection_unref(connection);
if (!reply2) {
return false;
}
auto reply2Guard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply2, dbusMessageDeleter);
DBusMessageIter iter, array_iter;
dbus_message_iter_init(reply, &iter);
dbus_message_iter_init(reply2, &iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
dbus_message_unref(reply);
dbus_connection_unref(connection);
return false;
}
@ -142,29 +142,25 @@ static bool checkDBusServiceActivatable(const QString &service)
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 == QString::fromUtf8(name)) {
if (service == name) {
found = true;
break;
}
dbus_message_iter_next(&array_iter);
}
dbus_message_unref(reply);
dbus_connection_unref(connection);
dbus_error_free(&error);
return found;
}
static QByteArray callDBusIdentifyMethod(const QString &service, const QString &path, const QString &interface, int pidfd)
static QByteArray callDBusIdentifyMethod(const QByteArray &serviceName, const QByteArray &path,
const QByteArray &interface, int pidfd)
{
DBusError error;
dbus_error_init(&error);
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);
if (dbus_error_is_set(&error)) {
qCWarning(dsgApp) << "Failed to connect to session bus:" << error.message;
dbus_error_free(&error);
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();
}
@ -172,62 +168,52 @@ static QByteArray callDBusIdentifyMethod(const QString &service, const QString &
qCWarning(dsgApp) << "Failed to get session bus connection";
return QByteArray();
}
auto connGuard = std::unique_ptr<DBusConnection, void(*)(DBusConnection*)>(connection, dbusConnectionDeleter);
// Create method call
// Create method call - string data is now managed by caller
DBusMessage *msg = dbus_message_new_method_call(
service.toUtf8().constData(),
path.toUtf8().constData(),
interface.toUtf8().constData(),
serviceName.constData(),
path.constData(),
interface.constData(),
"Identify"
);
if (!msg) {
qCWarning(dsgApp) << "Failed to create D-Bus message";
dbus_connection_unref(connection);
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";
dbus_message_unref(msg);
dbus_connection_unref(connection);
return QByteArray();
}
// Send message and get reply
DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, msg, 5000, &error);
dbus_message_unref(msg);
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)) {
qCWarning(dsgApp) << "Identify from AM failed:" << error.message;
dbus_error_free(&error);
dbus_connection_unref(connection);
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";
dbus_connection_unref(connection);
return QByteArray();
}
auto replyGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(reply, dbusMessageDeleter);
const char *result;
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID)) {
qCWarning(dsgApp) << "Failed to parse Identify reply:" << error.message;
dbus_error_free(&error);
dbus_message_unref(reply);
dbus_connection_unref(connection);
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;
dbus_message_unref(reply);
dbus_connection_unref(connection);
dbus_error_free(&error);
return appId;
}
@ -239,7 +225,7 @@ static inline QByteArray getSelfAppId() {
return DSGApplication::getId(QCoreApplication::applicationPid());
}
static bool isServiceActivatable(const QString &service)
static bool isServiceActivatable(const QByteArray &service)
{
return checkDBusServiceActivatable(service);
}
@ -286,6 +272,18 @@ QByteArray DSGApplication::id()
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)
{
if (!isServiceActivatable("org.desktopspec.ApplicationManager1")) {

View File

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

View File

@ -195,12 +195,21 @@ QAbstractFileEngine::FileFlags DCapFSFileEngine::fileFlags(QAbstractFileEngine::
return ret;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
DCapFSFileEngine::TriStateResult DCapFSFileEngine::cloneTo(QAbstractFileEngine *target)
#else
bool DCapFSFileEngine::cloneTo(QAbstractFileEngine *target)
#endif
{
D_DC(DCapFSFileEngine);
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;
#endif
}
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) {
*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);
QStorageInfo storageInfo(fileInfo.filePath());
QStorageInfo trashStorageInfo(trashDir);
if (followSymlink && fileInfo.isSymLink()) {
QStorageInfo storageInfo(fileInfo.filePath());
QStorageInfo trashStorageInfo(trashDir);
if (storageInfo != trashStorageInfo) {
return false;
if (storageInfo != trashStorageInfo) {
return false;
}
}
if (!trashDir.mkpath(TRASH_INFO_PATH)) {

View File

@ -48,7 +48,13 @@ public:
#endif
bool rmdir(const QString &dirName, bool recurseParentDirectories) 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;
#endif
bool setSize(qint64 size) override;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1)

View File

@ -213,7 +213,7 @@ QString DLogManager::getlogFilePath()
if (!QDir(cachePath).exists()) {
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);

View File

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

View File

@ -211,11 +211,23 @@ QStringList pinyin(const QString &words, ToneStyle ts, bool *ok)
\return pinyin first letters list of the 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;
bool ok = false;
for (const QChar &w : words) {
QStringList pys = pinyin(w, TS_Tone, &ok);
QStringList pys = pinyin(w, ts, &ok);
if (!ok) {
result << QStringList(w);
continue;

View File

@ -13,6 +13,7 @@
#include <QUrl>
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
#include <QStringConverter>
#include <QTimeZone>
#endif
DCORE_BEGIN_NAMESPACE
@ -67,7 +68,11 @@ bool DRecentManager::addItem(const QString &uri, DRecentData &data)
QFile file(RECENT_PATH);
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);
#endif
QDomDocument doc;
if (!doc.setContent(&file)) {

View File

@ -229,7 +229,21 @@ bool DVtableHook::hasVtable(const void *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)

View File

@ -20,6 +20,12 @@ if(LINUX)
find_package(PkgConfig REQUIRED)
if("${QT_VERSION_MAJOR}" STREQUAL "5")
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()
@ -28,6 +34,8 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Test)
find_package(GTest REQUIRED)
include(GoogleTest)
# for test.so
set(TEST_SO_NAME vtabletest${DTK_VERSION_MAJOR})
add_subdirectory(./testso)
@ -110,4 +118,4 @@ target_include_directories( ${BIN_NAME} PUBLIC
./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());
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)
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)
# start dci
include(../../src/dci/dci.cmake)

View File

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

View File

@ -598,7 +598,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
<< endl;
}
QSet<QString> annotations;
QStringList annotations;
for (const QDBusIntrospection::Interface *interface : interfaces) {
for (const auto &method : interface->methods) {
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) {
for (const QString &annotation : annotations) {
if (annotation.indexOf('<') == -1) {