diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d4002e0..e3494049 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,10 @@ cmake_minimum_required (VERSION 3.13) -file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" DTK_FILE_VERSION) -string(STRIP "${DTK_FILE_VERSION}" DTK_FILE_VERSION) -set(DTK_VERSION "${DTK_FILE_VERSION}" CACHE STRING "DTK version") +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FILE_VERSION) +string(STRIP "${FILE_VERSION}" FILE_VERSION) project (DtkCore - VERSION ${DTK_VERSION} + VERSION ${FILE_VERSION} DESCRIPTION "DTK Core module" HOMEPAGE_URL "https://github.com/linuxdeepin/dtkcore" LANGUAGES CXX C @@ -18,13 +17,19 @@ endif () include(GNUInstallDirs) include(CMakePackageConfigHelpers) -if("${PROJECT_VERSION_MAJOR}" STREQUAL "5") - set(QT_VERSION_MAJOR "5") -elseif("${PROJECT_VERSION_MAJOR}" STREQUAL "6") - set(QT_VERSION_MAJOR "6") - set(DTK_VERSION_MAJOR "6") +option(DTK5 "Build DTK5." ON) +if(DTK5) + set(DTK_VERSION_MAJOR "5") + set(DTK_NAME_SUFFIX "") # Empty name suffix for DTK5 products. else() - message(SEND_ERROR "not support Prject Version ${PROJECT_VERSION}.") + set(DTK_VERSION_MAJOR "6") + set(DTK_NAME_SUFFIX "6") endif() +set(DTK_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(DTK_VERSION_PATCH ${PROJECT_VERSION_PATCH}) +set(DTK_VERSION "${DTK_VERSION_MAJOR}.${DTK_VERSION_MINOR}.${DTK_VERSION_PATCH}") +# Officially, DTK5 uses QT5, DTK6 uses QT6 +set(QT_VERSION_MAJOR ${DTK_VERSION_MAJOR}) + include(dtkcore.cmake) diff --git a/cmake/DtkCMake/DtkCMakeConfig.cmake.in b/cmake/DtkCMake/DtkCMakeConfig.cmake.in index c115ebce..60a14ba7 100644 --- a/cmake/DtkCMake/DtkCMakeConfig.cmake.in +++ b/cmake/DtkCMake/DtkCMakeConfig.cmake.in @@ -6,7 +6,7 @@ endfunction() add_definitions(-DQ_HOST_NAME=\"${CMAKE_HOST_SYSTEM_PROCESSOR}\") addDefinitions(Q_HOST_${CMAKE_HOST_SYSTEM_PROCESSOR}) -find_package(Dtk@DTK_VERSION_MAJOR@Core REQUIRED) +find_package(Dtk@DTK_NAME_SUFFIX@Core REQUIRED) set(DEEPIN_OS_RELEASE_TOOL_PATH ${DtkCore_TOOL_DIRS}) set(DEEPIN_OS_RELEASE_TOOL ${DEEPIN_OS_RELEASE_TOOL_PATH}/deepin-os-release) diff --git a/cmake/DtkTools/DtkToolsConfig.cmake.in b/cmake/DtkTools/DtkToolsConfig.cmake.in index 074003b5..b34c7b7c 100644 --- a/cmake/DtkTools/DtkToolsConfig.cmake.in +++ b/cmake/DtkTools/DtkToolsConfig.cmake.in @@ -1,5 +1,5 @@ include(CMakeFindDependencyMacro) -find_dependency(Dtk@DTK_VERSION_MAJOR@Core REQUIRED) +find_dependency(Dtk@DTK_NAME_SUFFIX@Core REQUIRED) set (DTK_SETTINGS_TOOLS_EXECUTABLE ${DtkCore_TOOL_DIRS}/dtk-settings) @@ -7,10 +7,10 @@ if (EXISTS ${DTK_SETTINGS_TOOLS_EXECUTABLE}) set(DTK_SETTINGS_TOOLS_FOUND TRUE) endif () -include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@SettingsToolsMacros.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@ToolsTargets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_NAME_SUFFIX@SettingsToolsMacros.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_NAME_SUFFIX@ToolsTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/DtkDBusMacros.cmake") include("${CMAKE_CURRENT_LIST_DIR}/DtkDConfigMacros.cmake") -get_target_property(DTK_XML2CPP Dtk@DTK_VERSION_MAJOR@::Xml2Cpp LOCATION) -get_target_property(DTK_DCONFIG2CPP Dtk@DTK_VERSION_MAJOR@::DConfig2Cpp LOCATION) +get_target_property(DTK_XML2CPP Dtk@DTK_NAME_SUFFIX@::Xml2Cpp LOCATION) +get_target_property(DTK_DCONFIG2CPP Dtk@DTK_NAME_SUFFIX@::DConfig2Cpp LOCATION) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 357b7121..3b71425b 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -7,7 +7,7 @@ set (DOXYGEN_GENERATE_HTML YES CACHE STRING "Doxygen HTML output") set (DOXYGEN_GENERATE_XML YES CACHE STRING "Doxygen XML output") set (DOXYGEN_GENERATE_QHP YES CACHE STRING "Doxygen QHP output") set (DOXYGEN_FILE_PATTERNS *.cpp *.h *.zh_CN.md *.zh_CN.dox CACHE STRING "Doxygen File Patterns") -set (DOXYGEN_PROJECT_NUMBER ${CMAKE_PROJECT_VERSION} CACHE STRING "") # Should be the same as this project is using. +set (DOXYGEN_PROJECT_NUMBER ${DTK_VERSION} CACHE STRING "") # Should be the same as this project is using. set (DOXYGEN_EXTRACT_STATIC YES) set (DOXYGEN_OUTPUT_LANGUAGE "Chinese") diff --git a/dtkcore.cmake b/dtkcore.cmake index 556f3d41..4a3f8023 100644 --- a/dtkcore.cmake +++ b/dtkcore.cmake @@ -1,18 +1,16 @@ -set(LIB_NAME dtk${DTK_VERSION_MAJOR}core) -set(DtkCore Dtk${DTK_VERSION_MAJOR}Core) +set(LIB_NAME dtk${DTK_NAME_SUFFIX}core) +set(DtkCore Dtk${DTK_NAME_SUFFIX}Core) macro(add_sub_dir dir) -# message("add_subdirectory(${dir} ${OUTPUT_DIR}/${dir})") add_subdirectory(${dir} ${OUTPUT_DIR}/${dir}) endmacro() -message("Current Qt Version: ${QT_VERSION_MAJOR}") -message("Current Dtk Version: ${DTK_VERSION_MAJOR}") +message(STATUS "Compiling with DTK major version: ${DTK_VERSION_MAJOR}, Qt major version: ${QT_VERSION_MAJOR}") set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) set (LIBRARY_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") -set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${PROJECT_VERSION_MAJOR}/DCore") -set (TOOL_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/dtk${PROJECT_VERSION_MAJOR}/DCore/bin") +set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${DTK_VERSION_MAJOR}/DCore") +set (TOOL_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/dtk${DTK_VERSION_MAJOR}/DCore/bin") set (MKSPECS_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/mkspecs/modules" CACHE STRING "Install dir for qt pri files") set (FEATURES_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/mkspecs/features" CACHE STRING "Install dir for qt prf files") set (CONFIG_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${DtkCore}" CACHE STRING "Install dir for cmake config files") @@ -21,6 +19,7 @@ set (DSYSINFO_PREFIX "" CACHE STRING "PREFIX of DSysInfo") set (BUILD_EXAMPLES ON CACHE BOOL "Build examples") set (BUILD_VERSION "0" CACHE STRING "buildversion") +option(BUIILD_TESTING "Build tests" OFF) if(UNIX AND NOT APPLE) set(LINUX TRUE) @@ -40,9 +39,6 @@ else() # dtk6 not build doc set (BUILD_DOCS OFF CACHE BOOL "Generate doxygen-based documentation") endif() -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() if(NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra") @@ -74,35 +70,31 @@ if(BUILD_EXAMPLES) endif() add_sub_dir(tools) -if("${QT_VERSION_MAJOR}" STREQUAL "6") - set(DTK_VERSION_MAJOR 6) -endif() - configure_package_config_file(cmake/DtkCMake/DtkCMakeConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_VERSION_MAJOR}CMakeConfig.cmake - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}CMake" + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_NAME_SUFFIX}CMakeConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}CMake" PATH_VARS TOOL_INSTALL_DIR) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_VERSION_MAJOR}CMakeConfig.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}CMake") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkCMake/Dtk${DTK_NAME_SUFFIX}CMakeConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}CMake") configure_package_config_file(cmake/DtkTools/DtkToolsConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_VERSION_MAJOR}ToolsConfig.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_NAME_SUFFIX}ToolsConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools PATH_VARS TOOL_INSTALL_DIR) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_VERSION_MAJOR}ToolsConfig.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkTools/Dtk${DTK_NAME_SUFFIX}ToolsConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools") install(FILES cmake/DtkTools/DtkSettingsToolsMacros.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools" - RENAME Dtk${DTK_VERSION_MAJOR}SettingsToolsMacros.cmake) + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools" + RENAME Dtk${DTK_NAME_SUFFIX}SettingsToolsMacros.cmake) install(FILES cmake/DtkTools/DtkDBusMacros.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools") install(FILES ${CMAKE_SOURCE_DIR}/cmake/DtkTools/DtkDConfigMacros.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools") -if (NOT DTK_VERSION_MAJOR) +if (NOT DTK5) set(DCONFIG_DEPRECATED_FUNCS [=[ # deprecated since dtk6 function(dconfig_meta_files) @@ -114,11 +106,11 @@ endfunction()]=]) endif() configure_package_config_file(cmake/DtkDConfig/DtkDConfigConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_VERSION_MAJOR}DConfigConfig.cmake - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}DConfig" + ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_NAME_SUFFIX}DConfigConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}DConfig" PATH_VARS TOOL_INSTALL_DIR) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_VERSION_MAJOR}DConfigConfig.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}DConfig") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/DtkDConfig/Dtk${DTK_NAME_SUFFIX}DConfigConfig.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}DConfig") configure_package_config_file(misc/DtkCoreConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${DtkCore}Config.cmake @@ -141,11 +133,11 @@ install(FILES misc/dtk_install_dconfig.prf DESTINATION ${FEATURES_INSTALL_DIR}) set(CONFIGNAME ${PROJECT_BINARY_DIR}/dtkcore_config.h) file(WRITE ${CONFIGNAME} "// it is auto make config\n" - "#define DTK_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}\n" - "#define DTK_VERSION_MINOR ${PROJECT_VERSION_MINOR}\n" - "#define DTK_VERSION_PATCH ${PROJECT_VERSION_PATCH}\n" + "#define DTK_VERSION_MAJOR ${DTK_VERSION_MAJOR}\n" + "#define DTK_VERSION_MINOR ${DTK_VERSION_MINOR}\n" + "#define DTK_VERSION_PATCH ${DTK_VERSION_PATCH}\n" "#define DTK_VERSION_BUILD ${BUILD_VERSION}\n" - "#define DTK_VERSION_STR \"${PROJECT_VERSION}\"\n" + "#define DTK_VERSION_STR \"${DTK_VERSION}\"\n" "\n" ) file(GLOB CONFIGSOURCE include/DtkCore/*) diff --git a/examples/dlog-example/CMakeLists.txt b/examples/dlog-example/CMakeLists.txt index 99991107..772f3c24 100644 --- a/examples/dlog-example/CMakeLists.txt +++ b/examples/dlog-example/CMakeLists.txt @@ -1,4 +1,4 @@ -set(BIN_NAME dlog${DTK_VERSION_MAJOR}) +set(BIN_NAME dlog${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/examples/expintf-example/CMakeLists.txt b/examples/expintf-example/CMakeLists.txt index bf31c5a9..59417c39 100644 --- a/examples/expintf-example/CMakeLists.txt +++ b/examples/expintf-example/CMakeLists.txt @@ -1,4 +1,4 @@ -set(BIN_NAME exprintf${DTK_VERSION_MAJOR}) +set(BIN_NAME exprintf${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus) diff --git a/examples/filewatcher-example/CMakeLists.txt b/examples/filewatcher-example/CMakeLists.txt index 0b0f1e5e..ea9455a8 100644 --- a/examples/filewatcher-example/CMakeLists.txt +++ b/examples/filewatcher-example/CMakeLists.txt @@ -1,4 +1,4 @@ -set(BIN_NAME filewatcher${DTK_VERSION_MAJOR}) +set(BIN_NAME filewatcher${DTK_NAME_SUFFIX}) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/examples/textcodec-example/CMakeLists.txt b/examples/textcodec-example/CMakeLists.txt index 04e1dd94..0104064e 100644 --- a/examples/textcodec-example/CMakeLists.txt +++ b/examples/textcodec-example/CMakeLists.txt @@ -1,4 +1,4 @@ -set(BIN_NAME textcodec${DTK_VERSION_MAJOR}) +set(BIN_NAME textcodec${DTK_NAME_SUFFIX}) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/misc/DtkCoreConfig.cmake.in b/misc/DtkCoreConfig.cmake.in index ca897353..fc3ad5b2 100644 --- a/misc/DtkCoreConfig.cmake.in +++ b/misc/DtkCoreConfig.cmake.in @@ -6,17 +6,17 @@ endif() include(CMakeFindDependencyMacro) find_dependency(Qt@QT_VERSION_MAJOR@Core) find_dependency(Qt@QT_VERSION_MAJOR@Xml) -find_dependency(Dtk@DTK_VERSION_MAJOR@Log) +find_dependency(Dtk@DTK_NAME_SUFFIX@Log) if (LINUX) find_dependency(Qt@QT_VERSION_MAJOR@DBus) endif() -find_dependency(Dtk@DTK_VERSION_MAJOR@DConfig) -include(${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_VERSION_MAJOR@CoreTargets.cmake) +find_dependency(Dtk@DTK_NAME_SUFFIX@DConfig) +include(${CMAKE_CURRENT_LIST_DIR}/Dtk@DTK_NAME_SUFFIX@CoreTargets.cmake) -set(DtkCore_LIBRARIES Dtk@DTK_VERSION_MAJOR@::Core) -get_target_property(DtkCore_INCLUDE_DIRS Dtk@DTK_VERSION_MAJOR@::Core INTERFACE_INCLUDE_DIRECTORIES) -get_target_property(DtkCore_LIBRARY_DIRS Dtk@DTK_VERSION_MAJOR@::Core INTERFACE_LINK_DIRECTORIES) +set(DtkCore_LIBRARIES Dtk@DTK_NAME_SUFFIX@::Core) +get_target_property(DtkCore_INCLUDE_DIRS Dtk@DTK_NAME_SUFFIX@::Core INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(DtkCore_LIBRARY_DIRS Dtk@DTK_NAME_SUFFIX@::Core INTERFACE_LINK_DIRECTORIES) set(DtkCore_TOOL_DIRS "@PACKAGE_TOOL_INSTALL_DIR@") check_required_components(DtkCore) diff --git a/misc/dtkcore.pc.in b/misc/dtkcore.pc.in index 890d6225..d5b2d01d 100644 --- a/misc/dtkcore.pc.in +++ b/misc/dtkcore.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${prefix}/@LIBRARY_INSTALL_DIR@ includedir=${prefix}/@INCLUDE_INSTALL_DIR@ -Name: dtk@DTK_VERSION_MAJOR@core -Description: Deepin Tool Kit dtkcore header files -Version: @CMAKE_PROJECT_VERSION@ -Libs: -L${libdir} -ldtk@DTK_VERSION_MAJOR@core +Name: dtk@DTK_NAME_SUFFIX@core +Description: Development ToolKit Core Devel Library +Version: @DTK_VERSION@ +Libs: -L${libdir} -ldtk@DTK_NAME_SUFFIX@core Cflags: -I${includedir} -DQT_MESSAGELOGCONTEXT -Requires: dtk@DTK_VERSION_MAJOR@log +Requires: dtk@DTK_NAME_SUFFIX@log diff --git a/misc/qt_lib_dtkcore.pri.in b/misc/qt_lib_dtkcore.pri.in index 06ee503c..c019f288 100644 --- a/misc/qt_lib_dtkcore.pri.in +++ b/misc/qt_lib_dtkcore.pri.in @@ -1,9 +1,9 @@ -QT.dtkcore.VERSION = @CMAKE_PROJECT_VERSION@ -QT.dtkcore.MAJOR_VERSION = @PROJECT_VERSION_MAJOR@ -QT.dtkcore.MINOR_VERSION = @PROJECT_VERSION_MINOR@ -QT.dtkcore.PATCH_VERSION = @PROJECT_VERSION_PATCH@ +QT.dtkcore.VERSION = @DTK_VERSION@ +QT.dtkcore.MAJOR_VERSION = @DTK_VERSION_MAJOR@ +QT.dtkcore.MINOR_VERSION = @DTK_VERSION_MINOR@ +QT.dtkcore.PATCH_VERSION = @DTK_VERSION_PATCH@ QT.dtkcore.name = dtkcore -QT.dtkcore.module = dtk@DTK_VERSION_MAJOR@core +QT.dtkcore.module = dtk@DTK_NAME_SUFFIX@core QT.dtkcore.tools = @CMAKE_INSTALL_PREFIX@/@TOOL_INSTALL_DIR@ QT.dtkcore.libs = @CMAKE_INSTALL_PREFIX@/@LIBRARY_INSTALL_DIR@ QT.dtkcore.includes = @CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 80dd6859..db33425a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) -find_package(Dtk${DTK_VERSION_MAJOR}Log REQUIRED) +find_package(Dtk${DTK_NAME_SUFFIX}Log REQUIRED) find_package(DBus1 REQUIRED) if(LINUX) find_package(PkgConfig REQUIRED) @@ -77,7 +77,7 @@ if(LINUX) Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Xml - Dtk${DTK_VERSION_MAJOR}::Log + Dtk${DTK_NAME_SUFFIX}::Log ) target_link_libraries(${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::CorePrivate @@ -113,8 +113,8 @@ else() endif() endif() set_target_properties(${LIB_NAME} PROPERTIES - VERSION ${CMAKE_PROJECT_VERSION} - SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR} + VERSION ${DTK_VERSION} + SOVERSION ${DTK_VERSION_MAJOR} EXPORT_NAME Core ) @@ -191,6 +191,6 @@ install(TARGETS ${LIB_NAME} EXPORT ${DtkCore}Targets install(EXPORT ${DtkCore}Targets FILE ${DtkCore}Targets.cmake - NAMESPACE Dtk${DTK_VERSION_MAJOR}:: + NAMESPACE Dtk${DTK_NAME_SUFFIX}:: DESTINATION ${CONFIG_CMAKE_INSTALL_DIR} ) diff --git a/src/glob.cmake b/src/glob.cmake index 83bcdb81..558b797d 100644 --- a/src/glob.cmake +++ b/src/glob.cmake @@ -7,7 +7,7 @@ set(OUTER_SOURCE ${CMAKE_CURRENT_LIST_DIR}/ddesktopentry.cpp ) -if (NOT DTK_VERSION_MAJOR) +if (DTK5) list(APPEND OUTER_SOURCE ${CMAKE_CURRENT_LIST_DIR}/dtkcore_global.cpp) endif() diff --git a/src/log/LogManager.cpp b/src/log/LogManager.cpp index 390c4e08..55d1da7b 100644 --- a/src/log/LogManager.cpp +++ b/src/log/LogManager.cpp @@ -112,7 +112,7 @@ void DLogManagerPrivate::updateLoggingRules() // 4. 优先看 dsgConfig 是否默认值,其次 fallback 是否默认值 if (m_dsgConfig && m_dsgConfig->isInitializeSucceed() && !m_dsgConfig->rulesIsDefaultValue()) { var = m_dsgConfig->rules(); - } else if (m_fallbackConfig && m_dsgConfig->isInitializeSucceed() && !m_fallbackConfig->rulesIsDefaultValue()) { + } else if (m_fallbackConfig && m_fallbackConfig->isInitializeSucceed() && !m_fallbackConfig->rulesIsDefaultValue()) { var = m_fallbackConfig->rules(); } else if (m_dsgConfig && m_dsgConfig->isInitializeSucceed()) { var = m_dsgConfig->rules(); diff --git a/src/log/dconfig_org_deepin_dtk_preference.hpp b/src/log/dconfig_org_deepin_dtk_preference.hpp index 4fea5196..20e06fb1 100644 --- a/src/log/dconfig_org_deepin_dtk_preference.hpp +++ b/src/log/dconfig_org_deepin_dtk_preference.hpp @@ -1,7 +1,7 @@ /** * This file is generated by dconfig2cpp. - * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp /usr/share/dsg/configs/org.deepin.dtk.preference.json - * Generation time: 2025-08-20T15:40:55 + * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp /usr/share/dsg/configs/org.deepin.dtk.preference.json -o ./src/log/dconfig_org_deepin_dtk_preference.hpp + * Generation time: 2026-01-19T18:04:14 * JSON file version: 1.0 * * WARNING: DO NOT MODIFY THIS FILE MANUALLY. @@ -20,6 +20,7 @@ #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #include #endif +#include #include #include @@ -27,6 +28,8 @@ class dconfig_org_deepin_dtk_preference : public QObject { Q_OBJECT Q_PROPERTY(bool autoDisplayFeature READ autoDisplayFeature WRITE setAutoDisplayFeature NOTIFY autoDisplayFeatureChanged RESET resetAutoDisplayFeature) + Q_PROPERTY(QString colorMode READ colorMode WRITE setColorMode NOTIFY colorModeChanged RESET resetColorMode) + Q_PROPERTY(QString defaultColorMode READ defaultColorMode WRITE setDefaultColorMode NOTIFY defaultColorModeChanged RESET resetDefaultColorMode) Q_PROPERTY(bool enableDtkAnimations READ enableDtkAnimations WRITE setEnableDtkAnimations NOTIFY enableDtkAnimationsChanged RESET resetEnableDtkAnimations) Q_PROPERTY(bool featureUpdated READ featureUpdated WRITE setFeatureUpdated NOTIFY featureUpdatedChanged RESET resetFeatureUpdated) Q_PROPERTY(bool keyboardsearchDisabled READ keyboardsearchDisabled WRITE setKeyboardsearchDisabled NOTIFY keyboardsearchDisabledChanged RESET resetKeyboardsearchDisabled) @@ -36,7 +39,7 @@ class dconfig_org_deepin_dtk_preference : public QObject { Q_PROPERTY(qlonglong themeType READ themeType WRITE setThemeType NOTIFY themeTypeChanged RESET resetThemeType) Q_PROPERTY(qlonglong titlebarHeight READ titlebarHeight WRITE setTitlebarHeight NOTIFY titlebarHeightChanged RESET resetTitlebarHeight) Q_PROPERTY(bool underlineShortcut READ underlineShortcut WRITE setUnderlineShortcut NOTIFY underlineShortcutChanged RESET resetUnderlineShortcut) - Q_CLASSINFO("DConfigKeyList", "autoDisplayFeature;enableDtkAnimations;featureUpdated;keyboardsearchDisabled;rules;scrollBarPolicy;sizeMode;themeType;titlebarHeight;underlineShortcut") + Q_CLASSINFO("DConfigKeyList", "autoDisplayFeature;colorMode;defaultColorMode;enableDtkAnimations;featureUpdated;keyboardsearchDisabled;rules;scrollBarPolicy;sizeMode;themeType;titlebarHeight;underlineShortcut") Q_CLASSINFO("DConfigFileName", "org.deepin.dtk.preference") Q_CLASSINFO("DConfigFileVersion", "1.0") @@ -44,15 +47,30 @@ class dconfig_org_deepin_dtk_preference : public QObject { explicit dconfig_org_deepin_dtk_preference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId, const QString &subpath, bool isGeneric, QObject *parent) - : QObject(nullptr) { + : QObject(parent), m_data(new Data) { + m_data->m_userConfig = this; + m_data->moveToThread(this->thread()); + if (!thread->isRunning()) { qWarning() << QLatin1String("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); - QPointer watcher(parent); - QMetaObject::invokeMethod(worker, [=, this]() { + + QPointer safeData(m_data); + + QMetaObject::invokeMethod(worker, [safeData, backend, name, appId, subpath, isGeneric, worker]() mutable { + delete worker; + worker = nullptr; + + if (!safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Invalid), + static_cast(Data::Status::Initializing))) { + // CAS failed, state already changed - userConfig destructor will handle cleanup + // Do not attempt to delete here as it would race with destructor + return; + } + DTK_CORE_NAMESPACE::DConfig *config = nullptr; if (isGeneric) { if (backend) { @@ -77,21 +95,45 @@ class dconfig_org_deepin_dtk_preference : public QObject { } } } - if (!config) { + + if (!config || !config->isValid()) { qWarning() << QLatin1String("Failed to create DConfig instance."); - worker->deleteLater(); + + QMetaObject::invokeMethod(safeData, [safeData]() { + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Failed))) { + Q_EMIT safeData->m_userConfig->configInitializeFailed(); + } else { + // CAS failed, destroy data object + delete safeData; + } + }, Qt::QueuedConnection); + + if (config) + delete config; + return; } config->moveToThread(QThread::currentThread()); - initializeInConfigThread(config); - if (watcher != parent) { - // delete this if watcher is changed to nullptr. - deleteLater(); - } else if (!this->parent() && parent) { - // !parent() means that parent is not changed. - this->setParent(watcher); + // Initialize through Data class + safeData->initializeInConfigThread(config); + + // Try to transition from Initializing to Succeeded + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Succeeded))) { + // CAS succeeded, connect destroyed signal and emit success signal + QObject::connect(config, &QObject::destroyed, safeData, &QObject::deleteLater); + if (safeData->m_userConfig) { + QMetaObject::invokeMethod(safeData, [safeData, config]() { + Q_EMIT safeData->m_userConfig->configInitializeSucceed(config); + }, Qt::QueuedConnection); + } + } else { + // CAS failed - state changed (e.g., set to Destroyed) + // We must clean up the config we just created + config->deleteLater(); + safeData->deleteLater(); } - worker->deleteLater(); }); } static dconfig_org_deepin_dtk_preference* create(const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) @@ -111,30 +153,39 @@ class dconfig_org_deepin_dtk_preference : public QObject { static dconfig_org_deepin_dtk_preference* createGenericByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) { return new dconfig_org_deepin_dtk_preference(thread, backend, name, {}, subpath, true, parent); } ~dconfig_org_deepin_dtk_preference() { - if (m_config.loadRelaxed()) { - m_config.loadRelaxed()->deleteLater(); - m_config.storeRelaxed(nullptr); + int oldStatus = m_data->m_status.fetchAndStoreOrdered(static_cast(Data::Status::Destroyed)); + + m_data->m_userConfig = nullptr; + if (oldStatus == static_cast(Data::Status::Succeeded)) { + // When Succeeded, release config object only + auto config = m_data->m_config.loadRelaxed(); + Q_ASSERT(config); + config->deleteLater(); + // m_data will be deleted by config's destroyed signal + } else if (oldStatus == static_cast(Data::Status::Failed) || + oldStatus == static_cast(Data::Status::Invalid)) { + // When Failed or Invalid, directly clean up Data object + m_data->deleteLater(); } } Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const { - return m_config.loadRelaxed(); + return m_data->m_config.loadRelaxed(); } - Q_INVOKABLE bool isInitializeSucceed() const { - return m_status.loadRelaxed() == static_cast(Status::Succeed); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Succeeded); } - Q_INVOKABLE bool isInitializeFailed() const { - return m_status.loadRelaxed() == static_cast(Status::Failed); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Failed); } - Q_INVOKABLE bool isInitializing() const { - return m_status.loadRelaxed() == static_cast(Status::Invalid); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Initializing); } Q_INVOKABLE QStringList keyList() const { return { QStringLiteral("autoDisplayFeature"), + QStringLiteral("colorMode"), + QStringLiteral("defaultColorMode"), QStringLiteral("enableDtkAnimations"), QStringLiteral("featureUpdated"), QStringLiteral("keyboardsearchDisabled"), @@ -149,6 +200,10 @@ class dconfig_org_deepin_dtk_preference : public QObject { Q_INVOKABLE bool isDefaultValue(const QString &key) const { if (key == QStringLiteral("autoDisplayFeature")) return autoDisplayFeatureIsDefaultValue(); + if (key == QStringLiteral("colorMode")) + return colorModeIsDefaultValue(); + if (key == QStringLiteral("defaultColorMode")) + return defaultColorModeIsDefaultValue(); if (key == QStringLiteral("enableDtkAnimations")) return enableDtkAnimationsIsDefaultValue(); if (key == QStringLiteral("featureUpdated")) @@ -171,26 +226,26 @@ class dconfig_org_deepin_dtk_preference : public QObject { } bool autoDisplayFeature() const { - return p_autoDisplayFeature; + return m_data->p_autoDisplayFeature; } void setAutoDisplayFeature(const bool &value) { - auto oldValue = p_autoDisplayFeature; - p_autoDisplayFeature = value; - markPropertySet(0); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("autoDisplayFeature"), value); + auto oldValue = m_data->p_autoDisplayFeature; + m_data->p_autoDisplayFeature = value; + m_data->markPropertySet(0); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("autoDisplayFeature"), value); }); } - if (p_autoDisplayFeature != oldValue) { + if (m_data->p_autoDisplayFeature != oldValue) { Q_EMIT autoDisplayFeatureChanged(); Q_EMIT valueChanged(QStringLiteral("autoDisplayFeature"), value); } } void resetAutoDisplayFeature() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("autoDisplayFeature")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("autoDisplayFeature")); }); } } @@ -200,29 +255,93 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool autoDisplayFeatureIsDefaultValue() const { - return !testPropertySet(0); + return !m_data->testPropertySet(0); + } + QString colorMode() const { + return m_data->p_colorMode; + } + void setColorMode(const QString &value) { + auto oldValue = m_data->p_colorMode; + m_data->p_colorMode = value; + m_data->markPropertySet(1); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("colorMode"), value); + }); + } + if (m_data->p_colorMode != oldValue) { + Q_EMIT colorModeChanged(); + Q_EMIT valueChanged(QStringLiteral("colorMode"), value); + } + } + void resetColorMode() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("colorMode")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableColorMode() { + return QBindable(this, "colorMode"); + } +#endif + Q_INVOKABLE bool colorModeIsDefaultValue() const { + return !m_data->testPropertySet(1); + } + QString defaultColorMode() const { + return m_data->p_defaultColorMode; + } + void setDefaultColorMode(const QString &value) { + auto oldValue = m_data->p_defaultColorMode; + m_data->p_defaultColorMode = value; + m_data->markPropertySet(2); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("defaultColorMode"), value); + }); + } + if (m_data->p_defaultColorMode != oldValue) { + Q_EMIT defaultColorModeChanged(); + Q_EMIT valueChanged(QStringLiteral("defaultColorMode"), value); + } + } + void resetDefaultColorMode() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("defaultColorMode")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableDefaultColorMode() { + return QBindable(this, "defaultColorMode"); + } +#endif + Q_INVOKABLE bool defaultColorModeIsDefaultValue() const { + return !m_data->testPropertySet(2); } bool enableDtkAnimations() const { - return p_enableDtkAnimations; + return m_data->p_enableDtkAnimations; } void setEnableDtkAnimations(const bool &value) { - auto oldValue = p_enableDtkAnimations; - p_enableDtkAnimations = value; - markPropertySet(1); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("enableDtkAnimations"), value); + auto oldValue = m_data->p_enableDtkAnimations; + m_data->p_enableDtkAnimations = value; + m_data->markPropertySet(3); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("enableDtkAnimations"), value); }); } - if (p_enableDtkAnimations != oldValue) { + if (m_data->p_enableDtkAnimations != oldValue) { Q_EMIT enableDtkAnimationsChanged(); Q_EMIT valueChanged(QStringLiteral("enableDtkAnimations"), value); } } void resetEnableDtkAnimations() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("enableDtkAnimations")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("enableDtkAnimations")); }); } } @@ -232,29 +351,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool enableDtkAnimationsIsDefaultValue() const { - return !testPropertySet(1); + return !m_data->testPropertySet(3); } bool featureUpdated() const { - return p_featureUpdated; + return m_data->p_featureUpdated; } void setFeatureUpdated(const bool &value) { - auto oldValue = p_featureUpdated; - p_featureUpdated = value; - markPropertySet(2); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("featureUpdated"), value); + auto oldValue = m_data->p_featureUpdated; + m_data->p_featureUpdated = value; + m_data->markPropertySet(4); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("featureUpdated"), value); }); } - if (p_featureUpdated != oldValue) { + if (m_data->p_featureUpdated != oldValue) { Q_EMIT featureUpdatedChanged(); Q_EMIT valueChanged(QStringLiteral("featureUpdated"), value); } } void resetFeatureUpdated() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("featureUpdated")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("featureUpdated")); }); } } @@ -264,29 +383,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool featureUpdatedIsDefaultValue() const { - return !testPropertySet(2); + return !m_data->testPropertySet(4); } bool keyboardsearchDisabled() const { - return p_keyboardsearchDisabled; + return m_data->p_keyboardsearchDisabled; } void setKeyboardsearchDisabled(const bool &value) { - auto oldValue = p_keyboardsearchDisabled; - p_keyboardsearchDisabled = value; - markPropertySet(3); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("keyboardsearchDisabled"), value); + auto oldValue = m_data->p_keyboardsearchDisabled; + m_data->p_keyboardsearchDisabled = value; + m_data->markPropertySet(5); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("keyboardsearchDisabled"), value); }); } - if (p_keyboardsearchDisabled != oldValue) { + if (m_data->p_keyboardsearchDisabled != oldValue) { Q_EMIT keyboardsearchDisabledChanged(); Q_EMIT valueChanged(QStringLiteral("keyboardsearchDisabled"), value); } } void resetKeyboardsearchDisabled() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("keyboardsearchDisabled")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("keyboardsearchDisabled")); }); } } @@ -296,29 +415,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool keyboardsearchDisabledIsDefaultValue() const { - return !testPropertySet(3); + return !m_data->testPropertySet(5); } QString rules() const { - return p_rules; + return m_data->p_rules; } void setRules(const QString &value) { - auto oldValue = p_rules; - p_rules = value; - markPropertySet(4); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("rules"), value); + auto oldValue = m_data->p_rules; + m_data->p_rules = value; + m_data->markPropertySet(6); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("rules"), value); }); } - if (p_rules != oldValue) { + if (m_data->p_rules != oldValue) { Q_EMIT rulesChanged(); Q_EMIT valueChanged(QStringLiteral("rules"), value); } } void resetRules() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("rules")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("rules")); }); } } @@ -328,29 +447,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool rulesIsDefaultValue() const { - return !testPropertySet(4); + return !m_data->testPropertySet(6); } qlonglong scrollBarPolicy() const { - return p_scrollBarPolicy; + return m_data->p_scrollBarPolicy; } void setScrollBarPolicy(const qlonglong &value) { - auto oldValue = p_scrollBarPolicy; - p_scrollBarPolicy = value; - markPropertySet(5); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("scrollBarPolicy"), value); + auto oldValue = m_data->p_scrollBarPolicy; + m_data->p_scrollBarPolicy = value; + m_data->markPropertySet(7); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("scrollBarPolicy"), value); }); } - if (p_scrollBarPolicy != oldValue) { + if (m_data->p_scrollBarPolicy != oldValue) { Q_EMIT scrollBarPolicyChanged(); Q_EMIT valueChanged(QStringLiteral("scrollBarPolicy"), value); } } void resetScrollBarPolicy() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("scrollBarPolicy")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("scrollBarPolicy")); }); } } @@ -360,29 +479,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool scrollBarPolicyIsDefaultValue() const { - return !testPropertySet(5); + return !m_data->testPropertySet(7); } qlonglong sizeMode() const { - return p_sizeMode; + return m_data->p_sizeMode; } void setSizeMode(const qlonglong &value) { - auto oldValue = p_sizeMode; - p_sizeMode = value; - markPropertySet(6); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("sizeMode"), value); + auto oldValue = m_data->p_sizeMode; + m_data->p_sizeMode = value; + m_data->markPropertySet(8); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("sizeMode"), value); }); } - if (p_sizeMode != oldValue) { + if (m_data->p_sizeMode != oldValue) { Q_EMIT sizeModeChanged(); Q_EMIT valueChanged(QStringLiteral("sizeMode"), value); } } void resetSizeMode() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("sizeMode")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("sizeMode")); }); } } @@ -392,29 +511,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool sizeModeIsDefaultValue() const { - return !testPropertySet(6); + return !m_data->testPropertySet(8); } qlonglong themeType() const { - return p_themeType; + return m_data->p_themeType; } void setThemeType(const qlonglong &value) { - auto oldValue = p_themeType; - p_themeType = value; - markPropertySet(7); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("themeType"), value); + auto oldValue = m_data->p_themeType; + m_data->p_themeType = value; + m_data->markPropertySet(9); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("themeType"), value); }); } - if (p_themeType != oldValue) { + if (m_data->p_themeType != oldValue) { Q_EMIT themeTypeChanged(); Q_EMIT valueChanged(QStringLiteral("themeType"), value); } } void resetThemeType() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("themeType")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("themeType")); }); } } @@ -424,29 +543,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool themeTypeIsDefaultValue() const { - return !testPropertySet(7); + return !m_data->testPropertySet(9); } qlonglong titlebarHeight() const { - return p_titlebarHeight; + return m_data->p_titlebarHeight; } void setTitlebarHeight(const qlonglong &value) { - auto oldValue = p_titlebarHeight; - p_titlebarHeight = value; - markPropertySet(8); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("titlebarHeight"), value); + auto oldValue = m_data->p_titlebarHeight; + m_data->p_titlebarHeight = value; + m_data->markPropertySet(10); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("titlebarHeight"), value); }); } - if (p_titlebarHeight != oldValue) { + if (m_data->p_titlebarHeight != oldValue) { Q_EMIT titlebarHeightChanged(); Q_EMIT valueChanged(QStringLiteral("titlebarHeight"), value); } } void resetTitlebarHeight() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("titlebarHeight")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("titlebarHeight")); }); } } @@ -456,29 +575,29 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool titlebarHeightIsDefaultValue() const { - return !testPropertySet(8); + return !m_data->testPropertySet(10); } bool underlineShortcut() const { - return p_underlineShortcut; + return m_data->p_underlineShortcut; } void setUnderlineShortcut(const bool &value) { - auto oldValue = p_underlineShortcut; - p_underlineShortcut = value; - markPropertySet(9); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("underlineShortcut"), value); + auto oldValue = m_data->p_underlineShortcut; + m_data->p_underlineShortcut = value; + m_data->markPropertySet(11); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("underlineShortcut"), value); }); } - if (p_underlineShortcut != oldValue) { + if (m_data->p_underlineShortcut != oldValue) { Q_EMIT underlineShortcutChanged(); Q_EMIT valueChanged(QStringLiteral("underlineShortcut"), value); } } void resetUnderlineShortcut() { - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this]() { - m_config.loadRelaxed()->reset(QStringLiteral("underlineShortcut")); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("underlineShortcut")); }); } } @@ -488,14 +607,22 @@ class dconfig_org_deepin_dtk_preference : public QObject { } #endif Q_INVOKABLE bool underlineShortcutIsDefaultValue() const { - return !testPropertySet(9); + return !m_data->testPropertySet(11); + } +protected: + bool event(QEvent *e) override { + if (e->type() == QEvent::ThreadChange) { + Q_ASSERT(this->thread() == m_data->thread()); + } + return QObject::event(e); } Q_SIGNALS: - void configInitializeFailed(DTK_CORE_NAMESPACE::DConfig *config); + void configInitializeFailed(); void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config); void valueChanged(const QString &key, const QVariant &value); - void autoDisplayFeatureChanged(); + void colorModeChanged(); + void defaultColorModeChanged(); void enableDtkAnimationsChanged(); void featureUpdatedChanged(); void keyboardsearchDisabledChanged(); @@ -505,252 +632,294 @@ class dconfig_org_deepin_dtk_preference : public QObject { void themeTypeChanged(); void titlebarHeightChanged(); void underlineShortcutChanged(); + private: - void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) { - Q_ASSERT(!m_config.loadRelaxed()); - m_config.storeRelaxed(config); - if (!config->isValid()) { - m_status.storeRelaxed(static_cast(Status::Failed)); - Q_EMIT configInitializeFailed(config); - return; - } + // Prevent external moveToThread calls + using QObject::moveToThread; + class Data : public QObject { + public: + enum class Status { + Invalid = 0, + Initializing = 1, + Succeeded = 2, + Failed = 3, + Destroyed = 4 + }; - if (testPropertySet(0)) { - config->setValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature)); - } else { - updateValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature)); - } - if (testPropertySet(1)) { - config->setValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations)); - } else { - updateValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations)); - } - if (testPropertySet(2)) { - config->setValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated)); - } else { - updateValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated)); - } - if (testPropertySet(3)) { - config->setValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled)); - } else { - updateValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled)); - } - if (testPropertySet(4)) { - config->setValue(QStringLiteral("rules"), QVariant::fromValue(p_rules)); - } else { - updateValue(QStringLiteral("rules"), QVariant::fromValue(p_rules)); - } - if (testPropertySet(5)) { - config->setValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy)); - } else { - updateValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy)); - } - if (testPropertySet(6)) { - config->setValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode)); - } else { - updateValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode)); - } - if (testPropertySet(7)) { - config->setValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); - } else { - updateValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); - } - if (testPropertySet(8)) { - config->setValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); - } else { - updateValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); - } - if (testPropertySet(9)) { - config->setValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut)); - } else { - updateValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut)); - } + explicit Data() + : QObject(nullptr) {} - if (!m_config.loadRelaxed()) - return; - connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { - updateValue(key); - }, Qt::DirectConnection); + inline void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature)); + } else { + updateValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("colorMode"), QVariant::fromValue(p_colorMode)); + } else { + updateValue(QStringLiteral("colorMode"), QVariant::fromValue(p_colorMode)); + } + if (testPropertySet(2)) { + config->setValue(QStringLiteral("defaultColorMode"), QVariant::fromValue(p_defaultColorMode)); + } else { + updateValue(QStringLiteral("defaultColorMode"), QVariant::fromValue(p_defaultColorMode)); + } + if (testPropertySet(3)) { + config->setValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations)); + } else { + updateValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations)); + } + if (testPropertySet(4)) { + config->setValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated)); + } else { + updateValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated)); + } + if (testPropertySet(5)) { + config->setValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled)); + } else { + updateValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled)); + } + if (testPropertySet(6)) { + config->setValue(QStringLiteral("rules"), QVariant::fromValue(p_rules)); + } else { + updateValue(QStringLiteral("rules"), QVariant::fromValue(p_rules)); + } + if (testPropertySet(7)) { + config->setValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy)); + } else { + updateValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy)); + } + if (testPropertySet(8)) { + config->setValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode)); + } else { + updateValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode)); + } + if (testPropertySet(9)) { + config->setValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); + } else { + updateValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType)); + } + if (testPropertySet(10)) { + config->setValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); + } else { + updateValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight)); + } + if (testPropertySet(11)) { + config->setValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut)); + } else { + updateValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut)); + } + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); + } - m_status.storeRelaxed(static_cast(Status::Succeed)); - 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")) { - markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_autoDisplayFeature != newValue) { - p_autoDisplayFeature = newValue; - Q_EMIT autoDisplayFeatureChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("enableDtkAnimations")) { - markPropertySet(1, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_enableDtkAnimations != newValue) { - p_enableDtkAnimations = newValue; - Q_EMIT enableDtkAnimationsChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("featureUpdated")) { - markPropertySet(2, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_featureUpdated != newValue) { - p_featureUpdated = newValue; - Q_EMIT featureUpdatedChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("keyboardsearchDisabled")) { - markPropertySet(3, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_keyboardsearchDisabled != newValue) { - p_keyboardsearchDisabled = newValue; - Q_EMIT keyboardsearchDisabledChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("rules")) { - markPropertySet(4, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_rules != newValue) { - p_rules = newValue; - Q_EMIT rulesChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("scrollBarPolicy")) { - markPropertySet(5, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_scrollBarPolicy != newValue) { - p_scrollBarPolicy = newValue; - Q_EMIT scrollBarPolicyChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("sizeMode")) { - markPropertySet(6, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_sizeMode != newValue) { - p_sizeMode = newValue; - Q_EMIT sizeModeChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("themeType")) { - markPropertySet(7, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_themeType != newValue) { - p_themeType = newValue; - Q_EMIT themeTypeChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("titlebarHeight")) { - markPropertySet(8, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_titlebarHeight != newValue) { - p_titlebarHeight = newValue; - Q_EMIT titlebarHeightChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; - } - if (key == QStringLiteral("underlineShortcut")) { - markPropertySet(9, !m_config.loadRelaxed()->isDefaultValue(key)); - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue, key, value]() { - Q_ASSERT(QThread::currentThread() == this->thread()); - if (p_underlineShortcut != newValue) { - p_underlineShortcut = newValue; - Q_EMIT underlineShortcutChanged(); - Q_EMIT valueChanged(key, value); - } - }); - return; + inline 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")) { + markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_autoDisplayFeature != newValue) { + p_autoDisplayFeature = newValue; + Q_EMIT m_userConfig->autoDisplayFeatureChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("colorMode")) { + markPropertySet(1, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_colorMode != newValue) { + p_colorMode = newValue; + Q_EMIT m_userConfig->colorModeChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("defaultColorMode")) { + markPropertySet(2, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_defaultColorMode != newValue) { + p_defaultColorMode = newValue; + Q_EMIT m_userConfig->defaultColorModeChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("enableDtkAnimations")) { + markPropertySet(3, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_enableDtkAnimations != newValue) { + p_enableDtkAnimations = newValue; + Q_EMIT m_userConfig->enableDtkAnimationsChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("featureUpdated")) { + markPropertySet(4, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_featureUpdated != newValue) { + p_featureUpdated = newValue; + Q_EMIT m_userConfig->featureUpdatedChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("keyboardsearchDisabled")) { + markPropertySet(5, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_keyboardsearchDisabled != newValue) { + p_keyboardsearchDisabled = newValue; + Q_EMIT m_userConfig->keyboardsearchDisabledChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("rules")) { + markPropertySet(6, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_rules != newValue) { + p_rules = newValue; + Q_EMIT m_userConfig->rulesChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("scrollBarPolicy")) { + markPropertySet(7, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_scrollBarPolicy != newValue) { + p_scrollBarPolicy = newValue; + Q_EMIT m_userConfig->scrollBarPolicyChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("sizeMode")) { + markPropertySet(8, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_sizeMode != newValue) { + p_sizeMode = newValue; + Q_EMIT m_userConfig->sizeModeChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("themeType")) { + markPropertySet(9, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_themeType != newValue) { + p_themeType = newValue; + Q_EMIT m_userConfig->themeTypeChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("titlebarHeight")) { + markPropertySet(10, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_titlebarHeight != newValue) { + p_titlebarHeight = newValue; + Q_EMIT m_userConfig->titlebarHeightChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("underlineShortcut")) { + markPropertySet(11, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_underlineShortcut != newValue) { + p_underlineShortcut = newValue; + Q_EMIT m_userConfig->underlineShortcutChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } } - } - inline void markPropertySet(const int index, bool on = true) { - if (index < 32) { - if (on) - m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); - else - m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0))); - return; + inline void markPropertySet(const int index, bool on = true) { + if (index < 32) { + if (on) + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + else + m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0))); + return; + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - inline bool testPropertySet(const int index) const { - if (index < 32) { - return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - - QAtomicPointer m_config = nullptr; + // Member variables + QAtomicPointer m_config = nullptr; + QAtomicInteger m_status = static_cast(Status::Invalid); + QPointer m_userConfig = nullptr; + QAtomicInteger m_propertySetStatus0 = 0; -public: - enum class Status { - Invalid = 0, - Succeed = 1, - Failed = 2 + // Property storage + bool p_autoDisplayFeature { false }; + // Default value: "" + QString p_colorMode { QLatin1String("") }; + // Default value: "color" + QString p_defaultColorMode { QStringLiteral(u"\u0063\u006f\u006c\u006f\u0072") }; + bool p_enableDtkAnimations { false }; + bool p_featureUpdated { false }; + bool p_keyboardsearchDisabled { false }; + // 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 }; + qlonglong p_titlebarHeight { -1 }; + bool p_underlineShortcut { false }; }; -private: - QAtomicInteger m_status = static_cast(Status::Invalid); - bool p_autoDisplayFeature { false }; - bool p_enableDtkAnimations { false }; - bool p_featureUpdated { false }; - bool p_keyboardsearchDisabled { false }; - // 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 }; - qlonglong p_titlebarHeight { -1 }; - bool p_underlineShortcut { false }; - QAtomicInteger m_propertySetStatus0 = 0; + Data *m_data; }; #endif // DCONFIG_ORG_DEEPIN_DTK_PREFERENCE_H diff --git a/src/settings/settings.cmake b/src/settings/settings.cmake index ace9cd79..44ebd062 100644 --- a/src/settings/settings.cmake +++ b/src/settings/settings.cmake @@ -20,7 +20,7 @@ else() ) endif() -if(DTK_VERSION_MAJOR) +if(NOT DTK5) list(REMOVE_ITEM SETTINGS_SOURCES "${CMAKE_CURRENT_LIST_DIR}/backend/gsettingsbackend.cpp") list(REMOVE_ITEM SETTINGS_HEADERS "${CMAKE_CURRENT_LIST_DIR}/../../include/settings/backend/gsettingsbackend.h") endif() diff --git a/src/util/util.cmake b/src/util/util.cmake index aa2fa7cf..cda8f50b 100644 --- a/src/util/util.cmake +++ b/src/util/util.cmake @@ -47,7 +47,7 @@ set(PRIVATE_HEADERS ${CMAKE_CURRENT_LIST_DIR}/ddbusinterface_p.h ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher_p.h) -if(DTK_VERSION_MAJOR) +if(NOT DTK5) list(REMOVE_ITEM UTILS_SOURCES "${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp") list(REMOVE_ITEM UTILS_HEADERS "${PROJECT_SOURCE_DIR}/include/util/dtimedloop.h") # no longer be used list(REMOVE_ITEM UTILS_HEADERS "${PROJECT_SOURCE_DIR}/include/util/dasync.h") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3aa6b2c..5dcdc470 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,8 +9,10 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) # dbus set(CMAKE_CXX_FLAGS "-fno-access-control") -add_compile_options(-fsanitize=address) -add_link_options(-fsanitize=address) +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) +endif() find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) @@ -37,7 +39,7 @@ find_package(GTest REQUIRED) include(GoogleTest) # for test.so -set(TEST_SO_NAME vtabletest${DTK_VERSION_MAJOR}) +set(TEST_SO_NAME vtabletest${DTK_NAME_SUFFIX}) add_subdirectory(./testso) # test @@ -49,7 +51,7 @@ file(GLOB FackDBus "./fakedbus/*.cpp" ) -if(DTK_VERSION_MAJOR) +if(NOT DTK5) list(REMOVE_ITEM TEST_SOURCE "${CMAKE_CURRENT_LIST_DIR}/ut_gsettingsbackend.cpp") list(REMOVE_ITEM TEST_SOURCE "${CMAKE_CURRENT_LIST_DIR}/ut_dasync.cpp") endif() @@ -118,4 +120,9 @@ target_include_directories( ${BIN_NAME} PUBLIC ./testso/ ) +# Set RPATH to find libvtabletest*.so in the build directory +set_target_properties(${BIN_NAME} PROPERTIES + SKIP_BUILD_RPATH FALSE +) + gtest_discover_tests(${BIN_NAME}) diff --git a/toolGenerate/dconfig2cpp/dconf-example_meta.hpp b/toolGenerate/dconfig2cpp/dconf-example_meta.hpp index 3ceef68c..3af31272 100644 --- a/toolGenerate/dconfig2cpp/dconf-example_meta.hpp +++ b/toolGenerate/dconfig2cpp/dconf-example_meta.hpp @@ -1,322 +1,697 @@ /** * This file is generated by dconfig2cpp. - * Command line arguments: ./dconfig2cpp -p ./dtkcore/toolGenerate/dconfig2cpp ./dtkcore/tests/data/dconf-example.meta.json - * Generation time: 2025-01-14T10:54:59 + * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp ./tests/data/dconf-example.meta.json -o ./toolGenerate/dconfig2cpp/dconf-example_meta.hpp + * Generation time: 2026-01-19T18:04:14 * JSON file version: 1.0 - * + * * WARNING: DO NOT MODIFY THIS FILE MANUALLY. * If you need to change the content, please modify the dconfig2cpp tool. */ -#ifndef DCONF-EXAMPLE_META_H -#define DCONF-EXAMPLE_META_H +#ifndef DCONFIG_DCONF-EXAMPLE_META_H +#define DCONFIG_DCONF-EXAMPLE_META_H #include #include +#include #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include +#endif +#include +#include #include -class dconf-example_meta : public QObject { +class dconfig_dconf-example_meta : public QObject { Q_OBJECT - Q_PROPERTY(QList array READ array WRITE setArray NOTIFY arrayChanged) - Q_PROPERTY(QList array_map READ array_map WRITE setArray_map NOTIFY array_mapChanged) - Q_PROPERTY(QList array_map_struct READ array_map_struct WRITE setArray_map_struct NOTIFY array_map_structChanged) - Q_PROPERTY(bool canExit READ canExit WRITE setCanExit NOTIFY canExitChanged) - Q_PROPERTY(QString key2 READ key2 WRITE setKey2 NOTIFY key2Changed) - Q_PROPERTY(QString key3 READ key3 WRITE setKey3 NOTIFY key3Changed) - Q_PROPERTY(QVariantMap map READ map WRITE setMap NOTIFY mapChanged) - Q_PROPERTY(QVariantMap map_array READ map_array WRITE setMap_array NOTIFY map_arrayChanged) - Q_PROPERTY(double number READ number WRITE setNumber NOTIFY numberChanged) - Q_PROPERTY(double numberDouble READ numberDouble WRITE setNumberDouble NOTIFY numberDoubleChanged) - Q_PROPERTY(bool publicConfig READ publicConfig WRITE setPublicConfig NOTIFY publicConfigChanged) - Q_PROPERTY(QVariantMap struct READ struct WRITE setStruct NOTIFY structChanged) + Q_PROPERTY(QList array READ array WRITE setArray NOTIFY arrayChanged RESET resetArray) + Q_PROPERTY(QList array_map READ array_map WRITE setArray_map NOTIFY array_mapChanged RESET resetArray_map) + Q_PROPERTY(QList array_map_struct READ array_map_struct WRITE setArray_map_struct NOTIFY array_map_structChanged RESET resetArray_map_struct) + Q_PROPERTY(bool canExit READ canExit WRITE setCanExit NOTIFY canExitChanged RESET resetCanExit) + Q_PROPERTY(QString key2 READ key2 WRITE setKey2 NOTIFY key2Changed RESET resetKey2) + Q_PROPERTY(QString key3 READ key3 WRITE setKey3 NOTIFY key3Changed RESET resetKey3) + Q_PROPERTY(QVariantMap map READ map WRITE setMap NOTIFY mapChanged RESET resetMap) + Q_PROPERTY(QVariantMap map_array READ map_array WRITE setMap_array NOTIFY map_arrayChanged RESET resetMap_array) + Q_PROPERTY(qlonglong number READ number WRITE setNumber NOTIFY numberChanged RESET resetNumber) + Q_PROPERTY(double numberDouble READ numberDouble WRITE setNumberDouble NOTIFY numberDoubleChanged RESET resetNumberDouble) + Q_PROPERTY(bool publicConfig READ publicConfig WRITE setPublicConfig NOTIFY publicConfigChanged RESET resetPublicConfig) + Q_PROPERTY(bool readonly READ readonly WRITE setReadonly NOTIFY readonlyChanged RESET resetReadonly) + Q_PROPERTY(bool readwrite READ readwrite WRITE setReadwrite NOTIFY readwriteChanged RESET resetReadwrite) + Q_PROPERTY(QVariantMap struct READ struct WRITE setStruct NOTIFY structChanged RESET resetStruct) + Q_CLASSINFO("DConfigKeyList", "array;array_map;array_map_struct;canExit;key2;key3;map;map_array;number;numberDouble;publicConfig;readonly;readwrite;struct") + Q_CLASSINFO("DConfigFileName", "dconf-example.meta") + Q_CLASSINFO("DConfigFileVersion", "1.0") + public: - explicit dconf-example_meta(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + explicit dconfig_dconf-example_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, + const QString &name, const QString &appId, const QString &subpath, + bool isGeneric, QObject *parent) + : QObject(parent), m_data(new Data) { + m_data->m_userConfig = this; + m_data->moveToThread(this->thread()); if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); + qWarning() << QLatin1String("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + + QPointer safeData(m_data); + + QMetaObject::invokeMethod(worker, [safeData, backend, name, appId, subpath, isGeneric, worker]() mutable { + delete worker; + worker = nullptr; + + if (!safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Invalid), + static_cast(Data::Status::Initializing))) { + // CAS failed, state already changed - userConfig destructor will handle cleanup + // Do not attempt to delete here as it would race with destructor return; } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + DTK_CORE_NAMESPACE::DConfig *config = nullptr; + if (isGeneric) { + if (backend) { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(backend, name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(name, subpath, nullptr); + } + } else { + if (backend) { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + } + } else { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + } + } } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_meta(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + if (!config || !config->isValid()) { + qWarning() << QLatin1String("Failed to create DConfig instance."); + + QMetaObject::invokeMethod(safeData, [safeData]() { + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Failed))) { + Q_EMIT safeData->m_userConfig->configInitializeFailed(); + } else { + // CAS failed, destroy data object + delete safeData; + } + }, Qt::QueuedConnection); + + if (config) + delete config; + return; } config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + // Initialize through Data class + safeData->initializeInConfigThread(config); - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + // Try to transition from Initializing to Succeeded + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Succeeded))) { + // CAS succeeded, connect destroyed signal and emit success signal + QObject::connect(config, &QObject::destroyed, safeData, &QObject::deleteLater); + if (safeData->m_userConfig) { + QMetaObject::invokeMethod(safeData, [safeData, config]() { + Q_EMIT safeData->m_userConfig->configInitializeSucceed(config); + }, Qt::QueuedConnection); + } + } else { + // CAS failed - state changed (e.g., set to Destroyed) + // We must clean up the config we just created + config->deleteLater(); + safeData->deleteLater(); } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); }); } - ~dconf-example_meta() { - if (m_config.loadRelaxed()) { - m_config.loadRelaxed()->deleteLater(); + static dconfig_dconf-example_meta* create(const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-example_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-example_meta* createByName(const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, nullptr, name, appId, subpath, false, parent); } + static dconfig_dconf-example_meta* createByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, backend, name, appId, subpath, false, parent); } + static dconfig_dconf-example_meta* createGeneric(const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-example_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-example_meta* createGenericByName(const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, nullptr, name, {}, subpath, true, parent); } + static dconfig_dconf-example_meta* createGenericByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_meta(thread, backend, name, {}, subpath, true, parent); } + ~dconfig_dconf-example_meta() { + int oldStatus = m_data->m_status.fetchAndStoreOrdered(static_cast(Data::Status::Destroyed)); + + m_data->m_userConfig = nullptr; + if (oldStatus == static_cast(Data::Status::Succeeded)) { + // When Succeeded, release config object only + auto config = m_data->m_config.loadRelaxed(); + Q_ASSERT(config); + config->deleteLater(); + // m_data will be deleted by config's destroyed signal + } else if (oldStatus == static_cast(Data::Status::Failed) || + oldStatus == static_cast(Data::Status::Invalid)) { + // When Failed or Invalid, directly clean up Data object + m_data->deleteLater(); } } + Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const { + return m_data->m_config.loadRelaxed(); + } + Q_INVOKABLE bool isInitializeSucceed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Succeeded); + } + Q_INVOKABLE bool isInitializeFailed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Failed); + } + Q_INVOKABLE bool isInitializing() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Initializing); + } + + Q_INVOKABLE QStringList keyList() const { + return { QStringLiteral("array"), + QStringLiteral("array_map"), + QStringLiteral("array_map_struct"), + QStringLiteral("canExit"), + QStringLiteral("key2"), + QStringLiteral("key3"), + QStringLiteral("map"), + QStringLiteral("map_array"), + QStringLiteral("number"), + QStringLiteral("numberDouble"), + QStringLiteral("publicConfig"), + QStringLiteral("readonly"), + QStringLiteral("readwrite"), + QStringLiteral("struct")}; + } + + Q_INVOKABLE bool isDefaultValue(const QString &key) const { + if (key == QStringLiteral("array")) + return arrayIsDefaultValue(); + if (key == QStringLiteral("array_map")) + return array_mapIsDefaultValue(); + if (key == QStringLiteral("array_map_struct")) + return array_map_structIsDefaultValue(); + if (key == QStringLiteral("canExit")) + return canExitIsDefaultValue(); + if (key == QStringLiteral("key2")) + return key2IsDefaultValue(); + if (key == QStringLiteral("key3")) + return key3IsDefaultValue(); + if (key == QStringLiteral("map")) + return mapIsDefaultValue(); + if (key == QStringLiteral("map_array")) + return map_arrayIsDefaultValue(); + if (key == QStringLiteral("number")) + return numberIsDefaultValue(); + if (key == QStringLiteral("numberDouble")) + return numberDoubleIsDefaultValue(); + if (key == QStringLiteral("publicConfig")) + return publicConfigIsDefaultValue(); + if (key == QStringLiteral("readonly")) + return readonlyIsDefaultValue(); + if (key == QStringLiteral("readwrite")) + return readwriteIsDefaultValue(); + if (key == QStringLiteral("struct")) + return structIsDefaultValue(); + return false; + } + QList array() const { - return p_array; + return m_data->p_array; } void setArray(const QList &value) { - auto oldValue = p_array; - p_array = value; - markPropertySet(0); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("array"), value); + auto oldValue = m_data->p_array; + m_data->p_array = value; + m_data->markPropertySet(0); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("array"), value); }); } - if (p_array != oldValue) { + if (m_data->p_array != oldValue) { Q_EMIT arrayChanged(); + Q_EMIT valueChanged(QStringLiteral("array"), value); } } + void resetArray() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("array")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable> bindableArray() { + return QBindable>(this, "array"); + } +#endif + Q_INVOKABLE bool arrayIsDefaultValue() const { + return !m_data->testPropertySet(0); + } QList array_map() const { - return p_array_map; + return m_data->p_array_map; } void setArray_map(const QList &value) { - auto oldValue = p_array_map; - p_array_map = value; - markPropertySet(1); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("array_map"), value); + auto oldValue = m_data->p_array_map; + m_data->p_array_map = value; + m_data->markPropertySet(1); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("array_map"), value); }); } - if (p_array_map != oldValue) { + if (m_data->p_array_map != oldValue) { Q_EMIT array_mapChanged(); + Q_EMIT valueChanged(QStringLiteral("array_map"), value); } } + void resetArray_map() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("array_map")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable> bindableArray_map() { + return QBindable>(this, "array_map"); + } +#endif + Q_INVOKABLE bool array_mapIsDefaultValue() const { + return !m_data->testPropertySet(1); + } QList array_map_struct() const { - return p_array_map_struct; + return m_data->p_array_map_struct; } void setArray_map_struct(const QList &value) { - auto oldValue = p_array_map_struct; - p_array_map_struct = value; - markPropertySet(2); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("array_map_struct"), value); + auto oldValue = m_data->p_array_map_struct; + m_data->p_array_map_struct = value; + m_data->markPropertySet(2); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("array_map_struct"), value); }); } - if (p_array_map_struct != oldValue) { + if (m_data->p_array_map_struct != oldValue) { Q_EMIT array_map_structChanged(); + Q_EMIT valueChanged(QStringLiteral("array_map_struct"), value); + } + } + void resetArray_map_struct() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("array_map_struct")); + }); } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable> bindableArray_map_struct() { + return QBindable>(this, "array_map_struct"); + } +#endif + Q_INVOKABLE bool array_map_structIsDefaultValue() const { + return !m_data->testPropertySet(2); + } bool canExit() const { - return p_canExit; + return m_data->p_canExit; } void setCanExit(const bool &value) { - auto oldValue = p_canExit; - p_canExit = value; - markPropertySet(3); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("canExit"), value); + auto oldValue = m_data->p_canExit; + m_data->p_canExit = value; + m_data->markPropertySet(3); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("canExit"), value); }); } - if (p_canExit != oldValue) { + if (m_data->p_canExit != oldValue) { Q_EMIT canExitChanged(); + Q_EMIT valueChanged(QStringLiteral("canExit"), value); + } + } + void resetCanExit() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("canExit")); + }); } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableCanExit() { + return QBindable(this, "canExit"); + } +#endif + Q_INVOKABLE bool canExitIsDefaultValue() const { + return !m_data->testPropertySet(3); + } QString key2() const { - return p_key2; + return m_data->p_key2; } void setKey2(const QString &value) { - auto oldValue = p_key2; - p_key2 = value; - markPropertySet(4); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("key2"), value); + auto oldValue = m_data->p_key2; + m_data->p_key2 = value; + m_data->markPropertySet(4); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("key2"), value); }); } - if (p_key2 != oldValue) { + if (m_data->p_key2 != oldValue) { Q_EMIT key2Changed(); + Q_EMIT valueChanged(QStringLiteral("key2"), value); + } + } + void resetKey2() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("key2")); + }); } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableKey2() { + return QBindable(this, "key2"); + } +#endif + Q_INVOKABLE bool key2IsDefaultValue() const { + return !m_data->testPropertySet(4); + } QString key3() const { - return p_key3; + return m_data->p_key3; } void setKey3(const QString &value) { - auto oldValue = p_key3; - p_key3 = value; - markPropertySet(5); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("key3"), value); + auto oldValue = m_data->p_key3; + m_data->p_key3 = value; + m_data->markPropertySet(5); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("key3"), value); }); } - if (p_key3 != oldValue) { + if (m_data->p_key3 != oldValue) { Q_EMIT key3Changed(); + Q_EMIT valueChanged(QStringLiteral("key3"), value); } } + void resetKey3() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("key3")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableKey3() { + return QBindable(this, "key3"); + } +#endif + Q_INVOKABLE bool key3IsDefaultValue() const { + return !m_data->testPropertySet(5); + } QVariantMap map() const { - return p_map; + return m_data->p_map; } void setMap(const QVariantMap &value) { - auto oldValue = p_map; - p_map = value; - markPropertySet(6); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("map"), value); + auto oldValue = m_data->p_map; + m_data->p_map = value; + m_data->markPropertySet(6); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("map"), value); }); } - if (p_map != oldValue) { + if (m_data->p_map != oldValue) { Q_EMIT mapChanged(); + Q_EMIT valueChanged(QStringLiteral("map"), value); } } + void resetMap() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("map")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableMap() { + return QBindable(this, "map"); + } +#endif + Q_INVOKABLE bool mapIsDefaultValue() const { + return !m_data->testPropertySet(6); + } QVariantMap map_array() const { - return p_map_array; + return m_data->p_map_array; } void setMap_array(const QVariantMap &value) { - auto oldValue = p_map_array; - p_map_array = value; - markPropertySet(7); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("map_array"), value); + auto oldValue = m_data->p_map_array; + m_data->p_map_array = value; + m_data->markPropertySet(7); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("map_array"), value); }); } - if (p_map_array != oldValue) { + if (m_data->p_map_array != oldValue) { Q_EMIT map_arrayChanged(); + Q_EMIT valueChanged(QStringLiteral("map_array"), value); } } - double number() const { - return p_number; + void resetMap_array() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("map_array")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableMap_array() { + return QBindable(this, "map_array"); + } +#endif + Q_INVOKABLE bool map_arrayIsDefaultValue() const { + return !m_data->testPropertySet(7); } - void setNumber(const double &value) { - auto oldValue = p_number; - p_number = value; - markPropertySet(8); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("number"), value); + qlonglong number() const { + return m_data->p_number; + } + void setNumber(const qlonglong &value) { + auto oldValue = m_data->p_number; + m_data->p_number = value; + m_data->markPropertySet(8); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("number"), value); }); } - if (p_number != oldValue) { + if (m_data->p_number != oldValue) { Q_EMIT numberChanged(); + Q_EMIT valueChanged(QStringLiteral("number"), value); + } + } + void resetNumber() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("number")); + }); } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableNumber() { + return QBindable(this, "number"); + } +#endif + Q_INVOKABLE bool numberIsDefaultValue() const { + return !m_data->testPropertySet(8); + } double numberDouble() const { - return p_numberDouble; + return m_data->p_numberDouble; } void setNumberDouble(const double &value) { - auto oldValue = p_numberDouble; - p_numberDouble = value; - markPropertySet(9); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("numberDouble"), value); + auto oldValue = m_data->p_numberDouble; + m_data->p_numberDouble = value; + m_data->markPropertySet(9); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("numberDouble"), value); }); } - if (p_numberDouble != oldValue) { + if (m_data->p_numberDouble != oldValue) { Q_EMIT numberDoubleChanged(); + Q_EMIT valueChanged(QStringLiteral("numberDouble"), value); } } + void resetNumberDouble() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("numberDouble")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableNumberDouble() { + return QBindable(this, "numberDouble"); + } +#endif + Q_INVOKABLE bool numberDoubleIsDefaultValue() const { + return !m_data->testPropertySet(9); + } bool publicConfig() const { - return p_publicConfig; + return m_data->p_publicConfig; } void setPublicConfig(const bool &value) { - auto oldValue = p_publicConfig; - p_publicConfig = value; - markPropertySet(10); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("publicConfig"), value); + auto oldValue = m_data->p_publicConfig; + m_data->p_publicConfig = value; + m_data->markPropertySet(10); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("publicConfig"), value); }); } - if (p_publicConfig != oldValue) { + if (m_data->p_publicConfig != oldValue) { Q_EMIT publicConfigChanged(); + Q_EMIT valueChanged(QStringLiteral("publicConfig"), value); + } + } + void resetPublicConfig() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("publicConfig")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindablePublicConfig() { + return QBindable(this, "publicConfig"); + } +#endif + Q_INVOKABLE bool publicConfigIsDefaultValue() const { + return !m_data->testPropertySet(10); + } + bool readonly() const { + return m_data->p_readonly; + } + void setReadonly(const bool &value) { + auto oldValue = m_data->p_readonly; + m_data->p_readonly = value; + m_data->markPropertySet(11); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("readonly"), value); + }); + } + if (m_data->p_readonly != oldValue) { + Q_EMIT readonlyChanged(); + Q_EMIT valueChanged(QStringLiteral("readonly"), value); + } + } + void resetReadonly() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("readonly")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableReadonly() { + return QBindable(this, "readonly"); + } +#endif + Q_INVOKABLE bool readonlyIsDefaultValue() const { + return !m_data->testPropertySet(11); + } + bool readwrite() const { + return m_data->p_readwrite; + } + void setReadwrite(const bool &value) { + auto oldValue = m_data->p_readwrite; + m_data->p_readwrite = value; + m_data->markPropertySet(12); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("readwrite"), value); + }); + } + if (m_data->p_readwrite != oldValue) { + Q_EMIT readwriteChanged(); + Q_EMIT valueChanged(QStringLiteral("readwrite"), value); } } + void resetReadwrite() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("readwrite")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableReadwrite() { + return QBindable(this, "readwrite"); + } +#endif + Q_INVOKABLE bool readwriteIsDefaultValue() const { + return !m_data->testPropertySet(12); + } QVariantMap struct() const { - return p_struct; + return m_data->p_struct; } void setStruct(const QVariantMap &value) { - auto oldValue = p_struct; - p_struct = value; - markPropertySet(11); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("struct"), value); + auto oldValue = m_data->p_struct; + m_data->p_struct = value; + m_data->markPropertySet(13); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("struct"), value); }); } - if (p_struct != oldValue) { + if (m_data->p_struct != oldValue) { Q_EMIT structChanged(); + Q_EMIT valueChanged(QStringLiteral("struct"), value); } } + void resetStruct() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("struct")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableStruct() { + return QBindable(this, "struct"); + } +#endif + Q_INVOKABLE bool structIsDefaultValue() const { + return !m_data->testPropertySet(13); + } +protected: + bool event(QEvent *e) override { + if (e->type() == QEvent::ThreadChange) { + Q_ASSERT(this->thread() == m_data->thread()); + } + return QObject::event(e); + } Q_SIGNALS: + void configInitializeFailed(); + void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config); + void valueChanged(const QString &key, const QVariant &value); void arrayChanged(); void array_mapChanged(); void array_map_structChanged(); @@ -328,227 +703,334 @@ class dconf-example_meta : public QObject { void numberChanged(); void numberDoubleChanged(); void publicConfigChanged(); + void readonlyChanged(); + void readwriteChanged(); void structChanged(); + private: - void initialize(DTK_CORE_NAMESPACE::DConfig *config) { - Q_ASSERT(!m_config.loadRelaxed()); - m_config.storeRelaxed(config); - if (testPropertySet(0)) { - config->setValue(QStringLiteral("array"), QVariant::fromValue(p_array)); - } else { - updateValue(QStringLiteral("array"), QVariant::fromValue(p_array)); - } - if (testPropertySet(1)) { - config->setValue(QStringLiteral("array_map"), QVariant::fromValue(p_array_map)); - } else { - updateValue(QStringLiteral("array_map"), QVariant::fromValue(p_array_map)); - } - if (testPropertySet(2)) { - config->setValue(QStringLiteral("array_map_struct"), QVariant::fromValue(p_array_map_struct)); - } else { - updateValue(QStringLiteral("array_map_struct"), QVariant::fromValue(p_array_map_struct)); - } - if (testPropertySet(3)) { - config->setValue(QStringLiteral("canExit"), QVariant::fromValue(p_canExit)); - } else { - updateValue(QStringLiteral("canExit"), QVariant::fromValue(p_canExit)); - } - if (testPropertySet(4)) { - config->setValue(QStringLiteral("key2"), QVariant::fromValue(p_key2)); - } else { - updateValue(QStringLiteral("key2"), QVariant::fromValue(p_key2)); - } - if (testPropertySet(5)) { - config->setValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); - } else { - updateValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); - } - if (testPropertySet(6)) { - config->setValue(QStringLiteral("map"), QVariant::fromValue(p_map)); - } else { - updateValue(QStringLiteral("map"), QVariant::fromValue(p_map)); - } - if (testPropertySet(7)) { - config->setValue(QStringLiteral("map_array"), QVariant::fromValue(p_map_array)); - } else { - updateValue(QStringLiteral("map_array"), QVariant::fromValue(p_map_array)); - } - if (testPropertySet(8)) { - config->setValue(QStringLiteral("number"), QVariant::fromValue(p_number)); - } else { - updateValue(QStringLiteral("number"), QVariant::fromValue(p_number)); - } - if (testPropertySet(9)) { - config->setValue(QStringLiteral("numberDouble"), QVariant::fromValue(p_numberDouble)); - } else { - updateValue(QStringLiteral("numberDouble"), QVariant::fromValue(p_numberDouble)); - } - if (testPropertySet(10)) { - config->setValue(QStringLiteral("publicConfig"), QVariant::fromValue(p_publicConfig)); - } else { - updateValue(QStringLiteral("publicConfig"), QVariant::fromValue(p_publicConfig)); - } - if (testPropertySet(11)) { - config->setValue(QStringLiteral("struct"), QVariant::fromValue(p_struct)); - } else { - updateValue(QStringLiteral("struct"), QVariant::fromValue(p_struct)); + // Prevent external moveToThread calls + using QObject::moveToThread; + class Data : public QObject { + public: + enum class Status { + Invalid = 0, + Initializing = 1, + Succeeded = 2, + Failed = 3, + Destroyed = 4 + }; + + explicit Data() + : QObject(nullptr) {} + + inline void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("array"), QVariant::fromValue(p_array)); + } else { + updateValue(QStringLiteral("array"), QVariant::fromValue(p_array)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("array_map"), QVariant::fromValue(p_array_map)); + } else { + updateValue(QStringLiteral("array_map"), QVariant::fromValue(p_array_map)); + } + if (testPropertySet(2)) { + config->setValue(QStringLiteral("array_map_struct"), QVariant::fromValue(p_array_map_struct)); + } else { + updateValue(QStringLiteral("array_map_struct"), QVariant::fromValue(p_array_map_struct)); + } + if (testPropertySet(3)) { + config->setValue(QStringLiteral("canExit"), QVariant::fromValue(p_canExit)); + } else { + updateValue(QStringLiteral("canExit"), QVariant::fromValue(p_canExit)); + } + if (testPropertySet(4)) { + config->setValue(QStringLiteral("key2"), QVariant::fromValue(p_key2)); + } else { + updateValue(QStringLiteral("key2"), QVariant::fromValue(p_key2)); + } + if (testPropertySet(5)) { + config->setValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); + } else { + updateValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); + } + if (testPropertySet(6)) { + config->setValue(QStringLiteral("map"), QVariant::fromValue(p_map)); + } else { + updateValue(QStringLiteral("map"), QVariant::fromValue(p_map)); + } + if (testPropertySet(7)) { + config->setValue(QStringLiteral("map_array"), QVariant::fromValue(p_map_array)); + } else { + updateValue(QStringLiteral("map_array"), QVariant::fromValue(p_map_array)); + } + if (testPropertySet(8)) { + config->setValue(QStringLiteral("number"), QVariant::fromValue(p_number)); + } else { + updateValue(QStringLiteral("number"), QVariant::fromValue(p_number)); + } + if (testPropertySet(9)) { + config->setValue(QStringLiteral("numberDouble"), QVariant::fromValue(p_numberDouble)); + } else { + updateValue(QStringLiteral("numberDouble"), QVariant::fromValue(p_numberDouble)); + } + if (testPropertySet(10)) { + config->setValue(QStringLiteral("publicConfig"), QVariant::fromValue(p_publicConfig)); + } else { + updateValue(QStringLiteral("publicConfig"), QVariant::fromValue(p_publicConfig)); + } + if (testPropertySet(11)) { + config->setValue(QStringLiteral("readonly"), QVariant::fromValue(p_readonly)); + } else { + updateValue(QStringLiteral("readonly"), QVariant::fromValue(p_readonly)); + } + if (testPropertySet(12)) { + config->setValue(QStringLiteral("readwrite"), QVariant::fromValue(p_readwrite)); + } else { + updateValue(QStringLiteral("readwrite"), QVariant::fromValue(p_readwrite)); + } + if (testPropertySet(13)) { + config->setValue(QStringLiteral("struct"), QVariant::fromValue(p_struct)); + } else { + updateValue(QStringLiteral("struct"), QVariant::fromValue(p_struct)); + } + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); } - connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { - updateValue(key); - }, Qt::DirectConnection); - } - void updateValue(const QString &key, const QVariant &fallback = QVariant()) { - Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); - const QVariant &value = m_config.loadRelaxed()->value(key, fallback); - if (key == QStringLiteral("array")) { - auto newValue = qvariant_cast>(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_array != newValue) { - p_array = newValue; - Q_EMIT arrayChanged(); - } - }); - return; - } - if (key == QStringLiteral("array_map")) { - auto newValue = qvariant_cast>(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_array_map != newValue) { - p_array_map = newValue; - Q_EMIT array_mapChanged(); - } - }); - return; - } - if (key == QStringLiteral("array_map_struct")) { - auto newValue = qvariant_cast>(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_array_map_struct != newValue) { - p_array_map_struct = newValue; - Q_EMIT array_map_structChanged(); - } - }); - return; - } - if (key == QStringLiteral("canExit")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_canExit != newValue) { - p_canExit = newValue; - Q_EMIT canExitChanged(); - } - }); - return; - } - if (key == QStringLiteral("key2")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_key2 != newValue) { - p_key2 = newValue; - Q_EMIT key2Changed(); - } - }); - return; - } - if (key == QStringLiteral("key3")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_key3 != newValue) { - p_key3 = newValue; - Q_EMIT key3Changed(); - } - }); - return; - } - if (key == QStringLiteral("map")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_map != newValue) { - p_map = newValue; - Q_EMIT mapChanged(); - } - }); - return; - } - if (key == QStringLiteral("map_array")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_map_array != newValue) { - p_map_array = newValue; - Q_EMIT map_arrayChanged(); - } - }); - return; - } - if (key == QStringLiteral("number")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_number != newValue) { - p_number = newValue; - Q_EMIT numberChanged(); - } - }); - return; - } - if (key == QStringLiteral("numberDouble")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_numberDouble != newValue) { - p_numberDouble = newValue; - Q_EMIT numberDoubleChanged(); - } - }); - return; - } - if (key == QStringLiteral("publicConfig")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_publicConfig != newValue) { - p_publicConfig = newValue; - Q_EMIT publicConfigChanged(); - } - }); - return; - } - if (key == QStringLiteral("struct")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_struct != newValue) { - p_struct = newValue; - Q_EMIT structChanged(); - } - }); - return; - } - } - inline void markPropertySet(const int index) { - if (index < 32) { - m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); - return; - } - Q_UNREACHABLE(); - } - inline bool testPropertySet(const int index) const { - if (index < 32) { - return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); - } - Q_UNREACHABLE(); - } - QAtomicPointer m_config = nullptr; - QList p_array { QList{QVariant(QStringLiteral("value1")), QVariant(QStringLiteral("value2"))} }; - QList p_array_map { QList{QVariant(QVariantMap{{QStringLiteral("key1"), QVariant(QStringLiteral("value1"))}, {QStringLiteral("key2"), QVariant(QStringLiteral("value2"))}})} }; - QList p_array_map_struct { QList{QVariant(QVariantMap{{QStringLiteral("key1"), QVariant(QVariantMap{{QStringLiteral("field1"), QVariant(QStringLiteral("value1"))}})}, {QStringLiteral("key2"), QVariant(QStringLiteral("value2"))}})} }; - bool p_canExit { true }; - QString p_key2 { QStringLiteral("125") }; - QString p_key3 { QStringLiteral("application") }; - QVariantMap p_map { QVariantMap{{QStringLiteral("key1"), QVariant(QStringLiteral("value1"))}, {QStringLiteral("key2"), QVariant(QStringLiteral("value2"))}} }; - QVariantMap p_map_array { QVariantMap{{QStringLiteral("key1"), QVariant(QList{QVariant(QStringLiteral("value1"))})}, {QStringLiteral("key2"), QVariant(QList{QVariant(QStringLiteral("value2"))})}} }; - double p_number { 1 }; - double p_numberDouble { 1 }; - bool p_publicConfig { true }; - QVariantMap p_struct { QVariantMap{{QStringLiteral("key1"), QVariant(QStringLiteral("value1"))}, {QStringLiteral("key2"), QVariant(QStringLiteral("value2"))}} }; - QAtomicInteger m_propertySetStatus0 = 0; + inline 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("array")) { + markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast>(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_array != newValue) { + p_array = newValue; + Q_EMIT m_userConfig->arrayChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("array_map")) { + markPropertySet(1, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast>(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_array_map != newValue) { + p_array_map = newValue; + Q_EMIT m_userConfig->array_mapChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("array_map_struct")) { + markPropertySet(2, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast>(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_array_map_struct != newValue) { + p_array_map_struct = newValue; + Q_EMIT m_userConfig->array_map_structChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("canExit")) { + markPropertySet(3, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_canExit != newValue) { + p_canExit = newValue; + Q_EMIT m_userConfig->canExitChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("key2")) { + markPropertySet(4, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_key2 != newValue) { + p_key2 = newValue; + Q_EMIT m_userConfig->key2Changed(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("key3")) { + markPropertySet(5, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_key3 != newValue) { + p_key3 = newValue; + Q_EMIT m_userConfig->key3Changed(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("map")) { + markPropertySet(6, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_map != newValue) { + p_map = newValue; + Q_EMIT m_userConfig->mapChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("map_array")) { + markPropertySet(7, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_map_array != newValue) { + p_map_array = newValue; + Q_EMIT m_userConfig->map_arrayChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("number")) { + markPropertySet(8, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_number != newValue) { + p_number = newValue; + Q_EMIT m_userConfig->numberChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("numberDouble")) { + markPropertySet(9, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_numberDouble != newValue) { + p_numberDouble = newValue; + Q_EMIT m_userConfig->numberDoubleChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("publicConfig")) { + markPropertySet(10, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_publicConfig != newValue) { + p_publicConfig = newValue; + Q_EMIT m_userConfig->publicConfigChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("readonly")) { + markPropertySet(11, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_readonly != newValue) { + p_readonly = newValue; + Q_EMIT m_userConfig->readonlyChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("readwrite")) { + markPropertySet(12, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_readwrite != newValue) { + p_readwrite = newValue; + Q_EMIT m_userConfig->readwriteChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("struct")) { + markPropertySet(13, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_struct != newValue) { + p_struct = newValue; + Q_EMIT m_userConfig->structChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + } + inline void markPropertySet(const int index, bool on = true) { + if (index < 32) { + if (on) + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + else + m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0))); + return; + } + Q_UNREACHABLE(); + } + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); + } + // Member variables + QAtomicPointer m_config = nullptr; + QAtomicInteger m_status = static_cast(Status::Invalid); + QPointer m_userConfig = nullptr; + QAtomicInteger m_propertySetStatus0 = 0; + + // Property storage + QList p_array { QList{QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031")), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))} }; + QList p_array_map { QList{QVariant(QVariantMap{{QStringLiteral(u"\u006b\u0065\u0079\u0031"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031"))}, {QStringLiteral(u"\u006b\u0065\u0079\u0032"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))}})} }; + QList p_array_map_struct { QList{QVariant(QVariantMap{{QStringLiteral(u"\u006b\u0065\u0079\u0031"), QVariant(QVariantMap{{QStringLiteral(u"\u0066\u0069\u0065\u006c\u0064\u0031"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031"))}})}, {QStringLiteral(u"\u006b\u0065\u0079\u0032"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))}})} }; + bool p_canExit { true }; + // Default value: "125" + QString p_key2 { QStringLiteral(u"\u0031\u0032\u0035") }; + // Default value: "application" + QString p_key3 { QStringLiteral(u"\u0061\u0070\u0070\u006c\u0069\u0063\u0061\u0074\u0069\u006f\u006e") }; + QVariantMap p_map { QVariantMap{{QStringLiteral(u"\u006b\u0065\u0079\u0031"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031"))}, {QStringLiteral(u"\u006b\u0065\u0079\u0032"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))}} }; + QVariantMap p_map_array { QVariantMap{{QStringLiteral(u"\u006b\u0065\u0079\u0031"), QVariant(QList{QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031"))})}, {QStringLiteral(u"\u006b\u0065\u0079\u0032"), QVariant(QList{QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))})}} }; + qlonglong p_number { 1 }; + double p_numberDouble { 1 }; + bool p_publicConfig { true }; + bool p_readonly { true }; + bool p_readwrite { true }; + QVariantMap p_struct { QVariantMap{{QStringLiteral(u"\u006b\u0065\u0079\u0031"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0031"))}, {QStringLiteral(u"\u006b\u0065\u0079\u0032"), QVariant(QStringLiteral(u"\u0076\u0061\u006c\u0075\u0065\u0032"))}} }; + }; + + Data *m_data; }; -#endif // DCONF-EXAMPLE_META_H +#endif // DCONFIG_DCONF-EXAMPLE_META_H diff --git a/toolGenerate/dconfig2cpp/dconf-example_other_app_configure_meta.hpp b/toolGenerate/dconfig2cpp/dconf-example_other_app_configure_meta.hpp index 1f9a54eb..63afed64 100644 --- a/toolGenerate/dconfig2cpp/dconf-example_other_app_configure_meta.hpp +++ b/toolGenerate/dconfig2cpp/dconf-example_other_app_configure_meta.hpp @@ -1,214 +1,364 @@ /** * This file is generated by dconfig2cpp. - * Command line arguments: ./dconfig2cpp -p ./dtkcore/toolGenerate/dconfig2cpp ./dtkcore/tests/data/dconf-example_other_app_configure.meta.json - * Generation time: 2025-01-14T10:54:59 + * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp ./tests/data/dconf-example_other_app_configure.meta.json -o ./toolGenerate/dconfig2cpp/dconf-example_other_app_configure_meta.hpp + * Generation time: 2026-01-19T18:04:14 * JSON file version: 1.0 - * + * * WARNING: DO NOT MODIFY THIS FILE MANUALLY. * If you need to change the content, please modify the dconfig2cpp tool. */ -#ifndef DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H -#define DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H +#ifndef DCONFIG_DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H +#define DCONFIG_DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H #include #include +#include #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include +#endif +#include +#include #include -class dconf-example_other_app_configure_meta : public QObject { +class dconfig_dconf-example_other_app_configure_meta : public QObject { Q_OBJECT - Q_PROPERTY(QString appPrivate READ appPrivate WRITE setAppPrivate NOTIFY appPrivateChanged) - Q_PROPERTY(QString appPublic READ appPublic WRITE setAppPublic NOTIFY appPublicChanged) + Q_PROPERTY(QString appPrivate READ appPrivate WRITE setAppPrivate NOTIFY appPrivateChanged RESET resetAppPrivate) + Q_PROPERTY(QString appPublic READ appPublic WRITE setAppPublic NOTIFY appPublicChanged RESET resetAppPublic) + Q_CLASSINFO("DConfigKeyList", "appPrivate;appPublic") + Q_CLASSINFO("DConfigFileName", "dconf-example_other_app_configure.meta") + Q_CLASSINFO("DConfigFileVersion", "1.0") + public: - explicit dconf-example_other_app_configure_meta(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + explicit dconfig_dconf-example_other_app_configure_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, + const QString &name, const QString &appId, const QString &subpath, + bool isGeneric, QObject *parent) + : QObject(parent), m_data(new Data) { + m_data->m_userConfig = this; + m_data->moveToThread(this->thread()); if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); + qWarning() << QLatin1String("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + + QPointer safeData(m_data); + + QMetaObject::invokeMethod(worker, [safeData, backend, name, appId, subpath, isGeneric, worker]() mutable { + delete worker; + worker = nullptr; + + if (!safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Invalid), + static_cast(Data::Status::Initializing))) { + // CAS failed, state already changed - userConfig destructor will handle cleanup + // Do not attempt to delete here as it would race with destructor return; } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_other_app_configure_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + DTK_CORE_NAMESPACE::DConfig *config = nullptr; + if (isGeneric) { + if (backend) { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(backend, name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(name, subpath, nullptr); + } + } else { + if (backend) { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + } + } else { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + } + } } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_other_app_configure_meta(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + if (!config || !config->isValid()) { + qWarning() << QLatin1String("Failed to create DConfig instance."); + + QMetaObject::invokeMethod(safeData, [safeData]() { + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Failed))) { + Q_EMIT safeData->m_userConfig->configInitializeFailed(); + } else { + // CAS failed, destroy data object + delete safeData; + } + }, Qt::QueuedConnection); + + if (config) + delete config; + return; } config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-example_other_app_configure_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + // Initialize through Data class + safeData->initializeInConfigThread(config); - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + // Try to transition from Initializing to Succeeded + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Succeeded))) { + // CAS succeeded, connect destroyed signal and emit success signal + QObject::connect(config, &QObject::destroyed, safeData, &QObject::deleteLater); + if (safeData->m_userConfig) { + QMetaObject::invokeMethod(safeData, [safeData, config]() { + Q_EMIT safeData->m_userConfig->configInitializeSucceed(config); + }, Qt::QueuedConnection); + } + } else { + // CAS failed - state changed (e.g., set to Destroyed) + // We must clean up the config we just created + config->deleteLater(); + safeData->deleteLater(); } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); }); } - ~dconf-example_other_app_configure_meta() { - if (m_config.loadRelaxed()) { - m_config.loadRelaxed()->deleteLater(); + static dconfig_dconf-example_other_app_configure_meta* create(const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u005f\u006f\u0074\u0068\u0065\u0072\u005f\u0061\u0070\u0070\u005f\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0065\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-example_other_app_configure_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u005f\u006f\u0074\u0068\u0065\u0072\u005f\u0061\u0070\u0070\u005f\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0065\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-example_other_app_configure_meta* createByName(const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, nullptr, name, appId, subpath, false, parent); } + static dconfig_dconf-example_other_app_configure_meta* createByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, backend, name, appId, subpath, false, parent); } + static dconfig_dconf-example_other_app_configure_meta* createGeneric(const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u005f\u006f\u0074\u0068\u0065\u0072\u005f\u0061\u0070\u0070\u005f\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0065\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-example_other_app_configure_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0065\u0078\u0061\u006d\u0070\u006c\u0065\u005f\u006f\u0074\u0068\u0065\u0072\u005f\u0061\u0070\u0070\u005f\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0065\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-example_other_app_configure_meta* createGenericByName(const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, nullptr, name, {}, subpath, true, parent); } + static dconfig_dconf-example_other_app_configure_meta* createGenericByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-example_other_app_configure_meta(thread, backend, name, {}, subpath, true, parent); } + ~dconfig_dconf-example_other_app_configure_meta() { + int oldStatus = m_data->m_status.fetchAndStoreOrdered(static_cast(Data::Status::Destroyed)); + + m_data->m_userConfig = nullptr; + if (oldStatus == static_cast(Data::Status::Succeeded)) { + // When Succeeded, release config object only + auto config = m_data->m_config.loadRelaxed(); + Q_ASSERT(config); + config->deleteLater(); + // m_data will be deleted by config's destroyed signal + } else if (oldStatus == static_cast(Data::Status::Failed) || + oldStatus == static_cast(Data::Status::Invalid)) { + // When Failed or Invalid, directly clean up Data object + m_data->deleteLater(); } } + Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const { + return m_data->m_config.loadRelaxed(); + } + Q_INVOKABLE bool isInitializeSucceed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Succeeded); + } + Q_INVOKABLE bool isInitializeFailed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Failed); + } + Q_INVOKABLE bool isInitializing() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Initializing); + } + + Q_INVOKABLE QStringList keyList() const { + return { QStringLiteral("appPrivate"), + QStringLiteral("appPublic")}; + } + + Q_INVOKABLE bool isDefaultValue(const QString &key) const { + if (key == QStringLiteral("appPrivate")) + return appPrivateIsDefaultValue(); + if (key == QStringLiteral("appPublic")) + return appPublicIsDefaultValue(); + return false; + } + QString appPrivate() const { - return p_appPrivate; + return m_data->p_appPrivate; } void setAppPrivate(const QString &value) { - auto oldValue = p_appPrivate; - p_appPrivate = value; - markPropertySet(0); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("appPrivate"), value); + auto oldValue = m_data->p_appPrivate; + m_data->p_appPrivate = value; + m_data->markPropertySet(0); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("appPrivate"), value); }); } - if (p_appPrivate != oldValue) { + if (m_data->p_appPrivate != oldValue) { Q_EMIT appPrivateChanged(); + Q_EMIT valueChanged(QStringLiteral("appPrivate"), value); } } + void resetAppPrivate() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("appPrivate")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableAppPrivate() { + return QBindable(this, "appPrivate"); + } +#endif + Q_INVOKABLE bool appPrivateIsDefaultValue() const { + return !m_data->testPropertySet(0); + } QString appPublic() const { - return p_appPublic; + return m_data->p_appPublic; } void setAppPublic(const QString &value) { - auto oldValue = p_appPublic; - p_appPublic = value; - markPropertySet(1); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("appPublic"), value); + auto oldValue = m_data->p_appPublic; + m_data->p_appPublic = value; + m_data->markPropertySet(1); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("appPublic"), value); }); } - if (p_appPublic != oldValue) { + if (m_data->p_appPublic != oldValue) { Q_EMIT appPublicChanged(); + Q_EMIT valueChanged(QStringLiteral("appPublic"), value); } } + void resetAppPublic() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("appPublic")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableAppPublic() { + return QBindable(this, "appPublic"); + } +#endif + Q_INVOKABLE bool appPublicIsDefaultValue() const { + return !m_data->testPropertySet(1); + } +protected: + bool event(QEvent *e) override { + if (e->type() == QEvent::ThreadChange) { + Q_ASSERT(this->thread() == m_data->thread()); + } + return QObject::event(e); + } Q_SIGNALS: + void configInitializeFailed(); + void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config); + void valueChanged(const QString &key, const QVariant &value); void appPrivateChanged(); void appPublicChanged(); + private: - void initialize(DTK_CORE_NAMESPACE::DConfig *config) { - Q_ASSERT(!m_config.loadRelaxed()); - m_config.storeRelaxed(config); - if (testPropertySet(0)) { - config->setValue(QStringLiteral("appPrivate"), QVariant::fromValue(p_appPrivate)); - } else { - updateValue(QStringLiteral("appPrivate"), QVariant::fromValue(p_appPrivate)); - } - if (testPropertySet(1)) { - config->setValue(QStringLiteral("appPublic"), QVariant::fromValue(p_appPublic)); - } else { - updateValue(QStringLiteral("appPublic"), QVariant::fromValue(p_appPublic)); - } + // Prevent external moveToThread calls + using QObject::moveToThread; + class Data : public QObject { + public: + enum class Status { + Invalid = 0, + Initializing = 1, + Succeeded = 2, + Failed = 3, + Destroyed = 4 + }; - connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { - updateValue(key); - }, Qt::DirectConnection); - } - void updateValue(const QString &key, const QVariant &fallback = QVariant()) { - Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); - const QVariant &value = m_config.loadRelaxed()->value(key, fallback); - if (key == QStringLiteral("appPrivate")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_appPrivate != newValue) { - p_appPrivate = newValue; - Q_EMIT appPrivateChanged(); - } - }); - return; + explicit Data() + : QObject(nullptr) {} + + inline void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("appPrivate"), QVariant::fromValue(p_appPrivate)); + } else { + updateValue(QStringLiteral("appPrivate"), QVariant::fromValue(p_appPrivate)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("appPublic"), QVariant::fromValue(p_appPublic)); + } else { + updateValue(QStringLiteral("appPublic"), QVariant::fromValue(p_appPublic)); + } + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); } - if (key == QStringLiteral("appPublic")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_appPublic != newValue) { - p_appPublic = newValue; - Q_EMIT appPublicChanged(); - } - }); - return; + + inline 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("appPrivate")) { + markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_appPrivate != newValue) { + p_appPrivate = newValue; + Q_EMIT m_userConfig->appPrivateChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } + if (key == QStringLiteral("appPublic")) { + markPropertySet(1, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_appPublic != newValue) { + p_appPublic = newValue; + Q_EMIT m_userConfig->appPublicChanged(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } } - } - inline void markPropertySet(const int index) { - if (index < 32) { - m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); - return; + inline void markPropertySet(const int index, bool on = true) { + if (index < 32) { + if (on) + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + else + m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0))); + return; + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - inline bool testPropertySet(const int index) const { - if (index < 32) { - return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - QAtomicPointer m_config = nullptr; - QString p_appPrivate { QStringLiteral("appPrivate") }; - QString p_appPublic { QStringLiteral("publicValue") }; - QAtomicInteger m_propertySetStatus0 = 0; + // Member variables + QAtomicPointer m_config = nullptr; + QAtomicInteger m_status = static_cast(Status::Invalid); + QPointer m_userConfig = nullptr; + QAtomicInteger m_propertySetStatus0 = 0; + + // Property storage + // Default value: "appPrivate" + QString p_appPrivate { QStringLiteral(u"\u0061\u0070\u0070\u0050\u0072\u0069\u0076\u0061\u0074\u0065") }; + // Default value: "publicValue" + QString p_appPublic { QStringLiteral(u"\u0070\u0075\u0062\u006c\u0069\u0063\u0056\u0061\u006c\u0075\u0065") }; + }; + + Data *m_data; }; -#endif // DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H +#endif // DCONFIG_DCONF-EXAMPLE_OTHER_APP_CONFIGURE_META_H diff --git a/toolGenerate/dconfig2cpp/dconf-global_meta.hpp b/toolGenerate/dconfig2cpp/dconf-global_meta.hpp index 50071ad4..e571d1ed 100644 --- a/toolGenerate/dconfig2cpp/dconf-global_meta.hpp +++ b/toolGenerate/dconfig2cpp/dconf-global_meta.hpp @@ -1,180 +1,307 @@ /** * This file is generated by dconfig2cpp. - * Command line arguments: ./dconfig2cpp -p ./dtkcore/toolGenerate/dconfig2cpp ./dtkcore/tests/data/dconf-global.meta.json - * Generation time: 2025-01-14T10:54:59 + * Command line arguments: ./build/tools/dconfig2cpp/dconfig2cpp ./tests/data/dconf-global.meta.json -o ./toolGenerate/dconfig2cpp/dconf-global_meta.hpp + * Generation time: 2026-01-19T18:04:14 * JSON file version: 1.0 - * + * * WARNING: DO NOT MODIFY THIS FILE MANUALLY. * If you need to change the content, please modify the dconfig2cpp tool. */ -#ifndef DCONF-GLOBAL_META_H -#define DCONF-GLOBAL_META_H +#ifndef DCONFIG_DCONF-GLOBAL_META_H +#define DCONFIG_DCONF-GLOBAL_META_H #include #include +#include #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#include +#endif +#include +#include #include -class dconf-global_meta : public QObject { +class dconfig_dconf-global_meta : public QObject { Q_OBJECT - Q_PROPERTY(QString key3 READ key3 WRITE setKey3 NOTIFY key3Changed) + Q_PROPERTY(QString key3 READ key3 WRITE setKey3 NOTIFY key3Changed RESET resetKey3) + Q_CLASSINFO("DConfigKeyList", "key3") + Q_CLASSINFO("DConfigFileName", "dconf-global.meta") + Q_CLASSINFO("DConfigFileVersion", "1.0") + public: - explicit dconf-global_meta(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + explicit dconfig_dconf-global_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, + const QString &name, const QString &appId, const QString &subpath, + bool isGeneric, QObject *parent) + : QObject(parent), m_data(new Data) { + m_data->m_userConfig = this; + m_data->moveToThread(this->thread()); if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); + qWarning() << QLatin1String("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + + QPointer safeData(m_data); + + QMetaObject::invokeMethod(worker, [safeData, backend, name, appId, subpath, isGeneric, worker]() mutable { + delete worker; + worker = nullptr; + + if (!safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Invalid), + static_cast(Data::Status::Initializing))) { + // CAS failed, state already changed - userConfig destructor will handle cleanup + // Do not attempt to delete here as it would race with destructor return; } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-global_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + DTK_CORE_NAMESPACE::DConfig *config = nullptr; + if (isGeneric) { + if (backend) { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(backend, name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::createGeneric(name, subpath, nullptr); + } + } else { + if (backend) { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + } + } else { + if (appId.isNull()) { + config = DTK_CORE_NAMESPACE::DConfig::create(DTK_CORE_NAMESPACE::DSGApplication::id(), + name, subpath, nullptr); + } else { + config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + } + } } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-global_meta(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); + if (!config || !config->isValid()) { + qWarning() << QLatin1String("Failed to create DConfig instance."); + + QMetaObject::invokeMethod(safeData, [safeData]() { + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Failed))) { + Q_EMIT safeData->m_userConfig->configInitializeFailed(); + } else { + // CAS failed, destroy data object + delete safeData; + } + }, Qt::QueuedConnection); + + if (config) + delete config; + return; } config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); - }); - } - explicit dconf-global_meta(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) - : QObject(parent) { + // Initialize through Data class + safeData->initializeInConfigThread(config); - if (!thread->isRunning()) { - qWarning() << QStringLiteral("Warning: The provided thread is not running."); - } - Q_ASSERT(QThread::currentThread() != thread); - auto worker = new QObject(); - worker->moveToThread(thread); - QMetaObject::invokeMethod(worker, [=]() { - auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); - if (!config) { - qWarning() << QStringLiteral("Failed to create DConfig instance."); - worker->deleteLater(); - return; + // Try to transition from Initializing to Succeeded + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Succeeded))) { + // CAS succeeded, connect destroyed signal and emit success signal + QObject::connect(config, &QObject::destroyed, safeData, &QObject::deleteLater); + if (safeData->m_userConfig) { + QMetaObject::invokeMethod(safeData, [safeData, config]() { + Q_EMIT safeData->m_userConfig->configInitializeSucceed(config); + }, Qt::QueuedConnection); + } + } else { + // CAS failed - state changed (e.g., set to Destroyed) + // We must clean up the config we just created + config->deleteLater(); + safeData->deleteLater(); } - config->moveToThread(QThread::currentThread()); - initialize(config); - worker->deleteLater(); }); } - ~dconf-global_meta() { - if (m_config.loadRelaxed()) { - m_config.loadRelaxed()->deleteLater(); + static dconfig_dconf-global_meta* create(const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0067\u006c\u006f\u0062\u0061\u006c\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-global_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0067\u006c\u006f\u0062\u0061\u006c\u002e\u006d\u0065\u0074\u0061"), appId, subpath, false, parent); } + static dconfig_dconf-global_meta* createByName(const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, nullptr, name, appId, subpath, false, parent); } + static dconfig_dconf-global_meta* createByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, backend, name, appId, subpath, false, parent); } + static dconfig_dconf-global_meta* createGeneric(const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, nullptr, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0067\u006c\u006f\u0062\u0061\u006c\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-global_meta* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, backend, QStringLiteral(u"\u0064\u0063\u006f\u006e\u0066\u002d\u0067\u006c\u006f\u0062\u0061\u006c\u002e\u006d\u0065\u0074\u0061"), {}, subpath, true, parent); } + static dconfig_dconf-global_meta* createGenericByName(const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, nullptr, name, {}, subpath, true, parent); } + static dconfig_dconf-global_meta* createGenericByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread()) + { return new dconfig_dconf-global_meta(thread, backend, name, {}, subpath, true, parent); } + ~dconfig_dconf-global_meta() { + int oldStatus = m_data->m_status.fetchAndStoreOrdered(static_cast(Data::Status::Destroyed)); + + m_data->m_userConfig = nullptr; + if (oldStatus == static_cast(Data::Status::Succeeded)) { + // When Succeeded, release config object only + auto config = m_data->m_config.loadRelaxed(); + Q_ASSERT(config); + config->deleteLater(); + // m_data will be deleted by config's destroyed signal + } else if (oldStatus == static_cast(Data::Status::Failed) || + oldStatus == static_cast(Data::Status::Invalid)) { + // When Failed or Invalid, directly clean up Data object + m_data->deleteLater(); } } + Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const { + return m_data->m_config.loadRelaxed(); + } + Q_INVOKABLE bool isInitializeSucceed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Succeeded); + } + Q_INVOKABLE bool isInitializeFailed() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Failed); + } + Q_INVOKABLE bool isInitializing() const { + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Initializing); + } + + Q_INVOKABLE QStringList keyList() const { + return { QStringLiteral("key3")}; + } + + Q_INVOKABLE bool isDefaultValue(const QString &key) const { + if (key == QStringLiteral("key3")) + return key3IsDefaultValue(); + return false; + } + QString key3() const { - return p_key3; + return m_data->p_key3; } void setKey3(const QString &value) { - auto oldValue = p_key3; - p_key3 = value; - markPropertySet(0); - if (auto config = m_config.loadRelaxed()) { - QMetaObject::invokeMethod(config, [this, value]() { - m_config.loadRelaxed()->setValue(QStringLiteral("key3"), value); + auto oldValue = m_data->p_key3; + m_data->p_key3 = value; + m_data->markPropertySet(0); + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config, value]() { + config->setValue(QStringLiteral("key3"), value); }); } - if (p_key3 != oldValue) { + if (m_data->p_key3 != oldValue) { Q_EMIT key3Changed(); + Q_EMIT valueChanged(QStringLiteral("key3"), value); } } + void resetKey3() { + if (auto config = m_data->m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [config]() { + config->reset(QStringLiteral("key3")); + }); + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QBindable bindableKey3() { + return QBindable(this, "key3"); + } +#endif + Q_INVOKABLE bool key3IsDefaultValue() const { + return !m_data->testPropertySet(0); + } +protected: + bool event(QEvent *e) override { + if (e->type() == QEvent::ThreadChange) { + Q_ASSERT(this->thread() == m_data->thread()); + } + return QObject::event(e); + } Q_SIGNALS: + void configInitializeFailed(); + void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config); + void valueChanged(const QString &key, const QVariant &value); void key3Changed(); + private: - void initialize(DTK_CORE_NAMESPACE::DConfig *config) { - Q_ASSERT(!m_config.loadRelaxed()); - m_config.storeRelaxed(config); - if (testPropertySet(0)) { - config->setValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); - } else { - updateValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); + // Prevent external moveToThread calls + using QObject::moveToThread; + class Data : public QObject { + public: + enum class Status { + Invalid = 0, + Initializing = 1, + Succeeded = 2, + Failed = 3, + Destroyed = 4 + }; + + explicit Data() + : QObject(nullptr) {} + + inline void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); + } else { + updateValue(QStringLiteral("key3"), QVariant::fromValue(p_key3)); + } + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); } - connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { - updateValue(key); - }, Qt::DirectConnection); - } - void updateValue(const QString &key, const QVariant &fallback = QVariant()) { - Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); - const QVariant &value = m_config.loadRelaxed()->value(key, fallback); - if (key == QStringLiteral("key3")) { - auto newValue = qvariant_cast(value); - QMetaObject::invokeMethod(this, [this, newValue]() { - if (p_key3 != newValue) { - p_key3 = newValue; - Q_EMIT key3Changed(); - } - }); - return; + inline 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("key3")) { + markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key)); + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue, key, value]() { + Q_ASSERT(QThread::currentThread() == m_userConfig->thread()); + if (m_userConfig && p_key3 != newValue) { + p_key3 = newValue; + Q_EMIT m_userConfig->key3Changed(); + Q_EMIT m_userConfig->valueChanged(key, value); + } + }); + return; + } } - } - inline void markPropertySet(const int index) { - if (index < 32) { - m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); - return; + inline void markPropertySet(const int index, bool on = true) { + if (index < 32) { + if (on) + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + else + m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0))); + return; + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - inline bool testPropertySet(const int index) const { - if (index < 32) { - return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); - } - QAtomicPointer m_config = nullptr; - QString p_key3 { QStringLiteral("global") }; - QAtomicInteger m_propertySetStatus0 = 0; + // Member variables + QAtomicPointer m_config = nullptr; + QAtomicInteger m_status = static_cast(Status::Invalid); + QPointer m_userConfig = nullptr; + QAtomicInteger m_propertySetStatus0 = 0; + + // Property storage + // Default value: "global" + QString p_key3 { QStringLiteral(u"\u0067\u006c\u006f\u0062\u0061\u006c") }; + }; + + Data *m_data; }; -#endif // DCONF-GLOBAL_META_H +#endif // DCONFIG_DCONF-GLOBAL_META_H diff --git a/tools/ch2py/CMakeLists.txt b/tools/ch2py/CMakeLists.txt index 18f2e434..3cba13a4 100644 --- a/tools/ch2py/CMakeLists.txt +++ b/tools/ch2py/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME ch2py) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/tools/dci/CMakeLists.txt b/tools/dci/CMakeLists.txt index 2174db24..271afb00 100644 --- a/tools/dci/CMakeLists.txt +++ b/tools/dci/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME dci) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/tools/dconfig2cpp/CMakeLists.txt b/tools/dconfig2cpp/CMakeLists.txt index 74f1d3c3..b90b55eb 100644 --- a/tools/dconfig2cpp/CMakeLists.txt +++ b/tools/dconfig2cpp/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME dconfig2cpp) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) @@ -21,6 +21,6 @@ set_target_properties( install( TARGETS ${BIN_NAME} - EXPORT Dtk${DTK_VERSION_MAJOR}ToolsTargets + EXPORT Dtk${DTK_NAME_SUFFIX}ToolsTargets DESTINATION ${TOOL_INSTALL_DIR} ) diff --git a/tools/dconfig2cpp/main.cpp b/tools/dconfig2cpp/main.cpp index 85d92a60..f77f56f1 100644 --- a/tools/dconfig2cpp/main.cpp +++ b/tools/dconfig2cpp/main.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) { headerStream << "#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)\n" << "#include \n" << "#endif\n"; - + headerStream << "#include \n"; headerStream << "#include \n"; headerStream << "#include \n\n"; headerStream << "class " << className << " : public QObject {\n"; @@ -215,6 +215,7 @@ int main(int argc, char *argv[]) { "isDefaultValue", "m_config", "m_status", + "m_data", }; for (int i = 0; i <= (contents.size()) / 32; ++i) { @@ -281,15 +282,30 @@ int main(int argc, char *argv[]) { << R"((QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId, const QString &subpath, bool isGeneric, QObject *parent) - : QObject(nullptr) { + : QObject(parent), m_data(new Data) { + m_data->m_userConfig = this; + m_data->moveToThread(this->thread()); + if (!thread->isRunning()) { qWarning() << QLatin1String("Warning: The provided thread is not running."); } Q_ASSERT(QThread::currentThread() != thread); auto worker = new QObject(); worker->moveToThread(thread); - QPointer watcher(parent); - QMetaObject::invokeMethod(worker, [=, this]() { + + QPointer safeData(m_data); + + QMetaObject::invokeMethod(worker, [safeData, backend, name, appId, subpath, isGeneric, worker]() mutable { + delete worker; + worker = nullptr; + + if (!safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Invalid), + static_cast(Data::Status::Initializing))) { + // CAS failed, state already changed - userConfig destructor will handle cleanup + // Do not attempt to delete here as it would race with destructor + return; + } + DTK_CORE_NAMESPACE::DConfig *config = nullptr; if (isGeneric) { if (backend) { @@ -314,21 +330,45 @@ int main(int argc, char *argv[]) { } } } - if (!config) { + + if (!config || !config->isValid()) { qWarning() << QLatin1String("Failed to create DConfig instance."); - worker->deleteLater(); + + QMetaObject::invokeMethod(safeData, [safeData]() { + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Failed))) { + Q_EMIT safeData->m_userConfig->configInitializeFailed(); + } else { + // CAS failed, destroy data object + delete safeData; + } + }, Qt::QueuedConnection); + + if (config) + delete config; + return; } config->moveToThread(QThread::currentThread()); - initializeInConfigThread(config); - if (watcher != parent) { - // delete this if watcher is changed to nullptr. - deleteLater(); - } else if (!this->parent() && parent) { - // !parent() means that parent is not changed. - this->setParent(watcher); + // Initialize through Data class + safeData->initializeInConfigThread(config); + + // Try to transition from Initializing to Succeeded + if (safeData->m_status.testAndSetOrdered(static_cast(Data::Status::Initializing), + static_cast(Data::Status::Succeeded))) { + // CAS succeeded, connect destroyed signal and emit success signal + QObject::connect(config, &QObject::destroyed, safeData, &QObject::deleteLater); + if (safeData->m_userConfig) { + QMetaObject::invokeMethod(safeData, [safeData, config]() { + Q_EMIT safeData->m_userConfig->configInitializeSucceed(config); + }, Qt::QueuedConnection); + } + } else { + // CAS failed - state changed (e.g., set to Destroyed) + // We must clean up the config we just created + config->deleteLater(); + safeData->deleteLater(); } - worker->deleteLater(); }); } )"; @@ -379,26 +419,33 @@ int main(int argc, char *argv[]) { // Destructor headerStream << " ~" << className << R"(() { - if (m_config.loadRelaxed()) { - m_config.loadRelaxed()->deleteLater(); - m_config.storeRelaxed(nullptr); + int oldStatus = m_data->m_status.fetchAndStoreOrdered(static_cast(Data::Status::Destroyed)); + + m_data->m_userConfig = nullptr; + if (oldStatus == static_cast(Data::Status::Succeeded)) { + // When Succeeded, release config object only + auto config = m_data->m_config.loadRelaxed(); + Q_ASSERT(config); + config->deleteLater(); + // m_data will be deleted by config's destroyed signal + } else if (oldStatus == static_cast(Data::Status::Failed) || + oldStatus == static_cast(Data::Status::Invalid)) { + // When Failed or Invalid, directly clean up Data object + m_data->deleteLater(); } } Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const { - return m_config.loadRelaxed(); + return m_data->m_config.loadRelaxed(); } - Q_INVOKABLE bool isInitializeSucceed() const { - return m_status.loadRelaxed() == static_cast(Status::Succeed); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Succeeded); } - Q_INVOKABLE bool isInitializeFailed() const { - return m_status.loadRelaxed() == static_cast(Status::Failed); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Failed); } - Q_INVOKABLE bool isInitializing() const { - return m_status.loadRelaxed() == static_cast(Status::Invalid); + return m_data->m_status.loadRelaxed() == static_cast(Data::Status::Initializing); } )"; @@ -424,25 +471,25 @@ int main(int argc, char *argv[]) { assert(!usedKeywords.contains(readFunction)); headerStream << " " << property.typeName << " " << readFunction << "() const {\n" - << " return p_" << property.propertyName << ";\n }\n"; + << " return m_data->p_" << property.propertyName << ";\n }\n"; headerStream << " void set" << property.capitalizedPropertyName << "(const " << property.typeName << " &value) {\n" - << " auto oldValue = p_" << property.propertyName << ";\n" - << " p_" << property.propertyName << " = value;\n" - << " markPropertySet(" << i << ");\n" - << " if (auto config = m_config.loadRelaxed()) {\n" - << " QMetaObject::invokeMethod(config, [this, value]() {\n" - << " m_config.loadRelaxed()->setValue(" << property.propertyNameString << ", value);\n" + << " auto oldValue = m_data->p_" << property.propertyName << ";\n" + << " m_data->p_" << property.propertyName << " = value;\n" + << " m_data->markPropertySet(" << i << ");\n" + << " if (auto config = m_data->m_config.loadRelaxed()) {\n" + << " QMetaObject::invokeMethod(config, [config, value]() {\n" + << " config->setValue(" << property.propertyNameString << ", value);\n" << " });\n" << " }\n" - << " if (p_" << property.propertyName << " != oldValue) {\n" + << " if (m_data->p_" << property.propertyName << " != oldValue) {\n" << " Q_EMIT " << property.propertyName << "Changed();\n" << " Q_EMIT valueChanged(" << property.propertyNameString << ", value);\n" << " }\n" << " }\n" << " void reset" << property.capitalizedPropertyName << "() {\n" - << " if (auto config = m_config.loadRelaxed()) {\n" - << " QMetaObject::invokeMethod(config, [this]() {\n" - << " m_config.loadRelaxed()->reset(" << property.propertyNameString << ");\n" + << " if (auto config = m_data->m_config.loadRelaxed()) {\n" + << " QMetaObject::invokeMethod(config, [config]() {\n" + << " config->reset(" << property.propertyNameString << ");\n" << " });\n" << " }\n" << " }\n"; @@ -453,129 +500,130 @@ int main(int argc, char *argv[]) { headerStream << "#endif\n"; headerStream << " Q_INVOKABLE bool " << property.propertyName << "IsDefaultValue() const {\n" - << " return !testPropertySet(" << i << ");\n" + << " return !m_data->testPropertySet(" << i << ");\n" << " }\n"; } - // Generate signals for property changes - headerStream << "Q_SIGNALS:\n" - << " void configInitializeFailed(DTK_CORE_NAMESPACE::DConfig *config);\n" + headerStream << "protected:\n" + << " bool event(QEvent *e) override {\n" + << " if (e->type() == QEvent::ThreadChange) {\n" + << " Q_ASSERT(this->thread() == m_data->thread());\n" + << " }\n" + << " return QObject::event(e);\n" + << " }\n" + << "Q_SIGNALS:\n" + << " void configInitializeFailed();\n" << " void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config);\n" - << " void valueChanged(const QString &key, const QVariant &value);\n\n"; - for (const Property &property : std::as_const(properties)) { - headerStream << " void " << property.propertyName << "Changed();\n"; - } + << " void valueChanged(const QString &key, const QVariant &value);\n"; + for (const auto &p : properties) + headerStream << " void " << p.propertyName << "Changed();\n"; + + headerStream << "\nprivate:\n" + << " // Prevent external moveToThread calls\n" + << " using QObject::moveToThread;\n" + << " class Data : public QObject {\n" + << " public:\n" + << " enum class Status {\n" + << " Invalid = 0,\n" + << " Initializing = 1,\n" + << " Succeeded = 2,\n" + << " Failed = 3,\n" + << " Destroyed = 4\n" + << " };\n" + << "\n" + << " explicit Data()\n" + << " : QObject(nullptr) {}\n" + << "\n" + << " inline void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) {\n" + << " Q_ASSERT(!m_config.loadRelaxed());\n" + << " m_config.storeRelaxed(config);\n"; - // Generate private methods and members - headerStream << "private:\n"; - - headerStream << " void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) {\n" - << " Q_ASSERT(!m_config.loadRelaxed());\n" - << " m_config.storeRelaxed(config);\n" - << " if (!config->isValid()) {\n" - << " m_status.storeRelaxed(static_cast(Status::Failed));\n" - << " Q_EMIT configInitializeFailed(config);\n" - << " return;\n" - << " }\n\n"; for (int i = 0; i < properties.size(); ++i) { const Property &property = properties[i]; - headerStream << " if (testPropertySet(" << i << ")) {\n"; - headerStream << " config->setValue(" << property.propertyNameString << ", QVariant::fromValue(p_" << property.propertyName << "));\n"; - headerStream << " } else {\n"; - headerStream << " updateValue(" << property.propertyNameString << ", QVariant::fromValue(p_" << property.propertyName << "));\n"; - headerStream << " }\n"; + headerStream << " if (testPropertySet(" << i << ")) {\n"; + headerStream << " config->setValue(" << property.propertyNameString << ", QVariant::fromValue(p_" << property.propertyName << "));\n"; + headerStream << " } else {\n"; + headerStream << " updateValue(" << property.propertyNameString << ", QVariant::fromValue(p_" << property.propertyName << "));\n"; + 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); - - m_status.storeRelaxed(static_cast(Status::Succeed)); - 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); + + headerStream << " connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) {\n" + << " updateValue(key);\n" + << " }, Qt::DirectConnection);\n" + << R"( } + + inline 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); )"; for (int i = 0; i < properties.size(); ++i) { const Property &property = properties.at(i); - headerStream << " if (key == " << property.propertyNameString << ") {\n"; - - headerStream << " markPropertySet(" << i << ", !m_config.loadRelaxed()->isDefaultValue(key));\n"; - - headerStream << " auto newValue = qvariant_cast<" << property.typeName << ">(value);\n" - << " QMetaObject::invokeMethod(this, [this, newValue, key, value]() {\n" - << " Q_ASSERT(QThread::currentThread() == this->thread());\n" - << " if (p_" << property.propertyName << " != newValue) {\n" - << " p_" << property.propertyName << " = newValue;\n" - << " Q_EMIT " << property.propertyName << "Changed();\n" - << " Q_EMIT valueChanged(key, value);\n" - << " }\n" - << " });\n" - << " return;\n" - << " }\n"; + headerStream << " if (key == " << property.propertyNameString << ") {\n"; + + headerStream << " markPropertySet(" << i << ", !m_config.loadRelaxed()->isDefaultValue(key));\n"; + + headerStream << " auto newValue = qvariant_cast<" << property.typeName << ">(value);\n" + << " QMetaObject::invokeMethod(this, [this, newValue, key, value]() {\n" + << " Q_ASSERT(QThread::currentThread() == m_userConfig->thread());\n" + << " if (m_userConfig && p_" << property.propertyName << " != newValue) {\n" + << " p_" << property.propertyName << " = newValue;\n" + << " Q_EMIT m_userConfig->" << property.propertyName << "Changed();\n" + << " Q_EMIT m_userConfig->valueChanged(key, value);\n" + << " }\n" + << " });\n" + << " return;\n" + << " }\n"; } - headerStream << " }\n"; + headerStream << " }\n"; // Mark property as set - headerStream << " inline void markPropertySet(const int index, bool on = true) {\n"; + headerStream << " inline void markPropertySet(const int index, bool on = true) {\n"; for (int i = 0; i <= (properties.size()) / 32; ++i) { - headerStream << " if (index < " << (i + 1) * 32 << ") {\n" - << " if (on)\n" - << " m_propertySetStatus" << QString::number(i) << ".fetchAndOrOrdered(1 << (index - " << i * 32 << "));\n" - << " else\n" - << " m_propertySetStatus" << QString::number(i) << ".fetchAndAndOrdered(~(1 << (index - " << i * 32 << ")));\n" - << " return;\n" - << " }\n"; + headerStream << " if (index < " << (i + 1) * 32 << ") {\n" + << " if (on)\n" + << " m_propertySetStatus" << QString::number(i) << ".fetchAndOrOrdered(1 << (index - " << i * 32 << "));\n" + << " else\n" + << " m_propertySetStatus" << QString::number(i) << ".fetchAndAndOrdered(~(1 << (index - " << i * 32 << ")));\n" + << " return;\n" + << " }\n"; } - headerStream << " Q_UNREACHABLE();\n }\n"; + headerStream << " Q_UNREACHABLE();\n }\n"; // Test if property is set - headerStream << " inline bool testPropertySet(const int index) const {\n"; + headerStream << " inline bool testPropertySet(const int index) const {\n"; for (int i = 0; i <= (properties.size()) / 32; ++i) { - headerStream << " if (index < " << (i + 1) * 32 << ") {\n"; - headerStream << " return (m_propertySetStatus" << QString::number(i) << ".loadRelaxed() & (1 << (index - " << i * 32 << ")));\n"; - headerStream << " }\n"; + headerStream << " if (index < " << (i + 1) * 32 << ") {\n" + << " return (m_propertySetStatus" << QString::number(i) << ".loadRelaxed() & (1 << (index - " << i * 32 << ")));\n" + << " }\n"; } - headerStream << " Q_UNREACHABLE();\n" - << " }\n"; - - // Member variables - headerStream << R"( - QAtomicPointer m_config = nullptr; - -public: - enum class Status { - Invalid = 0, - Succeed = 1, - Failed = 2 - }; -private: - QAtomicInteger m_status = static_cast(Status::Invalid); + headerStream << " Q_UNREACHABLE();\n" + << " }\n"; -)"; + headerStream << " // Member variables\n" + << " QAtomicPointer m_config = nullptr;\n" + << " QAtomicInteger m_status = static_cast(Status::Invalid);\n" + << " QPointer<" << className << "> m_userConfig = nullptr;\n"; - // Property variables - for (const Property &property : std::as_const(properties)) { - if (property.typeName == QLatin1String("int") || property.typeName == QLatin1String("qint64")) { - headerStream << " // Note: If you expect a double type, use XXX.0\n"; - } else if (property.typeName == QLatin1String("QString")) { - headerStream << " // Default value: \"" << property.defaultValue.toString().replace("\n", "\\n").replace("\r", "\\r") << "\"\n"; - } - headerStream << " " << property.typeName << " p_" << property.propertyName << " { "; - headerStream << jsonValueToCppCode(property.defaultValue) << " };\n"; + for (int i = 0; i <= (properties.size()) / 32; ++i) { + headerStream << " QAtomicInteger m_propertySetStatus" << i << " = 0;\n"; } - // Property set status variables - for (int i = 0; i <= (properties.size()) / 32; ++i) { - headerStream << " QAtomicInteger m_propertySetStatus" << QString::number(i) << " = 0;\n"; + headerStream << "\n // Property storage\n"; + for (const Property &property : properties) { + if (property.typeName == QLatin1String("QString")) { + headerStream << " // Default value: \"" + << property.defaultValue.toString().replace("\n", "\\n").replace("\r", "\\r") << "\"\n"; + } + headerStream << " " << property.typeName << " p_" << property.propertyName << " { " + << jsonValueToCppCode(property.defaultValue) << " };\n"; } - headerStream << "};\n\n"; - headerStream << "#endif // " << className.toUpper() << "_H\n"; + + headerStream << " };\n\n" + << " Data *m_data;\n" + << "};\n\n" + << "#endif // " << className.toUpper() << "_H\n"; return 0; } diff --git a/tools/deepin-os-release/CMakeLists.txt b/tools/deepin-os-release/CMakeLists.txt index 4cc96c3b..e59d249e 100644 --- a/tools/deepin-os-release/CMakeLists.txt +++ b/tools/deepin-os-release/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME deepin-os-release) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_AUTOMOC ON) diff --git a/tools/qdbusxml2cpp/CMakeLists.txt b/tools/qdbusxml2cpp/CMakeLists.txt index e47e7f96..6e020d80 100644 --- a/tools/qdbusxml2cpp/CMakeLists.txt +++ b/tools/qdbusxml2cpp/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME qdbusxml2cpp-fix) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) @@ -30,13 +30,13 @@ set_target_properties( install( TARGETS ${BIN_NAME} - EXPORT Dtk${DTK_VERSION_MAJOR}ToolsTargets + EXPORT Dtk${DTK_NAME_SUFFIX}ToolsTargets DESTINATION ${TOOL_INSTALL_DIR} ) install( - EXPORT Dtk${DTK_VERSION_MAJOR}ToolsTargets - FILE Dtk${DTK_VERSION_MAJOR}ToolsTargets.cmake - NAMESPACE Dtk${DTK_VERSION_MAJOR}:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Tools" + EXPORT Dtk${DTK_NAME_SUFFIX}ToolsTargets + FILE Dtk${DTK_NAME_SUFFIX}ToolsTargets.cmake + NAMESPACE Dtk${DTK_NAME_SUFFIX}:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_NAME_SUFFIX}Tools" ) diff --git a/tools/settings/CMakeLists.txt b/tools/settings/CMakeLists.txt index c56bbed8..e713c041 100644 --- a/tools/settings/CMakeLists.txt +++ b/tools/settings/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME dtk-settings) -set(BIN_NAME ${TARGET_NAME}${DTK_VERSION_MAJOR}) +set(BIN_NAME ${TARGET_NAME}${DTK_NAME_SUFFIX}) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml)