Compare commits

...

16 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
27 changed files with 266 additions and 55 deletions

View File

@ -5,6 +5,49 @@ 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/), 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). 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 ## [5.7.20] - 2025-07-31
### Changed ### Changed

View File

@ -1 +1 @@
5.7.20 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.20 pkgver=5.7.25
pkgrel=1 pkgrel=1
sourcename=dtkcore sourcename=dtkcore
sourcetars=("$sourcename"_"$pkgver".tar.xz) sourcetars=("$sourcename"_"$pkgver".tar.xz)

30
debian/changelog vendored
View File

@ -1,3 +1,33 @@
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 dtkcore (5.7.20) unstable; urgency=medium
* Release 5.7.20 * Release 5.7.20

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

@ -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.7.20 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

@ -12,10 +12,16 @@ 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)

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

@ -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 {

View File

@ -39,7 +39,7 @@ static void dbusMessageDeleter(DBusMessage *msg) {
} }
// D-Bus utility functions using libdbus-1 // D-Bus utility functions using libdbus-1
static bool checkDBusServiceActivatable(const QString &service) static bool checkDBusServiceActivatable(const QByteArray &service)
{ {
auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter); auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter);
dbus_error_init(error.get()); dbus_error_init(error.get());
@ -70,10 +70,12 @@ static bool checkDBusServiceActivatable(const QString &service)
} }
auto msgGuard = std::unique_ptr<DBusMessage, void(*)(DBusMessage*)>(msg, dbusMessageDeleter); 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)) { const char *serviceName = service.constData();
qCWarning(dsgApp) << "Failed to append arguments to D-Bus message"; if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &serviceName, DBUS_TYPE_INVALID)) {
return false; qCWarning(dsgApp) << "Failed to append arguments to D-Bus message";
return false;
}
} }
// Send message and get reply // Send message and get reply
@ -140,7 +142,7 @@ static bool checkDBusServiceActivatable(const QString &service)
while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRING) { while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRING) {
const char *name; const char *name;
dbus_message_iter_get_basic(&array_iter, &name); dbus_message_iter_get_basic(&array_iter, &name);
if (service == QString::fromUtf8(name)) { if (service == name) {
found = true; found = true;
break; break;
} }
@ -150,7 +152,8 @@ static bool checkDBusServiceActivatable(const QString &service)
return found; 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)
{ {
auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter); auto error = std::unique_ptr<DBusError, void(*)(DBusError*)>(new DBusError, dbusErrorDeleter);
dbus_error_init(error.get()); dbus_error_init(error.get());
@ -167,11 +170,11 @@ static QByteArray callDBusIdentifyMethod(const QString &service, const QString &
} }
auto connGuard = std::unique_ptr<DBusConnection, void(*)(DBusConnection*)>(connection, dbusConnectionDeleter); 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( DBusMessage *msg = dbus_message_new_method_call(
service.toUtf8().constData(), serviceName.constData(),
path.toUtf8().constData(), path.constData(),
interface.toUtf8().constData(), interface.constData(),
"Identify" "Identify"
); );
@ -222,7 +225,7 @@ 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)
{ {
return checkDBusServiceActivatable(service); return checkDBusServiceActivatable(service);
} }
@ -273,9 +276,9 @@ QByteArray DSGApplication::id()
* Get application ID for a given process ID * Get application ID for a given process ID
* *
* This function has been updated to use libdbus-1 instead of Qt D-Bus to fix * 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 * the bug(pms:BUG-278055) where calling this function before QCoreApplication
* initialization would fail. This is particularly important when the service * initialization would fail. This is particularly important when the service
* is being started by D-Bus activation and DSGApplication::id() is called * is being started by D-Bus activation and DSGApplication::id() is called
* during early startup. * during early startup.
* *
* @param pid Process ID to get the application ID for * @param pid Process ID to get the application ID for

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

@ -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

@ -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) {