diff options
Diffstat (limited to 'src')
162 files changed, 4530 insertions, 1809 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8fa51056..48efd191 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,7 +61,7 @@ if(GPGFRONTEND_QT5_BUILD) else() # Introduce Qt # Support Qt version: 6.x - find_package(Qt6 6 COMPONENTS Core Widgets PrintSupport Network Core5Compat LinguistTools REQUIRED) + find_package(Qt6 6 COMPONENTS Core Widgets PrintSupport Network LinguistTools REQUIRED) endif() @@ -73,20 +73,29 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC_OPTIONS "--compress;9") set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_AUTOUIC_SEARCH_PATHS} ${CMAKE_SOURCE_DIR}/ui) +# Set Build Information +configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h @ONLY) +configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h @ONLY) +configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h @ONLY) +configure_file(${CMAKE_SOURCE_DIR}/src/module/sdk/GFSDKBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/module/sdk/GFSDKBuildInfo.h @ONLY) +if (APPLE) + configure_file(${CMAKE_SOURCE_DIR}/resource/plist/ExportOptions.plist.in ${CMAKE_BINARY_DIR}/ExportOptions.plist @ONLY) +endif () + +# Set Runtime Output Directory +if (NOT XCODE_BUILD) + # Set Binary Output Path + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts) +else () + # Set Binary Output Path + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}) +endif () # configure for output path and resources if (BUILD_APPLICATION) aux_source_directory(. BASE_SOURCE) set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_SOURCE_DIR}/gpgfrontend.rc") set_property(SOURCE gpgfrontend.rc APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/gpgfrontend.ico) - - if (NOT XCODE_BUILD) - # Set Binary Output Path - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts) - else () - # Set Binary Output Path - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}) - endif () endif () if (BUILD_CORE) @@ -121,10 +130,12 @@ if (BUILD_APPLICATION) if (APPLE) set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Resources) elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) - file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/app-image/gpgfrontend DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.metainfo.xml DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share/metainfo FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share/applications FOLLOW_SYMLINK_CHAIN) - set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share) + file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir) + file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/icons) + file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.metainfo.xml DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/metainfo FOLLOW_SYMLINK_CHAIN) + file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/applications FOLLOW_SYMLINK_CHAIN) + file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/com.bktus.gpgfrontend.png DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir FOLLOW_SYMLINK_CHAIN) + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share) else () set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endif () @@ -133,31 +144,14 @@ if (BUILD_APPLICATION) endif () endif () -if (BASIC_ENV_CONFIG) - # Set Build Information - configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h @ONLY) - configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h @ONLY) - configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h @ONLY) - if (APPLE) - configure_file(${CMAKE_SOURCE_DIR}/resource/plist/ExportOptions.plist.in ${CMAKE_BINARY_DIR}/ExportOptions.plist @ONLY) - endif () -endif () - -if (BUILD_APPLICATION) - # Copy Resource Files - file(COPY ${CMAKE_SOURCE_DIR}/resource/css DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/icons DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/TRANSLATORS DESTINATION ${RESOURCE_OUTPUT_DIRECTORY} FOLLOW_SYMLINK_CHAIN) -endif () - if (BUILD_APPLICATION) if (${CMAKE_BUILD_TYPE} STREQUAL "Release") if (APPLE) - file(COPY ${CMAKE_SOURCE_DIR}/gpgfrontend.icns DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) - # Refresh App Bundle - file(REMOVE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.app) + set(GPGFRONTEND_MACOS_ICON ${CMAKE_SOURCE_DIR}/gpgfrontend.icns) + set_source_files_properties(${GPGFRONTEND_MACOS_ICON} PROPERTIES + MACOSX_PACKAGE_LOCATION "Resources") elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) - file(REMOVE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/bin/${AppName}) + file(REMOVE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}) endif () endif () endif () @@ -341,39 +335,31 @@ if (BUILD_APPLICATION) add_custom_command(TARGET ${AppName} POST_BUILD COMMAND windeployqt-qt6.exe --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) endif() - elseif (APPLE AND NOT XCODE_BUILD) - # custom app bundle packing - add_executable(${AppName} MACOSX_BUNDLE ${ICON_RESOURCE} ${BASE_SOURCE} ${RESOURCE_FILES}) - set_target_properties(${AppName} PROPERTIES - BUNDLE True - MACOSX_BUNDLE_GUI_IDENTIFIER com.bktus.gpgfrontend - MACOSX_BUNDLE_BUNDLE_NAME ${AppName} - MACOSX_BUNDLE_LONG_VERSION_STRING ${BUILD_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} - MACOSX_BUNDLE_BUNDLE_VERSION ${BUILD_VERSION} - MACOSX_BUNDLE_ICON_FILE "gpgfrontend.icns") - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/rm -rf ./${AppName}.app/Contents/Resources - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Deleting Resources in App Bundle") - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/mv -n ./Resources ./${AppName}.app/Contents/ - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Copying Resources into App Bundle Resource") elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) + add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/mkdir -p ./gpgfrontend/usr/bin && /bin/mv -f ./${AppName} ./gpgfrontend/usr/bin/ - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Copying Binary into App Image") + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin" + COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}" + COMMENT "Copying Binary into App Image" + ) + add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/mkdir -p ./gpgfrontend/usr/lib - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Complement to build the required architecture") - # app bundle packing using xcode + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins" + COMMENT "Complement to build the required architecture" + ) + + add_custom_command(TARGET ${AppName} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins/mods" + COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins/mods" + COMMENT "Copying Mods into App Image" + ) + + # app bundle packing using xcode elseif (APPLE AND XCODE_BUILD) # standard app bundle packing - add_executable(${AppName} MACOSX_BUNDLE ${ICON_RESOURCE} ${BASE_SOURCE} ${RESOURCE_FILES}) + add_executable(${AppName} MACOSX_BUNDLE ${GPGFRONTEND_MACOS_ICON} ${BASE_SOURCE} ${RESOURCE_FILES}) + set_target_properties(${AppName} PROPERTIES BUNDLE True MACOSX_BUNDLE_GUI_IDENTIFIER com.bktus.gpgfrontend @@ -384,20 +370,7 @@ if (BUILD_APPLICATION) MACOSX_BUNDLE_COPYRIGHT "GPL-3.0" MACOSX_BUNDLE_INFO_STRING "An OpenPGP Crypto Tool" MACOSX_BUNDLE_ICON_FILE "gpgfrontend.icns" - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/resource/plist/MacOSXBundleInfo.plist.in - ) - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/rm -rf ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.app/Contents/Resources - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Deleting Resources in App Bundle") - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/cp -rf ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Resources ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${AppName}.app/Contents/ - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Copying Resources into App Bundle Resource") - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND macdeployqt ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${AppName}.app - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Resolving Qt Dependency") + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/resource/plist/MacOSXBundleInfo.plist.in) # option for sandbox mode, still under test if(GPGFRONTEND_XOCDE_ENABLE_SANDBOX) @@ -408,8 +381,7 @@ if (BUILD_APPLICATION) WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMENT "Copying Buddled GnuPG into App Bundle Resource") set_target_properties(${AppName} PROPERTIES - XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/resource/entitlements/GpgFrontend.entitlements" - ) + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/resource/entitlements/GpgFrontend.entitlements") else() message(STATUS "Build Application Without App Sandbox") set(CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX "No") @@ -421,10 +393,11 @@ if (BUILD_APPLICATION) XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep --entitlements ${CMAKE_SOURCE_DIR}/resource/plist/entitlement.plist" XCODE_ATTRIBUTE_ENABLE_APP_SANDBOX "${CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX}" XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}" - ) - else () + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") + elseif(LINUX AND LINUX_INSTALL_SOFTWARE) add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) + else () + message(FATAL_ERROR "cannot find a defined method to release application.") endif () else () # if the status is debug @@ -451,7 +424,7 @@ endif () # link options for GpgFrontend if (BUILD_APPLICATION) - target_link_libraries(${AppName} gpgfrontend_ui gpgfrontend_module gpgfrontend_test) + target_link_libraries(${AppName} gpgfrontend_ui gpgfrontend_test) if (MINGW) message(STATUS "Link Application Library For MINGW") target_link_libraries(${AppName} crypto) @@ -466,7 +439,8 @@ endif () # add i18n support if (BUILD_APPLICATION) set(LOCALE_TS_PATH ${CMAKE_SOURCE_DIR}/resource/lfs/locale/ts) - set(TS_FILES "${LOCALE_TS_PATH}/GpgFrontend.de_DE.ts" + set(TS_FILES "${LOCALE_TS_PATH}/GpgFrontend.en_US.ts" + "${LOCALE_TS_PATH}/GpgFrontend.de_DE.ts" "${LOCALE_TS_PATH}/GpgFrontend.fr_FR.ts" "${LOCALE_TS_PATH}/GpgFrontend.zh_CN.ts" "${LOCALE_TS_PATH}/GpgFrontend.zh_TW.ts" @@ -521,42 +495,35 @@ if (BUILD_APPLICATION) FILES ${QT_TRANSLATIONS_QM}) endif() - endif() # if building linux package if (LINUX AND LINUX_INSTALL_SOFTWARE) include(GNUInstallDirs) - if (INSTALL_GPGFRONTEND_APP) - install(TARGETS ${AppName} gpgfrontend_core gpgfrontend_ui - EXPORT GpgFrontendTargets - RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) - install(DIRECTORY ${PC_GPGME_LIBDIR} - DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - FILES_MATCHING PATTERN "libgpgme.so*" - PATTERN "lib" EXCLUDE) - install(DIRECTORY ${PC_GPGME_LIBDIR} - DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - FILES_MATCHING PATTERN "libassuan.so*" - PATTERN "lib" EXCLUDE) - install(DIRECTORY ${PC_GPGME_LIBDIR} - DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - FILES_MATCHING PATTERN "libgpg-error.so*" - PATTERN "lib" EXCLUDE) - install(FILES ${CMAKE_SOURCE_DIR}/TRANSLATORS - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/${AppName}/) - install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.appdata.xml - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/metainfo/) - install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/ - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/pixmaps/) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor/ - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/) - endif () + set(GPGFRONTEND_INSTALL_LIBRARIES + mimalloc + spdlog + gpgfrontend_core + gpgfrontend_ui + gpgfrontend_test + gpgfrontend_pinentry + gpgfrontend_module_sdk) + + message(STATUS "GpgFrontend Install Libraries: ${GPGFRONTEND_INSTALL_LIBRARIES}") + install(TARGETS ${AppName} ${GPGFRONTEND_INSTALL_LIBRARIES} + EXPORT GpgFrontendTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) + + install(FILES ${CMAKE_SOURCE_DIR}/TRANSLATORS + DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/${AppName}/) + install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.appdata.xml + DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/metainfo/) + install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop + DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/ + DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/pixmaps/) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor/ + DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/) endif () - -message(STATUS "Resource Files: ${RESOURCE_OUTPUT_DIRECTORY}") -message(STATUS "Runtime Files: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") diff --git a/src/GpgFrontendBuildInfo.h.in b/src/GpgFrontendBuildInfo.h.in index c6242b1e..37338de0 100644 --- a/src/GpgFrontendBuildInfo.h.in +++ b/src/GpgFrontendBuildInfo.h.in @@ -52,4 +52,10 @@ */ #define BUILD_FLAG "@BUILD_FLAG@" #define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@" -#define APP_INSTALL_FLAG "@APP_INSTALL_FLAG@"
\ No newline at end of file +#define APP_INSTALL_FLAG "@APP_INSTALL_FLAG@" + +/** + * @brief Network + * + */ +#define HTTP_REQUEST_USER_AGENT "@HTTP_REQUEST_USER_AGENT@"
\ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index a5539a37..9aa72894 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -29,7 +29,7 @@ #include "GpgFrontendContext.h" #include "core/GpgConstants.h" #include "core/GpgCoreInit.h" -#include "module/GpgFrontendModuleInit.h" +#include "core/module/ModuleInit.h" #include "ui/GpgFrontendUIInit.h" // main diff --git a/src/cmd.cpp b/src/cmd.cpp index cef0a984..d41b6de0 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -28,13 +28,13 @@ #include "cmd.h" +#include "core/utils/BuildInfoUtils.h" #include "main.h" // std #include <iostream> // GpgFrontend -#include "GpgFrontendBuildInfo.h" #include "GpgFrontendContext.h" #include "test/GpgFrontendTest.h" @@ -42,19 +42,19 @@ namespace GpgFrontend { auto PrintVersion() -> int { QTextStream stream(stdout); - stream << PROJECT_NAME << " " - << "v" << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH - << '\n'; + stream << PROJECT_NAME << " " << GetProjectVersion() << '\n'; stream << "Copyright (©) 2021 Saturneric <[email protected]>" << '\n' << QCoreApplication::tr( "This is free software; see the source for copying conditions.") << '\n' << '\n'; - stream << QCoreApplication::tr("Build DateTime: ") << BUILD_TIMESTAMP << '\n' - << QCoreApplication::tr("Build Version: ") << BUILD_VERSION << '\n' - << QCoreApplication::tr("Source Code Version: ") << GIT_VERSION - << '\n'; + stream << QCoreApplication::tr("Build DateTime: ") + << QLocale().toString(GetProjectBuildTimestamp()) << '\n' + << QCoreApplication::tr("Build Version: ") << GetProjectBuildVersion() + << '\n' + << QCoreApplication::tr("Source Code Version: ") + << GetProjectBuildGitVersion() << '\n'; stream << Qt::endl; return 0; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cc1f6742..cedbe69a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -129,7 +129,6 @@ if (MINGW) target_link_libraries(gpgfrontend_core PUBLIC wsock32) elseif (APPLE) message(STATUS "Link GPG Static Library For macOS") - target_link_libraries(gpgfrontend_core PUBLIC dl) if (XCODE_BUILD) set_target_properties(gpgfrontend_core PROPERTIES diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h index c2125650..91d5f1ef 100644 --- a/src/core/GpgConstants.h +++ b/src/core/GpgConstants.h @@ -30,6 +30,7 @@ namespace GpgFrontend { +constexpr int kNonRestartCode = 0; constexpr int kRestartCode = 1000; ///< only refresh ui constexpr int kDeepRestartCode = 1001; // refresh core and ui @@ -51,4 +52,10 @@ constexpr const char* PGP_PUBLIC_KEY_BEGIN = constexpr const char* PGP_PRIVATE_KEY_BEGIN = "-----BEGIN PGP PRIVATE KEY BLOCK-----"; ///< +// MODULE ID +const QString kGnuPGInfoGatheringModuleID = + "com.bktus.gpgfrontend.module.gnupg_info_gathering"; +const QString kVersionCheckingModuleID = + "com.bktus.gpgfrontend.module.version_checking"; + } // namespace GpgFrontend diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index 3a56c02a..2952d6e4 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -45,7 +45,17 @@ namespace GpgFrontend { -void DestroyGpgFrontendCore() { SingletonStorageCollection::Destroy(); } +void DestroyGpgFrontendCore() { + // kill all daemon if necessary + auto settings = GlobalSettingStation::GetInstance().GetSettings(); + auto kill_all_gnupg_daemon_at_close = + settings.value("gnupg/kill_all_gnupg_daemon_at_close", false).toBool(); + if (kill_all_gnupg_daemon_at_close) { + GpgAdvancedOperator::KillAllGpgComponents(); + } + + SingletonStorageCollection::Destroy(); +} auto VerifyGpgconfPath(const QFileInfo& gnupg_install_fs_path) -> bool { return gnupg_install_fs_path.isAbsolute() && gnupg_install_fs_path.exists() && @@ -176,7 +186,7 @@ auto InitGpgME(const QString& gpgconf_path, const QString& gnupg_path) -> bool { GF_CORE_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); // conditional check: only support gpg 2.1.x now - if (!(CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0 && find_gpgconf && + if (!(GFCompareSoftwareVersion(gnupg_version, "2.1.0") >= 0 && find_gpgconf && find_openpgp && find_cms)) { GF_CORE_LOG_ERROR("gpgme env check failed, abort"); return false; @@ -276,7 +286,6 @@ void InitGpgFrontendCore(CoreInitArgs args) { // initialize global register table Module::UpsertRTValue("core", "env.state.gpgme", 0); Module::UpsertRTValue("core", "env.state.ctx", 0); - Module::UpsertRTValue("core", "env.state.gnupg", 0); Module::UpsertRTValue("core", "env.state.basic", 0); Module::UpsertRTValue("core", "env.state.all", 0); @@ -319,7 +328,10 @@ void InitGpgFrontendCore(CoreInitArgs args) { .toString(); auto use_pinentry_as_password_input_dialog = - settings.value("gnupg/use_pinentry_as_password_input_dialog", true) + settings + .value( + "gnupg/use_pinentry_as_password_input_dialog", + QString::fromLocal8Bit(qgetenv("container")) != "flatpak") .toBool(); GF_CORE_LOG_DEBUG("core loaded if use custom key databse path: {}", @@ -406,60 +418,22 @@ void InitGpgFrontendCore(CoreInitArgs args) { QCoreApplication::tr("Gpg Key Detabase initiation failed")); }; } + GF_CORE_LOG_DEBUG( - "basic env checking finished, " - "including gpgme, ctx, and key infos"); + "basic env checking finished, including gpgme, ctx, and key infos"); + Module::UpsertRTValue("core", "env.state.basic", 1); CoreSignalStation::GetInstance()->SignalGoodGnupgEnv(); - // if gnupg-info-gathering module activated - if (args.gather_external_gnupg_info && - Module::IsModuleAcivate("com.bktus.gpgfrontend.module." - "integrated.gnupg-info-gathering")) { - GF_CORE_LOG_DEBUG( - "module gnupg-info-gathering is activated, " - "loading external gnupg info..."); - - // gather external gnupg info - Module::TriggerEvent( - "GPGFRONTEND_CORE_INITLIZED", - [](const Module::EventIdentifier& /*e*/, - const Module::Event::ListenerIdentifier& l_id, - DataObjectPtr o) { - GF_CORE_LOG_DEBUG( - "received event GPGFRONTEND_CORE_INITLIZED callback " - "from module: {}", - l_id); - - if (l_id == - "com.bktus.gpgfrontend.module.integrated.gnupg-info-" - "gathering") { - GF_CORE_LOG_DEBUG( - "received callback from gnupg-info-gathering "); - - // try to restart all components - auto settings = - GlobalSettingStation::GetInstance().GetSettings(); - auto restart_all_gnupg_components_on_start = - settings.value("gnupg/restart_gpg_agent_on_start", false) - .toBool(); - - if (restart_all_gnupg_components_on_start) { - GpgAdvancedOperator::RestartGpgComponents(); - } - Module::UpsertRTValue("core", "env.state.gnupg", 1); + // try to restart all components + auto restart_all_gnupg_components_on_start = + settings.value("gnupg/restart_gpg_agent_on_start", false).toBool(); - // announce that all checkings were finished - GF_CORE_LOG_INFO( - "all env checking finished, including gpgme, " - "ctx and gnupg"); - Module::UpsertRTValue("core", "env.state.all", 1); - } - }); - } else { - GF_CORE_LOG_DEBUG("gnupg-info-gathering is not activated"); - Module::UpsertRTValue("core", "env.state.all", 1); + if (restart_all_gnupg_components_on_start) { + GpgAdvancedOperator::RestartGpgComponents(); } + + Module::UpsertRTValue("core", "env.state.all", 1); return 0; }, "core_init_task"); diff --git a/src/core/GpgCoreInit.h b/src/core/GpgCoreInit.h index 15f0254d..ecd6afea 100644 --- a/src/core/GpgCoreInit.h +++ b/src/core/GpgCoreInit.h @@ -28,7 +28,7 @@ #pragma once -#include "GpgConstants.h" +#include "core/GpgFrontendCoreExport.h" namespace GpgFrontend { diff --git a/src/core/GpgFrontendCore.h b/src/core/GpgFrontendCore.h index 14b1f878..f07824cf 100644 --- a/src/core/GpgFrontendCore.h +++ b/src/core/GpgFrontendCore.h @@ -30,23 +30,3 @@ // Qt #include <QtCore> - -// std -#include <cstdint> -#include <vector> - -// spdlog library configuration -#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE -#include <spdlog/spdlog.h> - -// logger fmt -#include "log/QtLoggerFmt.h" - -// gpgme library -#include <gpgme.h> - -// logbal includes or macroes -#include "GpgFrontend.h" - -// dll export macroes -#include "GpgFrontendCoreExport.h" diff --git a/src/core/function/CoreSignalStation.h b/src/core/function/CoreSignalStation.h index e0a11fa3..8827c803 100644 --- a/src/core/function/CoreSignalStation.h +++ b/src/core/function/CoreSignalStation.h @@ -28,7 +28,7 @@ #pragma once -#include "core/GpgFrontendCore.h" +#include "core/GpgFrontendCoreExport.h" namespace GpgFrontend { diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp index 7b21ebca..45ab11f9 100644 --- a/src/core/function/GlobalSettingStation.cpp +++ b/src/core/function/GlobalSettingStation.cpp @@ -69,6 +69,7 @@ class GlobalSettingStation::Impl { if (!QDir(app_data_path_).exists()) QDir(app_data_path_).mkpath("."); if (!QDir(app_log_path_).exists()) QDir(app_log_path_).mkpath("."); + if (!QDir(GetModulesDir()).exists()) QDir(GetModulesDir()).mkpath("."); } [[nodiscard]] auto GetSettings() -> QSettings { @@ -124,6 +125,15 @@ class GlobalSettingStation::Impl { */ [[nodiscard]] auto GetLogDir() const -> QString { return app_log_path_; } + /** + * @brief Get the Modules Dir object + * + * @return QString + */ + [[nodiscard]] auto GetModulesDir() const -> QString { + return GetAppDataPath() + "/mods"; + } + private: QString working_path_ = QDir::currentPath(); @@ -174,6 +184,10 @@ auto GlobalSettingStation::GetAppDataPath() const -> QString { return p_->GetLogDir(); } +[[nodiscard]] auto GlobalSettingStation::GetModulesDir() const -> QString { + return p_->GetModulesDir(); +} + auto GlobalSettingStation::GetLogFilesSize() const -> QString { return p_->GetLogFilesSize(); } diff --git a/src/core/function/GlobalSettingStation.h b/src/core/function/GlobalSettingStation.h index 85ac57b4..c907bdb5 100644 --- a/src/core/function/GlobalSettingStation.h +++ b/src/core/function/GlobalSettingStation.h @@ -83,6 +83,13 @@ class GPGFRONTEND_CORE_EXPORT GlobalSettingStation [[nodiscard]] auto GetLogDir() const -> QString; /** + * @brief Get the Modules Dir object + * + * @return QString + */ + [[nodiscard]] auto GetModulesDir() const -> QString; + + /** * @brief Get the Log Files Size object * * @return QString diff --git a/src/core/function/SecureMemoryAllocator.h b/src/core/function/SecureMemoryAllocator.h index e9f1c1c3..e86d54d6 100644 --- a/src/core/function/SecureMemoryAllocator.h +++ b/src/core/function/SecureMemoryAllocator.h @@ -28,9 +28,7 @@ #pragma once -#include <cstdint> -#include <memory> - +#include "core/GpgFrontendCoreExport.h" #include "core/utils/LogUtils.h" namespace GpgFrontend { diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index 1ea352b6..422af4a1 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -29,7 +29,6 @@ #pragma once #include <mutex> -#include <stdexcept> #include "core/GpgFrontendCoreExport.h" #include "core/function/basic/ChannelObject.h" diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp index 3fc831ed..cb8fec00 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.cpp +++ b/src/core/function/gpg/GpgAdvancedOperator.cpp @@ -76,6 +76,34 @@ void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( }}); } +void GpgFrontend::GpgAdvancedOperator::KillAllGpgComponents() { + const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gpgconf_path", QString{}); + GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); + + if (gpgconf_path.isEmpty()) { + GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + return; + } + + GpgFrontend::GpgCommandExecutor::ExecuteSync( + {gpgconf_path, QStringList{"--verbose", "--kill", "all"}, + [=](int exit_code, const QString &p_out, const QString &p_err) { + GF_CORE_LOG_DEBUG("gpgconf --kill all command got exit code: {}", + exit_code); + bool success = true; + if (exit_code != 0) { + success = false; + GF_CORE_LOG_ERROR( + "gpgconf execute error, process stderr: {}, process stdout: {}", + p_err, p_out); + return; + } + + GF_CORE_LOG_DEBUG("gpgconf --kill --all execute result: {}", success); + }}); +} + void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents() { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); @@ -139,14 +167,17 @@ void GpgFrontend::GpgAdvancedOperator::ResetConfigures(OperationCallback cb) { } void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) { + if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + cb(-1, TransferParams()); + return; + } + const auto gpg_agent_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.gpg_agent_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.gpg_agent_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg agent path from rt: {}", gpg_agent_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.home_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (gpg_agent_path.isEmpty()) { @@ -164,14 +195,17 @@ void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) { } void GpgFrontend::GpgAdvancedOperator::StartDirmngr(OperationCallback cb) { + if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + cb(-1, TransferParams()); + return; + } + const auto dirmngr_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.dirmngr_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.dirmngr_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg dirmngr path from rt: {}", dirmngr_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.home_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (dirmngr_path.isEmpty()) { @@ -189,14 +223,17 @@ void GpgFrontend::GpgAdvancedOperator::StartDirmngr(OperationCallback cb) { } void GpgFrontend::GpgAdvancedOperator::StartKeyBoxd(OperationCallback cb) { + if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + cb(-1, TransferParams()); + return; + } + const auto keyboxd_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.keyboxd_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.keyboxd_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg keyboxd path from rt: {}", keyboxd_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.home_path", QString{}); + kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (keyboxd_path.isEmpty()) { diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h index d6b57095..26391e03 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.h +++ b/src/core/function/gpg/GpgAdvancedOperator.h @@ -93,6 +93,12 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { * @return false */ static void StartKeyBoxd(OperationCallback); + + /** + * @brief + * + */ + static void KillAllGpgComponents(); }; } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 7c84d3c4..7dec318e 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -94,18 +94,18 @@ class GpgContext::Impl { int fd) -> gpgme_error_t { size_t res; #ifdef QT5_BUILD - QString pass_qstr = "abcdefg\n"; - QByteArray pass = pass_qstr.toUtf8(); + QString pass_qstr = "abcdefg\n"; + QByteArray pass = pass_qstr.toUtf8(); #else - QString pass = "abcdefg\n"; + QString pass = "abcdefg\n"; #endif - + auto passpahrase_size = pass.size(); size_t off = 0; do { #ifdef QT5_BUILD - const char* p_pass = pass.data(); + const char *p_pass = pass.data(); res = gpgme_io_write(fd, &p_pass[off], passpahrase_size - off); #else res = gpgme_io_write(fd, &pass[off], passpahrase_size - off); @@ -246,15 +246,14 @@ class GpgContext::Impl { } // set context offline mode - GF_CORE_LOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + GF_CORE_LOG_DEBUG("gpg context: offline mode: {}", args_.offline_mode); + GF_CORE_LOG_DEBUG("gpg context: auto import missing key: {}", + args_.auto_import_missing_key); gpgme_set_offline(ctx, args_.offline_mode ? 1 : 0); // set option auto import missing key - // invalid at offline mode - GF_CORE_LOG_DEBUG("gpg context auto import missing key: {}", - args_.offline_mode); - if (!args.offline_mode && args.auto_import_missing_key) { - if (CheckGpgError(gpgme_set_ctx_flag(ctx, "auto-key-import", "1")) != + if (!args_.offline_mode && args.auto_import_missing_key) { + if (CheckGpgError(gpgme_set_ctx_flag(ctx, "auto-key-retrieve", "1")) != GPG_ERR_NO_ERROR) { return false; } diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index d473a341..2a8f6fdd 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -28,6 +28,8 @@ #pragma once +#include <gpgme.h> + #include "core/function/SecureMemoryAllocator.h" #include "core/function/basic/GpgFunctionObject.h" diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index e0ecb3ce..14d58a10 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -502,7 +502,7 @@ auto GpgKeyOpera::ModifyTOFUPolicy(const GpgKey& key, "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); GF_CORE_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); - if (CompareSoftwareVersion(gnupg_version, "2.1.10") < 0) { + if (GFCompareSoftwareVersion(gnupg_version, "2.1.10") < 0) { GF_CORE_LOG_ERROR("operator not support"); return GPG_ERR_NOT_SUPPORTED; } diff --git a/src/core/function/result_analyse/GpgSignResultAnalyse.cpp b/src/core/function/result_analyse/GpgSignResultAnalyse.cpp index 3f3040b8..e02996b3 100644 --- a/src/core/function/result_analyse/GpgSignResultAnalyse.cpp +++ b/src/core/function/result_analyse/GpgSignResultAnalyse.cpp @@ -103,11 +103,9 @@ void GpgSignResultAnalyse::doAnalyse() { stream_ << "- " << tr("Hash Algo") << ": " << gpgme_hash_algo_name(new_sign->hash_algo) << Qt::endl; stream_ << "- " << tr("Sign Date") << "(" << tr("UTC") << ")" - << ": " - << QDateTime::fromSecsSinceEpoch(new_sign->timestamp).toString() - << Qt::endl; + << ": " << GetUTCDateByTimestamp(new_sign->timestamp) << Qt::endl; stream_ << "- " << tr("Sign Date") << "(" << tr("Localized") << ")" - << ": " << GetFormatedDateByTimestamp(new_sign->timestamp) + << ": " << GetLocalizedDateByTimestamp(new_sign->timestamp) << Qt::endl; stream_ << Qt::endl diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp index df6b58b0..0a098a93 100644 --- a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp +++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp @@ -55,11 +55,10 @@ void GpgFrontend::GpgVerifyResultAnalyse::doAnalyse() { auto *sign = result->signatures; stream_ << "-> " << tr("Signed On") << "(" << tr("UTC") << ")" - << ": " << QDateTime::fromSecsSinceEpoch(sign->timestamp).toString() - << Qt::endl; + << ": " << GetUTCDateByTimestamp(sign->timestamp) << Qt::endl; stream_ << "-> " << tr("Signed On") << "(" << tr("Localized") << ")" - << ": " << GetFormatedDateByTimestamp(sign->timestamp) << Qt::endl; + << ": " << GetLocalizedDateByTimestamp(sign->timestamp) << Qt::endl; stream_ << Qt::endl << "## " << tr("Signatures List") << ":" << Qt::endl; stream_ << Qt::endl; @@ -190,7 +189,8 @@ auto GpgFrontend::GpgVerifyResultAnalyse::print_signer_without_key( << Qt::endl; stream << "- " << tr("Hash Algo") << ": " << sign.GetHashAlgo() << Qt::endl; stream << "- " << tr("Sign Date") << "(" << tr("UTC") << ")" - << ": " << sign.GetCreateTime().toString() << Qt::endl; + << ": " << QLocale().toString(sign.GetCreateTime().toUTC()) + << Qt::endl; stream << "- " << tr("Sign Date") << "(" << tr("Localized") << ")" << ": " << QLocale().toString(sign.GetCreateTime()) << Qt::endl; return true; @@ -235,7 +235,8 @@ auto GpgFrontend::GpgVerifyResultAnalyse::print_signer(QTextStream &stream, << Qt::endl; stream << "- " << tr("Hash Algo") << ": " << sign.GetHashAlgo() << Qt::endl; stream << "- " << tr("Sign Date") << "(" << tr("UTC") << ")" - << ": " << sign.GetCreateTime().toString() << Qt::endl; + << ": " << QLocale().toString(sign.GetCreateTime().toUTC()) + << Qt::endl; stream << "- " << tr("Sign Date") << "(" << tr("Localized") << ")" << ": " << QLocale().toString(sign.GetCreateTime()) << Qt::endl; stream << Qt::endl; diff --git a/src/ui/struct/CacheObject.cpp b/src/core/model/CacheObject.cpp index bd3b9818..37dedd92 100644 --- a/src/ui/struct/CacheObject.cpp +++ b/src/core/model/CacheObject.cpp @@ -30,7 +30,7 @@ #include "core/function/CacheManager.h" -namespace GpgFrontend::UI { +namespace GpgFrontend { CacheObject::CacheObject(QString cache_name) : cache_name_(std::move(cache_name)) { @@ -42,4 +42,4 @@ CacheObject::~CacheObject() { CacheManager::GetInstance().SaveDurableCache(cache_name_, *this); } -} // namespace GpgFrontend::UI
\ No newline at end of file +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/ui/struct/CacheObject.h b/src/core/model/CacheObject.h index ae8aa056..3cfa8083 100644 --- a/src/ui/struct/CacheObject.h +++ b/src/core/model/CacheObject.h @@ -28,9 +28,11 @@ #pragma once -namespace GpgFrontend::UI { +#include "core/GpgFrontendCoreExport.h" -class CacheObject : public QJsonDocument { +namespace GpgFrontend { + +class GPGFRONTEND_CORE_EXPORT CacheObject : public QJsonDocument { public: /** * @brief Construct a new Cache Object object @@ -49,4 +51,4 @@ class CacheObject : public QJsonDocument { QString cache_name_; ///< }; -} // namespace GpgFrontend::UI
\ No newline at end of file +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgData.h b/src/core/model/GpgData.h index 358ebd19..eb1d7621 100644 --- a/src/core/model/GpgData.h +++ b/src/core/model/GpgData.h @@ -28,6 +28,8 @@ #pragma once +#include <gpgme.h> + #include "core/GpgFrontendCoreExport.h" #include "core/model/GFBuffer.h" #include "core/typedef/CoreTypedef.h" diff --git a/src/core/model/GpgGenKeyInfo.h b/src/core/model/GpgGenKeyInfo.h index 166c6b0f..65a7d03e 100644 --- a/src/core/model/GpgGenKeyInfo.h +++ b/src/core/model/GpgGenKeyInfo.h @@ -28,6 +28,8 @@ #pragma once +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { class GPGFRONTEND_CORE_EXPORT GenKeyInfo { diff --git a/src/core/model/GpgGenerateKeyResult.h b/src/core/model/GpgGenerateKeyResult.h index f312d415..dfd92ae1 100644 --- a/src/core/model/GpgGenerateKeyResult.h +++ b/src/core/model/GpgGenerateKeyResult.h @@ -28,6 +28,8 @@ #pragma once +#include <gpgme.h> + #include "core/GpgFrontendCore.h" #include "core/GpgFrontendCoreExport.h" diff --git a/src/core/model/GpgImportInformation.h b/src/core/model/GpgImportInformation.h index 5f85a338..cbe5a265 100644 --- a/src/core/model/GpgImportInformation.h +++ b/src/core/model/GpgImportInformation.h @@ -28,6 +28,10 @@ #pragma once +#include <gpgme.h> + +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { /** diff --git a/src/core/model/GpgPassphraseContext.cpp b/src/core/model/GpgPassphraseContext.cpp index 5df3f5a8..0156c04d 100644 --- a/src/core/model/GpgPassphraseContext.cpp +++ b/src/core/model/GpgPassphraseContext.cpp @@ -28,6 +28,7 @@ #include "GpgPassphraseContext.h" + namespace GpgFrontend { GpgPassphraseContext::GpgPassphraseContext(const QString& uids_info, diff --git a/src/core/model/GpgPassphraseContext.h b/src/core/model/GpgPassphraseContext.h index 2bc1ac75..1db36f62 100644 --- a/src/core/model/GpgPassphraseContext.h +++ b/src/core/model/GpgPassphraseContext.h @@ -30,6 +30,8 @@ #pragma once +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { class GPGFRONTEND_CORE_EXPORT GpgPassphraseContext : public QObject { diff --git a/src/core/model/GpgSubKey.h b/src/core/model/GpgSubKey.h index 83d75e2d..8257eab8 100644 --- a/src/core/model/GpgSubKey.h +++ b/src/core/model/GpgSubKey.h @@ -28,6 +28,10 @@ #pragma once +#include <gpgme.h> + +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { /** diff --git a/src/core/model/GpgTOFUInfo.h b/src/core/model/GpgTOFUInfo.h index ec4c49b7..5e8d83d4 100644 --- a/src/core/model/GpgTOFUInfo.h +++ b/src/core/model/GpgTOFUInfo.h @@ -28,6 +28,10 @@ #pragma once +#include <gpgme.h> + +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { /** * @brief diff --git a/src/ui/struct/SettingsObject.cpp b/src/core/model/SettingsObject.cpp index cc5e85bf..09824f12 100644 --- a/src/ui/struct/SettingsObject.cpp +++ b/src/core/model/SettingsObject.cpp @@ -30,25 +30,25 @@ #include "core/function/DataObjectOperator.h" -namespace GpgFrontend::UI { +namespace GpgFrontend { SettingsObject::SettingsObject(QString settings_name) : settings_name_(std::move(settings_name)) { try { - GF_UI_LOG_DEBUG("loading settings from: {}", this->settings_name_); + GF_CORE_LOG_DEBUG("loading settings from: {}", this->settings_name_); auto json_optional = DataObjectOperator::GetInstance().GetDataObject(settings_name_); if (json_optional.has_value() && json_optional->isObject()) { - GF_UI_LOG_DEBUG("settings object: {} loaded.", settings_name_); + GF_CORE_LOG_DEBUG("settings object: {} loaded.", settings_name_); QJsonObject::operator=(json_optional.value().object()); } else { - GF_UI_LOG_DEBUG("settings object: {} not found.", settings_name_); + GF_CORE_LOG_DEBUG("settings object: {} not found.", settings_name_); QJsonObject::operator=({}); } } catch (std::exception& e) { - GF_UI_LOG_ERROR("load setting object error: {}", e.what()); + GF_CORE_LOG_ERROR("load setting object error: {}", e.what()); } } @@ -66,4 +66,4 @@ void SettingsObject::Store(const QJsonObject& json) { auto* parent = (static_cast<QJsonObject*>(this)); *parent = json; } -} // namespace GpgFrontend::UI
\ No newline at end of file +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/ui/struct/SettingsObject.h b/src/core/model/SettingsObject.h index a9e5819f..4b52f31d 100644 --- a/src/ui/struct/SettingsObject.h +++ b/src/core/model/SettingsObject.h @@ -28,14 +28,16 @@ #pragma once -namespace GpgFrontend::UI { +#include "core/GpgFrontendCoreExport.h" + +namespace GpgFrontend { /** * @brief The SettingsObject class * This class is used to store data for the application securely. * */ -class SettingsObject : public QJsonObject { +class GPGFRONTEND_CORE_EXPORT SettingsObject : public QJsonObject { public: /** * @brief Construct a new Settings Object object @@ -66,4 +68,4 @@ class SettingsObject : public QJsonObject { private: QString settings_name_; ///< }; -} // namespace GpgFrontend::UI +} // namespace GpgFrontend diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp index fab26453..4b0b989b 100644 --- a/src/core/module/Event.cpp +++ b/src/core/module/Event.cpp @@ -28,6 +28,8 @@ #include "Event.h" +#include "core/utils/CommonUtils.h" + namespace GpgFrontend::Module { class Event::Impl { @@ -67,7 +69,11 @@ class Event::Impl { auto GetIdentifier() -> EventIdentifier { return event_identifier_; } - void AddParameter(const QString& key, const ParameterValue& value) { + auto GetTriggerIdentifier() -> EventTriggerIdentifier { + return trigger_uuid_; + } + + void AddParameter(const QString& key, const QString& value) { data_[key] = value; } @@ -95,9 +101,37 @@ class Event::Impl { } } + auto ToModuleEvent() -> GFModuleEvent* { + auto* event = + static_cast<GFModuleEvent*>(SecureMalloc(sizeof(GFModuleEvent))); + + event->id = GFStrDup(event_identifier_); + event->trigger_id = GFStrDup(trigger_uuid_); + + GFModuleEventParam* l_param = nullptr; + GFModuleEventParam* p_param; + + int index = 0; + for (const auto& data : data_) { + p_param = static_cast<GFModuleEventParam*>( + SecureMalloc(sizeof(GFModuleEventParam))); + if (index++ == 0) event->params = p_param; + + p_param->name = GFStrDup(data.first); + p_param->value = GFStrDup(data.second); + p_param->next = nullptr; + + if (l_param != nullptr) l_param->next = p_param; + l_param = p_param; + } + + return event; + } + private: EventIdentifier event_identifier_; - std::map<QString, ParameterValue> data_; + EventTriggerIdentifier trigger_uuid_ = QUuid::createUuid().toString(); + std::map<QString, QString> data_; EventCallback callback_; QThread* callback_thread_ = nullptr; ///< }; @@ -128,7 +162,11 @@ auto Event::Event::GetIdentifier() -> EventIdentifier { return p_->GetIdentifier(); } -void Event::AddParameter(const QString& key, const ParameterValue& value) { +auto Event::Event::GetTriggerIdentifier() -> EventTriggerIdentifier { + return p_->GetTriggerIdentifier(); +} + +void Event::AddParameter(const QString& key, const QString& value) { p_->AddParameter(key, value); } @@ -136,4 +174,6 @@ void Event::ExecuteCallback(ListenerIdentifier l_id, DataObjectPtr d_o) { p_->ExecuteCallback(std::move(l_id), d_o); } +auto Event::ToModuleEvent() -> GFModuleEvent* { return p_->ToModuleEvent(); } + } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/Event.h b/src/core/module/Event.h index 92268216..b629caae 100644 --- a/src/core/module/Event.h +++ b/src/core/module/Event.h @@ -34,13 +34,15 @@ #include "core/GpgFrontendCore.h" #include "core/model/DataObject.h" +#include "module/sdk/GFSDKModule.h" namespace GpgFrontend::Module { class Event; -using EventRefrernce = std::shared_ptr<Event>; +using EventReference = std::shared_ptr<Event>; using EventIdentifier = QString; +using EventTriggerIdentifier = QString; using Evnets = std::vector<Event>; class GPGFRONTEND_CORE_EXPORT Event { @@ -52,7 +54,7 @@ class GPGFRONTEND_CORE_EXPORT Event { std::function<void(EventIdentifier, ListenerIdentifier, DataObjectPtr)>; struct ParameterInitializer { QString key; - ParameterValue value; + QString value; }; explicit Event(const QString&, @@ -75,10 +77,14 @@ class GPGFRONTEND_CORE_EXPORT Event { auto GetIdentifier() -> EventIdentifier; - void AddParameter(const QString& key, const ParameterValue& value); + auto GetTriggerIdentifier() -> EventTriggerIdentifier; + + void AddParameter(const QString& key, const QString& value); void ExecuteCallback(ListenerIdentifier, DataObjectPtr); + auto ToModuleEvent() -> GFModuleEvent*; + private: class Impl; SecureUniquePtr<Impl> p_; @@ -86,7 +92,7 @@ class GPGFRONTEND_CORE_EXPORT Event { template <typename... Args> auto MakeEvent(const EventIdentifier& event_id, Args&&... args, - Event::EventCallback e_cb) -> EventRefrernce { + Event::EventCallback e_cb) -> EventReference { std::initializer_list<Event::ParameterInitializer> params = { Event::ParameterInitializer{std::forward<Args>(args)}...}; return GpgFrontend::SecureCreateSharedObject<Event>(event_id, params, e_cb); diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp index 9bc4f06b..e67e48f9 100644 --- a/src/core/module/GlobalModuleContext.cpp +++ b/src/core/module/GlobalModuleContext.cpp @@ -31,6 +31,7 @@ #include <set> #include <unordered_map> #include <unordered_set> +#include <utility> #include "core/module/Event.h" #include "core/module/Module.h" @@ -49,6 +50,18 @@ class GlobalModuleContext::Impl { acquired_channel_.insert(kGpgFrontendNonAsciiChannel); } + auto SearchModule(ModuleIdentifier module_id) -> ModulePtr { + // Search for the module in the register table. + auto module_info_opt = search_module_register_table(module_id); + if (!module_info_opt.has_value()) { + GF_CORE_LOG_ERROR("cannot find module id {} at register table", + module_id); + return nullptr; + } + + return module_info_opt.value()->module; + } + auto GetChannel(ModuleRawPtr module) -> int { // Search for the module in the register table. auto module_info_opt = @@ -85,7 +98,7 @@ class GlobalModuleContext::Impl { return default_task_runner_; } - auto RegisterModule(const ModulePtr& module) -> bool { + auto RegisterModule(const ModulePtr& module, bool integrated_module) -> bool { GF_CORE_LOG_DEBUG("attempting to register module: {}", module->GetModuleIdentifier()); // Check if the module is null or already registered. @@ -97,7 +110,7 @@ class GlobalModuleContext::Impl { return false; } - if (!module->Register()) { + if (module->Register() != 0) { GF_CORE_LOG_ERROR("register module {} failed", module->GetModuleIdentifier()); return false; @@ -107,6 +120,7 @@ class GlobalModuleContext::Impl { GpgFrontend::SecureCreateSharedObject<ModuleRegisterInfo>(); register_info->module = module; register_info->channel = acquire_new_unique_channel(); + register_info->integrated = integrated_module; // move module to its task runner' thread register_info->module->setParent(nullptr); @@ -158,6 +172,15 @@ class GlobalModuleContext::Impl { auto ListenEvent(ModuleIdentifier module_id, EventIdentifier event) -> bool { GF_CORE_LOG_DEBUG("module: {} is attempting to listen to event {}", module_id, event); + + // module -> event + auto module_info_opt = search_module_register_table(module_id); + if (!module_info_opt.has_value()) { + GF_CORE_LOG_ERROR("cannot find module id {} at register table", + module_id); + return false; + } + // Check if the event exists, if not, create it. auto met_it = module_events_table_.find(event); if (met_it == module_events_table_.end()) { @@ -166,6 +189,8 @@ class GlobalModuleContext::Impl { GF_CORE_LOG_DEBUG("new event {} of module system created", event); } + module_info_opt.value()->listening_event_ids.push_back(event); + auto& listeners_set = met_it->second; // Add the listener (module) to the event. auto listener_it = listeners_set.find(module_id); @@ -176,7 +201,7 @@ class GlobalModuleContext::Impl { } auto DeactivateModule(ModuleIdentifier module_id) -> bool { - // Search for the module in the register table. + // search for the module in the register table. auto module_info_opt = search_module_register_table(module_id); if (!module_info_opt.has_value()) { GF_CORE_LOG_ERROR("cannot find module id {} at register table", @@ -185,15 +210,23 @@ class GlobalModuleContext::Impl { } auto module_info = module_info_opt.value(); - // Activate the module if it is not already deactive. - if (!module_info->activate && module_info->module->Deactive()) { + // activate the module if it is not already deactive. + if (module_info->activate && (module_info->module->Deactive() == 0)) { + for (const auto& event_ids : module_info->listening_event_ids) { + auto& modules = module_events_table_[event_ids]; + if (auto it = modules.find(module_id); it != modules.end()) { + modules.erase(it); + } + } + + module_info->listening_event_ids.clear(); module_info->activate = false; } return !module_info->activate; } - auto TriggerEvent(const EventRefrernce& event) -> bool { + auto TriggerEvent(const EventReference& event) -> bool { auto event_id = event->GetIdentifier(); GF_CORE_LOG_DEBUG("attempting to trigger event: {}", event_id); @@ -222,6 +255,9 @@ class GlobalModuleContext::Impl { GF_CORE_LOG_DEBUG("event {}'s current listeners size: {}", event->GetIdentifier(), listeners_set.size()); + // register trigger id index table + module_on_triggering_events_table_[event->GetTriggerIdentifier()] = event; + // Iterate through each listener and execute the corresponding module for (const auto& listener_module_id : listeners_set) { // Search for the module's information in the registration table @@ -272,16 +308,49 @@ class GlobalModuleContext::Impl { return true; } - auto IsModuleActivated(const ModuleIdentifier& m_id) const -> bool { + auto SearchEvent(const EventTriggerIdentifier& trigger_id) + -> std::optional<EventReference> { + if (module_on_triggering_events_table_.find(trigger_id) != + module_on_triggering_events_table_.end()) { + return module_on_triggering_events_table_[trigger_id]; + } + return {}; + } + + [[nodiscard]] auto IsModuleActivated(const ModuleIdentifier& m_id) const + -> bool { auto m = search_module_register_table(m_id); return m.has_value() && m->get()->activate; } + auto IsIntegratedModule(ModuleIdentifier m_id) -> bool { + auto m = search_module_register_table(m_id); + return m.has_value() && m->get()->integrated; + } + + auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier> { + QList<ModuleIdentifier> module_ids; + for (const auto& module : module_register_table_) { + module_ids.append(module.first); + } + module_ids.sort(); + return module_ids; + } + + auto GetModuleListening(const ModuleIdentifier& module_id) + -> QList<EventIdentifier> { + auto module_info = search_module_register_table(module_id); + if (!module_info.has_value()) return {}; + return module_info->get()->listening_event_ids; + } + private: struct ModuleRegisterInfo { int channel; ModulePtr module; bool activate; + bool integrated; + QList<QString> listening_event_ids; }; using ModuleRegisterInfoPtr = std::shared_ptr<ModuleRegisterInfo>; @@ -290,6 +359,8 @@ class GlobalModuleContext::Impl { module_register_table_; std::map<EventIdentifier, std::unordered_set<ModuleIdentifier>> module_events_table_; + std::map<EventTriggerIdentifier, EventReference> + module_on_triggering_events_table_; std::set<int> acquired_channel_; TaskRunnerPtr default_task_runner_; @@ -307,7 +378,8 @@ class GlobalModuleContext::Impl { } // Function to search for a module in the register table. - auto search_module_register_table(const ModuleIdentifier& identifier) const + [[nodiscard]] auto search_module_register_table( + const ModuleIdentifier& identifier) const -> std::optional<ModuleRegisterInfoPtr> { auto mrt_it = module_register_table_.find(identifier); if (mrt_it == module_register_table_.end()) { @@ -323,6 +395,11 @@ GlobalModuleContext::GlobalModuleContext() GlobalModuleContext::~GlobalModuleContext() = default; +auto GlobalModuleContext::SearchModule(ModuleIdentifier module_id) + -> ModulePtr { + return p_->SearchModule(std::move(module_id)); +} + // Function to get the task runner associated with a module. auto GlobalModuleContext::GetTaskRunner(ModuleRawPtr module) -> std::optional<TaskRunnerPtr> { @@ -341,8 +418,9 @@ auto GlobalModuleContext::GetGlobalTaskRunner() return p_->GetGlobalTaskRunner(); } -auto GlobalModuleContext::RegisterModule(ModulePtr module) -> bool { - return p_->RegisterModule(std::move(module)); +auto GlobalModuleContext::RegisterModule(ModulePtr module, + bool integrated_module) -> bool { + return p_->RegisterModule(module, integrated_module); } auto GlobalModuleContext::ActiveModule(ModuleIdentifier module_id) -> bool { @@ -358,8 +436,13 @@ auto GlobalModuleContext::DeactivateModule(ModuleIdentifier module_id) -> bool { return p_->DeactivateModule(std::move(module_id)); } -auto GlobalModuleContext::TriggerEvent(EventRefrernce event) -> bool { - return p_->TriggerEvent(std::move(event)); +auto GlobalModuleContext::TriggerEvent(EventReference event) -> bool { + return p_->TriggerEvent(event); +} + +auto GlobalModuleContext::SearchEvent(EventTriggerIdentifier trigger_id) + -> std::optional<EventReference> { + return p_->SearchEvent(trigger_id); } auto GlobalModuleContext::GetChannel(ModuleRawPtr module) -> int { @@ -371,7 +454,20 @@ auto GlobalModuleContext::GetDefaultChannel(ModuleRawPtr channel) -> int { } auto GlobalModuleContext::IsModuleActivated(ModuleIdentifier m_id) -> bool { - return p_->IsModuleActivated(std::move(m_id)); + return p_->IsModuleActivated(m_id); } +auto GlobalModuleContext::IsIntegratedModule(ModuleIdentifier m_id) -> bool { + return p_->IsIntegratedModule(m_id); +} + +auto GlobalModuleContext::ListAllRegisteredModuleID() + -> QList<ModuleIdentifier> { + return p_->ListAllRegisteredModuleID(); +} + +auto GlobalModuleContext::GetModuleListening(ModuleIdentifier module_id) + -> QList<EventIdentifier> { + return p_->GetModuleListening(module_id); +} } // namespace GpgFrontend::Module diff --git a/src/core/module/GlobalModuleContext.h b/src/core/module/GlobalModuleContext.h index 1c971bb5..8942b04d 100644 --- a/src/core/module/GlobalModuleContext.h +++ b/src/core/module/GlobalModuleContext.h @@ -58,6 +58,8 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject { ~GlobalModuleContext() override; + auto SearchModule(ModuleIdentifier) -> ModulePtr; + auto GetChannel(ModuleRawPtr) -> int; static auto GetDefaultChannel(ModuleRawPtr) -> int; @@ -68,7 +70,7 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject { auto GetGlobalTaskRunner() -> std::optional<TaskRunnerPtr>; - auto RegisterModule(ModulePtr) -> bool; + auto RegisterModule(ModulePtr, bool) -> bool; auto ActiveModule(ModuleIdentifier) -> bool; @@ -76,10 +78,18 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject { auto ListenEvent(ModuleIdentifier, EventIdentifier) -> bool; - auto TriggerEvent(EventRefrernce) -> bool; + auto TriggerEvent(EventReference) -> bool; + + auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventReference>; + + auto GetModuleListening(ModuleIdentifier) -> QList<EventIdentifier>; auto IsModuleActivated(ModuleIdentifier) -> bool; + auto IsIntegratedModule(ModuleIdentifier) -> bool; + + auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier>; + private: class Impl; SecureUniquePtr<Impl> p_; diff --git a/src/core/module/GlobalRegisterTable.cpp b/src/core/module/GlobalRegisterTable.cpp index c16eba37..bac51d85 100644 --- a/src/core/module/GlobalRegisterTable.cpp +++ b/src/core/module/GlobalRegisterTable.cpp @@ -31,10 +31,10 @@ #include <any> #include <optional> #include <shared_mutex> -#include <sstream> -#include <unordered_map> +#include <utility> #include <vector> +#include "GlobalRegisterTableTreeModel.h" #include "function/SecureMemoryAllocator.h" #include "utils/MemoryUtils.h" @@ -43,33 +43,45 @@ namespace GpgFrontend::Module { class GlobalRegisterTable::Impl { public: struct RTNode { - std::optional<std::any> value = std::nullopt; - std::unordered_map<QString, SecureUniquePtr<RTNode>> children; + QString name; + QString type = tr("NODE"); int version = 0; - const std::type_info* type = nullptr; + const std::type_info* value_type = nullptr; + std::optional<std::any> value = std::nullopt; + QMap<QString, QSharedPointer<RTNode>> children; + QWeakPointer<RTNode> parent; + + explicit RTNode(QString name, const QSharedPointer<RTNode>& parent) + : name(std::move(name)), parent(parent) {} }; - explicit Impl(GlobalRegisterTable* parent) : parent_(parent) {} + using RTNodePtr = QSharedPointer<RTNode>; + + explicit Impl(GlobalRegisterTable* parent) + : parent_(parent), + root_node_(SecureCreateQSharedObject<RTNode>("", nullptr)) {} auto PublishKV(const Namespace& n, const Key& k, std::any v) -> bool { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); int version = 0; { std::unique_lock lock(lock_); - auto& root_rt_node = - global_register_table_.emplace(n, SecureCreateUniqueObject<RTNode>()) - .first->second; - RTNode* current = root_rt_node.get(); + auto current = root_node_; for (const QString& segment : segments) { - current = current->children - .emplace(segment, SecureCreateUniqueObject<RTNode>()) - .first->second.get(); + auto it = current->children.find(segment); + if (it == current->children.end()) { + it = current->children.insert( + segment, SecureCreateQSharedObject<RTNode>(segment, current)); + } + current = it.value(); } + current->name = segments.back(); + current->type = tr("LEAF"); current->value = v; - current->type = &v.type(); + current->value_type = &v.type(); version = ++current->version; } @@ -78,19 +90,17 @@ class GlobalRegisterTable::Impl { } auto LookupKV(const Namespace& n, const Key& k) -> std::optional<std::any> { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); std::optional<std::any> rtn = std::nullopt; { std::shared_lock const lock(lock_); - auto it = global_register_table_.find(n); - if (it == global_register_table_.end()) return std::nullopt; - RTNode* current = it->second.get(); + auto current = root_node_; for (const QString& segment : segments) { auto it = current->children.find(segment); if (it == current->children.end()) return std::nullopt; - current = it->second.get(); + current = it.value(); } rtn = current->value; } @@ -98,24 +108,20 @@ class GlobalRegisterTable::Impl { } auto ListChildKeys(const Namespace& n, const Key& k) -> std::vector<Key> { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); std::vector<Key> rtn; { std::shared_lock lock(lock_); - auto it = global_register_table_.find(n); - if (it == global_register_table_.end()) return {}; - RTNode* current = it->second.get(); + auto current = root_node_; for (const QString& segment : segments) { auto it = current->children.find(segment); if (it == current->children.end()) return {}; - current = it->second.get(); + current = it.value(); } - for (auto& it : current->children) { - rtn.emplace_back(it.first); - } + for (auto& key : current->children.keys()) rtn.emplace_back(key); } return rtn; } @@ -132,12 +138,149 @@ class GlobalRegisterTable::Impl { }) == nullptr; } + auto RootRTNode() -> RTNode* { return root_node_.get(); } + private: - using Table = std::map<Namespace, SecureUniquePtr<RTNode>>; std::shared_mutex lock_; GlobalRegisterTable* parent_; - Table global_register_table_; + RTNodePtr root_node_; +}; + +class GlobalRegisterTableTreeModel::Impl { + public: + using RTNode = GlobalRegisterTable::Impl::RTNode; + + Impl(GlobalRegisterTableTreeModel* parent, GlobalRegisterTable::Impl* grt) + : parent_(parent), root_node_(grt->RootRTNode()) {} + + [[nodiscard]] auto RowCount(const QModelIndex& parent) const -> int { + auto* parent_node = !parent.isValid() + ? root_node_.get() + : static_cast<RTNode*>(parent.internalPointer()); + return parent_node->children.size(); + } + + [[nodiscard]] auto ColumnCount(const QModelIndex& parent) const -> int { + return 4; + } + + [[nodiscard]] auto Data(const QModelIndex& index, int role) const + -> QVariant { + if (!index.isValid()) return {}; + + if (role == Qt::DisplayRole) { + auto* node = static_cast<RTNode*>(index.internalPointer()); + switch (index.column()) { + case 0: + return node->name; + case 1: + return node->type; + case 2: + return QString(node->value && node->value.has_value() + ? node->value->type().name() + : ""); + case 3: + return Any2QVariant(node->value); + default: + return {}; + } + } + return {}; + } + + static auto Any2QVariant(std::optional<std::any> op) -> QVariant { + if (!op) return tr("<EMPTY>"); + + auto& o = op.value(); + if (o.type() == typeid(QString)) { + return QVariant::fromValue(std::any_cast<QString>(o)); + } + if (o.type() == typeid(std::string)) { + return QVariant::fromValue( + QString::fromStdString(std::any_cast<std::string>(o))); + } + if (o.type() == typeid(int)) { + return QVariant::fromValue(std::any_cast<int>(o)); + } + if (o.type() == typeid(long)) { + return QVariant::fromValue( + static_cast<qlonglong>(std::any_cast<long>(o))); + } + if (o.type() == typeid(long long)) { + return QVariant::fromValue(std::any_cast<long long>(o)); + } + if (o.type() == typeid(unsigned)) { + return QVariant::fromValue(std::any_cast<unsigned>(o)); + } + if (o.type() == typeid(unsigned long)) { + return QVariant::fromValue( + static_cast<qulonglong>(std::any_cast<unsigned long>(o))); + } + if (o.type() == typeid(unsigned long long)) { + return QVariant::fromValue(std::any_cast<unsigned long long>(o)); + } + if (o.type() == typeid(float)) { + return QVariant::fromValue(std::any_cast<float>(o)); + } + if (o.type() == typeid(double)) { + return QVariant::fromValue(std::any_cast<double>(o)); + } + if (o.type() == typeid(bool)) { + return QVariant::fromValue(std::any_cast<bool>(o)); + } + return tr("<UNSUPPORTED>"); + } + + [[nodiscard]] auto Index(int row, int column, const QModelIndex& parent) const + -> QModelIndex { + if (!parent_->hasIndex(row, column, parent)) return {}; + + auto* parent_node = !parent.isValid() + ? root_node_.get() + : static_cast<RTNode*>(parent.internalPointer()); + auto key = parent_node->children.keys().at(row); + auto child_node = parent_node->children.value(key); + return parent_->createIndex(row, column, child_node.get()); + } + + [[nodiscard]] auto Parent(const QModelIndex& index) const -> QModelIndex { + if (!index.isValid()) return {}; + + auto* child_node = static_cast<RTNode*>(index.internalPointer()); + auto parent_node = child_node->parent.lock(); + + if (!parent_node || parent_node == root_node_) return {}; + + int const row = static_cast<int>( + parent_node->parent.lock()->children.keys().indexOf(parent_node->name)); + return parent_->createIndex(row, 0, parent_node.data()); + } + + [[nodiscard]] static auto HeaderData(int section, Qt::Orientation orientation, + int role) -> QVariant { + if (role != Qt::DisplayRole) return {}; + + if (orientation == Qt::Horizontal) { + switch (section) { + case 0: + return tr("Key"); + case 1: + return tr("Type"); + case 2: + return tr("Value Type"); + case 3: + return tr("Value"); + default: + return {}; + } + } + return {}; + } + + private: + GlobalRegisterTableTreeModel* parent_; + GlobalRegisterTable::Impl::RTNodePtr root_node_; }; GlobalRegisterTable::GlobalRegisterTable() @@ -164,4 +307,39 @@ auto GlobalRegisterTable::ListChildKeys(Namespace n, Key k) return p_->ListChildKeys(n, k); } +GlobalRegisterTableTreeModel::GlobalRegisterTableTreeModel( + GlobalRegisterTable* grt) + : p_(SecureCreateUniqueObject<Impl>(this, grt->p_.get())) {} + +auto GlobalRegisterTableTreeModel::rowCount(const QModelIndex& parent) const + -> int { + return p_->RowCount(parent); +} + +auto GlobalRegisterTableTreeModel::columnCount(const QModelIndex& parent) const + -> int { + return p_->ColumnCount(parent); +} + +auto GlobalRegisterTableTreeModel::data(const QModelIndex& index, + int role) const -> QVariant { + return p_->Data(index, role); +} + +auto GlobalRegisterTableTreeModel::index(int row, int column, + const QModelIndex& parent) const + -> QModelIndex { + return p_->Index(row, column, parent); +} + +auto GlobalRegisterTableTreeModel::parent(const QModelIndex& index) const + -> QModelIndex { + return p_->Parent(index); +} + +auto GlobalRegisterTableTreeModel::headerData(int section, + Qt::Orientation orientation, + int role) const -> QVariant { + return p_->HeaderData(section, orientation, role); +} } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/GlobalRegisterTable.h b/src/core/module/GlobalRegisterTable.h index db68c888..1d3e43da 100644 --- a/src/core/module/GlobalRegisterTable.h +++ b/src/core/module/GlobalRegisterTable.h @@ -32,7 +32,7 @@ #include <functional> #include <optional> -#include "function/SecureMemoryAllocator.h" +#include "core/function/SecureMemoryAllocator.h" namespace GpgFrontend::Module { @@ -43,6 +43,8 @@ using LPCallback = std::function<void(Namespace, Key, int, std::any)>; class GlobalRegisterTable : public QObject { Q_OBJECT public: + friend class GlobalRegisterTableTreeModel; + GlobalRegisterTable(); ~GlobalRegisterTable() override; diff --git a/src/core/module/GlobalRegisterTableTreeModel.h b/src/core/module/GlobalRegisterTableTreeModel.h new file mode 100644 index 00000000..fe4242a2 --- /dev/null +++ b/src/core/module/GlobalRegisterTableTreeModel.h @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/module/GlobalRegisterTable.h" + +namespace GpgFrontend::Module { +class GPGFRONTEND_CORE_EXPORT GlobalRegisterTableTreeModel + : public QAbstractItemModel { + public: + explicit GlobalRegisterTableTreeModel(GlobalRegisterTable *grt); + + [[nodiscard]] auto rowCount(const QModelIndex &parent) const -> int override; + + [[nodiscard]] auto columnCount(const QModelIndex &parent) const + -> int override; + + [[nodiscard]] auto data(const QModelIndex &index, int role) const + -> QVariant override; + + [[nodiscard]] auto index(int row, int column, const QModelIndex &parent) const + -> QModelIndex override; + + [[nodiscard]] auto parent(const QModelIndex &index) const + -> QModelIndex override; + + [[nodiscard]] auto headerData(int section, Qt::Orientation orientation, + int role) const -> QVariant override; + + private: + class Impl; + SecureUniquePtr<Impl> p_; +}; + +}; // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index 9076dc2c..9c875fce 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -29,6 +29,10 @@ #include "Module.h" #include "core/module/GlobalModuleContext.h" +#include "core/utils/CommonUtils.h" +#include "core/utils/IOUtils.h" +#include "module/sdk/GFSDKModule.h" +#include "utils/BuildInfoUtils.h" namespace GpgFrontend::Module { @@ -43,7 +47,127 @@ class Module::Impl { : m_ptr_(m_ptr), identifier_(std::move(id)), version_(std::move(version)), - meta_data_(std::move(meta_data)) {} + meta_data_(std::move(meta_data)), + good_(true) {} + + Impl(ModuleRawPtr m_ptr, QLibrary& module_library) + : m_ptr_(m_ptr), + module_hash_(CalculateBinaryChacksum(module_library.fileName())), + module_library_path_(module_library.fileName()), + good_(false) { + for (auto& required_symbol : module_required_symbols_) { + *required_symbol.pointer = + reinterpret_cast<void*>(module_library.resolve(required_symbol.name)); + if (*required_symbol.pointer == nullptr) { + GF_CORE_LOG_WARN( + "illegal module: {}, reason: cannot load symbol: {}, abort...", + module_library.fileName(), required_symbol.name); + return; + } + } + + identifier_ = GFUnStrDup(get_id_api_()); + version_ = GFUnStrDup(get_version_api_()); + gf_sdk_ver_ = GFUnStrDup(get_sdk_ver_api_()); + qt_env_ver_ = GFUnStrDup(get_qt_ver_api_()); + + if (!module_identifier_regex_exp_.match(identifier_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid module id, abort...", + identifier_); + return; + } + + if (!module_version_regex_exp_.match(version_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid version: {}, abort...", + identifier_, version_); + return; + } + + if (!module_version_regex_exp_.match(gf_sdk_ver_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid sdk version: {}, abort...", + identifier_, gf_sdk_ver_); + return; + } + + if (GFCompareSoftwareVersion(gf_sdk_ver_, GetProjectVersion()) > 0) { + GF_CORE_LOG_WARN( + "uncompatible module: {}, sdk version: {} greater than " + "current sdk version: {}, abort...", + identifier_, gf_sdk_ver_, GetProjectVersion()); + return; + } + + auto qt_env_ver_regex_match = module_version_regex_exp_.match(qt_env_ver_); + if (!qt_env_ver_regex_match.hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid qt env version: {}, abort...", + identifier_, qt_env_ver_); + return; + } + + auto qt_env_ver_major = qt_env_ver_regex_match.captured(1); + auto qt_env_ver_minor = qt_env_ver_regex_match.captured(2); + + if (qt_env_ver_major != QString::number(QT_VERSION_MAJOR) + "." || + qt_env_ver_minor != QString::number(QT_VERSION_MINOR) + ".") { + GF_CORE_LOG_WARN( + "uncompatible module: {}, qt version: {} is not binary uncompatible " + "with application's qt env version: {}, abort...", + identifier_, qt_env_ver_, QString::fromUtf8(QT_VERSION_STR)); + return; + } + + GF_CORE_LOG_INFO( + "module loaded, id: {}, version: {}, " + "sdk version: {}, qt env version: {}, hash: {}, path: {}", + identifier_, version_, gf_sdk_ver_, qt_env_ver_, module_hash_, + module_library_path_); + + ::GFModuleMetaData* p_meta_data = get_metadata_api_(); + + while (p_meta_data != nullptr) { + ::GFModuleMetaData* l_meta_data; + meta_data_[QString::fromUtf8(p_meta_data->key)] = + QString::fromUtf8(p_meta_data->value); + l_meta_data = p_meta_data; + p_meta_data = p_meta_data->next; + SecureFree(l_meta_data); + } + + good_ = true; + } + + [[nodiscard]] auto IsGood() const -> bool { return good_; } + + auto Register() -> int { + if (good_ && register_api_ != nullptr) return register_api_(); + return -1; + } + + auto Active() -> int { + if (good_ && activate_api_ != nullptr) return activate_api_(); + return -1; + } + + auto Exec(const EventReference& event) -> int { + if (good_ && execute_api_ != nullptr) { + return execute_api_(event->ToModuleEvent()); + } + return -1; + } + + auto Deactive() -> int { + if (good_ && deactivate_api_ != nullptr) return deactivate_api_(); + return -1; + } + + auto UnRegister() -> int { + if (good_ && unregister_api_ != nullptr) return unregister_api_(); + return -1; + } auto GetChannel() -> int { return get_gpc()->GetChannel(m_ptr_); } @@ -63,14 +187,77 @@ class Module::Impl { return identifier_; } + [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion { + return version_; + } + + [[nodiscard]] auto GetModuleSDKVersion() const -> QString { + return gf_sdk_ver_; + } + + [[nodiscard]] auto GetModuleQtEnvVersion() const -> QString { + return qt_env_ver_; + } + + [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData { + return meta_data_; + } + + [[nodiscard]] auto GetModulePath() const -> QString { + return module_library_path_; + } + + [[nodiscard]] auto GetModuleHash() const -> QString { return module_hash_; } + void SetGPC(GlobalModuleContext* gpc) { gpc_ = gpc; } private: GlobalModuleContext* gpc_{}; Module* m_ptr_; - const ModuleIdentifier identifier_; - const ModuleVersion version_; - const ModuleMetaData meta_data_; + ModuleIdentifier identifier_; + ModuleVersion version_; + ModuleMetaData meta_data_; + QString module_hash_; + QString module_library_path_; + QString gf_sdk_ver_; + QString qt_env_ver_; + + QRegularExpression module_identifier_regex_exp_ = QRegularExpression( + R"(^([A-Za-z]{1}[A-Za-z\d_]*\.)+[A-Za-z][A-Za-z\d_]*$)"); + QRegularExpression module_version_regex_exp_ = + QRegularExpression(R"(^(\d+\.)?(\d+\.)?(\*|\d+)$)"); + + bool good_; + + GFModuleAPIGetModuleGFSDKVersion get_sdk_ver_api_; + GFModuleAPIGetModuleQtEnvVersion get_qt_ver_api_; + + GFModuleAPIGetModuleID get_id_api_; + GFModuleAPIGetModuleVersion get_version_api_; + GFModuleAPIGetModuleMetaData get_metadata_api_; + GFModuleAPIRegisterModule register_api_; + GFModuleAPIActivateModule activate_api_; + GFModuleAPIExecuteModule execute_api_; + GFModuleAPIDeactivateModule deactivate_api_; + GFModuleAPIUnregisterModule unregister_api_; + + struct Symbol { + const char* name; + void** pointer; + }; + + QList<Symbol> module_required_symbols_ = { + {"GFGetModuleGFSDKVersion", reinterpret_cast<void**>(&get_sdk_ver_api_)}, + {"GFGetModuleQtEnvVersion", reinterpret_cast<void**>(&get_qt_ver_api_)}, + {"GFGetModuleID", reinterpret_cast<void**>(&get_id_api_)}, + {"GFGetModuleVersion", reinterpret_cast<void**>(&get_version_api_)}, + {"GFGetModuleMetaData", reinterpret_cast<void**>(&get_metadata_api_)}, + {"GFRegisterModule", reinterpret_cast<void**>(®ister_api_)}, + {"GFActiveModule", reinterpret_cast<void**>(&activate_api_)}, + {"GFExecuteModule", reinterpret_cast<void**>(&execute_api_)}, + {"GFDeactiveModule", reinterpret_cast<void**>(&deactivate_api_)}, + {"GFUnregisterModule", reinterpret_cast<void**>(&unregister_api_)}, + }; auto get_gpc() -> GlobalModuleContext* { if (gpc_ == nullptr) { @@ -84,8 +271,25 @@ Module::Module(ModuleIdentifier id, ModuleVersion version, const ModuleMetaData& meta_data) : p_(SecureCreateUniqueObject<Impl>(this, id, version, meta_data)) {} +Module::Module(QLibrary& module_library) + : p_(SecureCreateUniqueObject<Impl>(this, module_library)) {} + Module::~Module() = default; +auto Module::IsGood() -> bool { return p_->IsGood(); } + +auto Module::Register() -> int { return p_->Register(); } + +auto Module::Active() -> int { return p_->Active(); } + +auto Module::Exec(EventReference event) -> int { + return p_->Exec(std::move(event)); +} + +auto Module::Deactive() -> int { return p_->Deactive(); } + +auto Module::UnRegister() -> int { return p_->UnRegister(); } + auto Module::getChannel() -> int { return p_->GetChannel(); } auto Module::getDefaultChannel() -> int { return p_->GetDefaultChannel(); } @@ -102,5 +306,29 @@ auto Module::GetModuleIdentifier() const -> ModuleIdentifier { return p_->GetModuleIdentifier(); } +[[nodiscard]] auto Module::GetModuleVersion() const -> ModuleVersion { + return p_->GetModuleVersion(); +} + +[[nodiscard]] auto Module::GetModuleMetaData() const -> ModuleMetaData { + return p_->GetModuleMetaData(); +} + +[[nodiscard]] auto Module::GetModulePath() const -> QString { + return p_->GetModulePath(); +} + +[[nodiscard]] auto Module::GetModuleHash() const -> QString { + return p_->GetModuleHash(); +} + +[[nodiscard]] auto Module::GetModuleSDKVersion() const -> QString { + return p_->GetModuleSDKVersion(); +} + +[[nodiscard]] auto Module::GetModuleQtEnvVersion() const -> QString { + return p_->GetModuleQtEnvVersion(); +} + void Module::SetGPC(GlobalModuleContext* gpc) { p_->SetGPC(gpc); } } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/Module.h b/src/core/module/Module.h index 2a5b54e7..c332d455 100644 --- a/src/core/module/Module.h +++ b/src/core/module/Module.h @@ -39,7 +39,7 @@ class ModuleManager; using ModuleIdentifier = QString; using ModuleVersion = QString; -using ModuleMetaData = std::map<QString, QString>; +using ModuleMetaData = QMap<QString, QString>; using ModulePtr = std::shared_ptr<Module>; using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>; @@ -47,21 +47,39 @@ using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>; class GPGFRONTEND_CORE_EXPORT Module : public QObject { Q_OBJECT public: - Module(ModuleIdentifier, ModuleVersion, const ModuleMetaData&); + Module(ModuleIdentifier, ModuleVersion, const ModuleMetaData &); + + explicit Module(QLibrary &module_library); ~Module(); - virtual auto Register() -> bool = 0; + auto IsGood() -> bool; + + virtual auto Register() -> int; + + virtual auto Active() -> int; - virtual auto Active() -> bool = 0; + virtual auto Exec(EventReference) -> int; - virtual auto Exec(EventRefrernce) -> int = 0; + virtual auto Deactive() -> int; - virtual auto Deactive() -> bool = 0; + virtual auto UnRegister() -> int; [[nodiscard]] auto GetModuleIdentifier() const -> ModuleIdentifier; - void SetGPC(GlobalModuleContext*); + [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion; + + [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData; + + [[nodiscard]] auto GetModulePath() const -> QString; + + [[nodiscard]] auto GetModuleHash() const -> QString; + + [[nodiscard]] auto GetModuleSDKVersion() const -> QString; + + [[nodiscard]] auto GetModuleQtEnvVersion() const -> QString; + + void SetGPC(GlobalModuleContext *); protected: auto getChannel() -> int; diff --git a/src/core/module/ModuleInit.cpp b/src/core/module/ModuleInit.cpp new file mode 100644 index 00000000..ceb5987e --- /dev/null +++ b/src/core/module/ModuleInit.cpp @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "ModuleInit.h" + +#include <QCoreApplication> +#include <QDir> + +#include "core/function/GlobalSettingStation.h" +#include "core/module/ModuleManager.h" +#include "core/thread/Task.h" +#include "core/thread/TaskRunnerGetter.h" + +namespace GpgFrontend::Module { + +void LoadModuleFromPath(const QString& mods_path, bool integrated) { + for (const auto& module_library_name : + QDir(mods_path).entryList(QStringList() << "*.so" + << "*.dll" + << "*.dylib", + QDir::Files)) { + ModuleManager::GetInstance().LoadModule( + mods_path + "/" + module_library_name, integrated); + } +} + +auto LoadIntegratedMods() -> bool { + auto exec_binary_path = QCoreApplication::applicationDirPath(); + +#if defined(MACOS) && defined(RELEASE) + // App Bundle + auto mods_path = exec_binary_path + "/../PlugIns/mods"; +#else + // Debug Or Windows Platform + auto mods_path = exec_binary_path + "/mods"; +#endif + + // AppImage + if (!qEnvironmentVariable("APPIMAGE").isEmpty()) { + mods_path = qEnvironmentVariable("APPDIR") + "/usr/plugins/mods"; + } + + // Flatpak + if (!qEnvironmentVariable("container").isEmpty()) { + mods_path = "/app/lib/mods"; + } + + GF_CORE_LOG_DEBUG("try loading integrated modules at path: {} ...", + mods_path); + if (!QDir(mods_path).exists()) { + GF_CORE_LOG_WARN( + "integrated module directory at path {} not found, abort...", + mods_path); + return false; + } + + LoadModuleFromPath(mods_path, true); + + GF_CORE_LOG_DEBUG("load integrated modules done."); + return true; +} + +auto LoadExternalMods() -> bool { + auto mods_path = + GpgFrontend::GlobalSettingStation::GetInstance().GetModulesDir(); + + GF_CORE_LOG_DEBUG("try loading external modules at path: {} ...", mods_path); + if (!QDir(mods_path).exists()) { + GF_CORE_LOG_WARN("external module directory at path {} not found, abort...", + mods_path); + return false; + } + + LoadModuleFromPath(mods_path, false); + + GF_CORE_LOG_DEBUG("load integrated modules done."); + return true; +} + +void LoadGpgFrontendModules(ModuleInitArgs) { + // must init at default thread before core + Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( + new Thread::Task( + [](const DataObjectPtr&) -> int { + return LoadIntegratedMods() && LoadExternalMods() ? 0 : -1; + }, + "modules_system_init_task")); +} + +void ShutdownGpgFrontendModules() {} + +} // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/module/GpgFrontendModuleInit.h b/src/core/module/ModuleInit.h index a3a8bbd3..e7e86f0f 100644 --- a/src/module/GpgFrontendModuleInit.h +++ b/src/core/module/ModuleInit.h @@ -28,7 +28,9 @@ #pragma once -#include "module/GpgFrontendModule.h" +#include <spdlog/spdlog.h> + +#include "core/GpgFrontendCoreExport.h" namespace GpgFrontend::Module { @@ -40,12 +42,12 @@ struct ModuleInitArgs { * @brief init the module library * */ -void GPGFRONTEND_MODULE_EXPORT LoadGpgFrontendModules(ModuleInitArgs args); +void GPGFRONTEND_CORE_EXPORT LoadGpgFrontendModules(ModuleInitArgs args); /** * @brief shutdown the module library * */ -void GPGFRONTEND_MODULE_EXPORT ShutdownGpgFrontendModules(); +void GPGFRONTEND_CORE_EXPORT ShutdownGpgFrontendModules(); }; // namespace GpgFrontend::Module diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp index 83e7c1ff..d07ca989 100644 --- a/src/core/module/ModuleManager.cpp +++ b/src/core/module/ModuleManager.cpp @@ -29,16 +29,18 @@ #include "ModuleManager.h" #include <memory> +#include <utility> -#include "GpgConstants.h" +#include "core/function/SecureMemoryAllocator.h" +#include "core/function/basic/GpgFunctionObject.h" +#include "core/model/SettingsObject.h" #include "core/module/GlobalModuleContext.h" #include "core/module/GlobalRegisterTable.h" #include "core/module/Module.h" +#include "core/struct/settings_object/ModuleSO.h" #include "core/thread/Task.h" -#include "function/SecureMemoryAllocator.h" -#include "function/basic/GpgFunctionObject.h" -#include "thread/TaskRunnerGetter.h" -#include "utils/MemoryUtils.h" +#include "core/thread/TaskRunnerGetter.h" +#include "core/utils/MemoryUtils.h" namespace GpgFrontend::Module { @@ -50,19 +52,95 @@ class ModuleManager::Impl { ~Impl() = default; + auto LoadAndRegisterModule(const QString& module_library_path, + bool integrated_module) -> void { + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) + ->PostTask(new Thread::Task( + [=](GpgFrontend::DataObjectPtr) -> int { + QLibrary module_library(module_library_path); + if (!module_library.load()) { + GF_CORE_LOG_WARN( + "module manager failed to load module, " + "reason: broken library: {} ", + module_library.fileName()); + return -1; + } + + auto module = SecureCreateSharedObject<Module>(module_library); + if (!module->IsGood()) { + GF_CORE_LOG_WARN( + "module manager failed to load module, " + "reason: illegal module: {}", + module_library.fileName()); + return -1; + } + + module->SetGPC(gmc_.get()); + if (!gmc_->RegisterModule(module, integrated_module)) return -1; + + const auto module_id = module->GetModuleIdentifier(); + const auto module_hash = module->GetModuleHash(); + + SettingsObject so(QString("module.%1.so").arg(module_id)); + ModuleSO module_so(so); + + // reset module settings if necessary + if (module_so.module_id != module_id || + module_so.module_hash != module_hash) { + module_so.module_id = module_id; + module_so.module_hash = module_hash; + // auto active integrated module by default + module_so.auto_activate = integrated_module; + module_so.set_by_user = false; + + so.Store(module_so.ToJson()); + } + + // if this module need auto active + if (module_so.auto_activate) { + if (!gmc_->ActiveModule(module_id)) { + return -1; + } + } + + return 0; + }, + __func__, nullptr)); + } + + auto SearchModule(ModuleIdentifier module_id) -> ModulePtr { + return gmc_->SearchModule(std::move(module_id)); + } + + auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier> { + return gmc_->ListAllRegisteredModuleID(); + } + void RegisterModule(const ModulePtr& module) { Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) ->PostTask(new Thread::Task( [=](GpgFrontend::DataObjectPtr) -> int { module->SetGPC(gmc_.get()); - gmc_->RegisterModule(module); + return gmc_->RegisterModule(module, false) ? 0 : -1; + }, + __func__, nullptr)); + } + + void ListenEvent(const ModuleIdentifier& module_id, + const EventIdentifier& event_id) { + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) + ->PostTask(new Thread::Task( + [=](const GpgFrontend::DataObjectPtr&) -> int { + gmc_->ListenEvent(module_id, event_id); return 0; }, __func__, nullptr)); } - void TriggerEvent(const EventRefrernce& event) { + void TriggerEvent(const EventReference& event) { Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) ->PostTask(new Thread::Task( @@ -73,6 +151,16 @@ class ModuleManager::Impl { __func__, nullptr)); } + auto SearchEvent(EventTriggerIdentifier trigger_id) + -> std::optional<EventReference> { + return gmc_->SearchEvent(std::move(trigger_id)); + } + + auto GetModuleListening(ModuleIdentifier module_id) + -> QList<EventIdentifier> { + return gmc_->GetModuleListening(std::move(module_id)); + } + void ActiveModule(const ModuleIdentifier& identifier) { Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) @@ -84,6 +172,17 @@ class ModuleManager::Impl { __func__, nullptr)); } + void DeactiveModule(const ModuleIdentifier& identifier) { + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) + ->PostTask(new Thread::Task( + [=](const GpgFrontend::DataObjectPtr&) -> int { + gmc_->DeactivateModule(identifier); + return 0; + }, + __func__, nullptr)); + } + auto GetTaskRunner(ModuleIdentifier module_id) -> std::optional<TaskRunnerPtr> { return gmc_->GetTaskRunner(std::move(module_id)); @@ -109,13 +208,20 @@ class ModuleManager::Impl { return gmc_->IsModuleActivated(id); } + auto IsIntegratedModule(ModuleIdentifier id) -> bool { + return gmc_->IsIntegratedModule(id); + } + + auto GRT() -> GlobalRegisterTable* { return grt_.get(); } + private: static ModuleMangerPtr global_module_manager; SecureUniquePtr<GlobalModuleContext> gmc_; SecureUniquePtr<GlobalRegisterTable> grt_; + QList<QLibrary> module_libraries_; }; -auto IsModuleAcivate(ModuleIdentifier id) -> bool { +auto IsModuleActivate(ModuleIdentifier id) -> bool { return ModuleManager::GetInstance().IsModuleActivated(id); } @@ -141,18 +247,46 @@ ModuleManager::ModuleManager(int channel) ModuleManager::~ModuleManager() = default; +void ModuleManager::LoadModule(QString module_library_path, + bool integrated_module) { + return p_->LoadAndRegisterModule(module_library_path, integrated_module); +} + +auto ModuleManager::SearchModule(ModuleIdentifier module_id) -> ModulePtr { + return p_->SearchModule(std::move(module_id)); +} + void ModuleManager::RegisterModule(ModulePtr module) { return p_->RegisterModule(module); } -void ModuleManager::TriggerEvent(EventRefrernce event) { +void ModuleManager::ListenEvent(ModuleIdentifier module, + EventIdentifier event) { + return p_->ListenEvent(module, event); +} + +auto ModuleManager::GetModuleListening(ModuleIdentifier module_id) + -> QList<EventIdentifier> { + return p_->GetModuleListening(module_id); +} + +void ModuleManager::TriggerEvent(EventReference event) { return p_->TriggerEvent(event); } +auto ModuleManager::SearchEvent(EventTriggerIdentifier trigger_id) + -> std::optional<EventReference> { + return p_->SearchEvent(std::move(trigger_id)); +} + void ModuleManager::ActiveModule(ModuleIdentifier id) { return p_->ActiveModule(id); } +void ModuleManager::DeactiveModule(ModuleIdentifier id) { + return p_->DeactiveModule(id); +} + auto ModuleManager::GetTaskRunner(ModuleIdentifier id) -> std::optional<TaskRunnerPtr> { return p_->GetTaskRunner(std::move(id)); @@ -181,4 +315,14 @@ auto ModuleManager::IsModuleActivated(ModuleIdentifier id) -> bool { return p_->IsModuleActivated(id); } +auto ModuleManager::IsIntegratedModule(ModuleIdentifier id) -> bool { + return p_->IsIntegratedModule(id); +} + +auto ModuleManager::ListAllRegisteredModuleID() -> QList<ModuleIdentifier> { + return p_->ListAllRegisteredModuleID(); +}; + +auto ModuleManager::GRT() -> GlobalRegisterTable* { return p_->GRT(); } + } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h index 93b89e95..ea2d88cb 100644 --- a/src/core/module/ModuleManager.h +++ b/src/core/module/ModuleManager.h @@ -48,8 +48,9 @@ class Event; class Module; class GlobalModuleContext; class ModuleManager; +class GlobalRegisterTable; -using EventRefrernce = std::shared_ptr<Event>; +using EventReference = std::shared_ptr<Event>; using ModuleIdentifier = QString; using ModulePtr = std::shared_ptr<Module>; using ModuleMangerPtr = std::shared_ptr<ModuleManager>; @@ -65,11 +66,25 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager virtual ~ModuleManager() override; + auto LoadModule(QString, bool) -> void; + + auto SearchModule(ModuleIdentifier) -> ModulePtr; + + auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier>; + void RegisterModule(ModulePtr); auto IsModuleActivated(ModuleIdentifier) -> bool; - void TriggerEvent(EventRefrernce); + auto IsIntegratedModule(ModuleIdentifier) -> bool; + + void ListenEvent(ModuleIdentifier, EventIdentifier); + + void TriggerEvent(EventReference); + + auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventReference>; + + auto GetModuleListening(ModuleIdentifier) -> QList<EventIdentifier>; void ActiveModule(ModuleIdentifier); @@ -85,6 +100,8 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager auto ListRTChildKeys(const QString&, const QString&) -> std::vector<Key>; + auto GRT() -> GlobalRegisterTable*; + private: class Impl; SecureUniquePtr<Impl> p_; @@ -118,7 +135,7 @@ void TriggerEvent(const EventIdentifier& event_id, Args&&... args, * @return true * @return false */ -auto GPGFRONTEND_CORE_EXPORT IsModuleAcivate(ModuleIdentifier) -> bool; +auto GPGFRONTEND_CORE_EXPORT IsModuleActivate(ModuleIdentifier) -> bool; /** * @brief diff --git a/src/core/struct/settings_object/ModuleSO.h b/src/core/struct/settings_object/ModuleSO.h new file mode 100644 index 00000000..b0139b1f --- /dev/null +++ b/src/core/struct/settings_object/ModuleSO.h @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +namespace GpgFrontend { + +struct ModuleSO { + QString module_id; + QString module_version; + QString module_hash; + bool auto_activate; + bool set_by_user; + + ModuleSO() = default; + + explicit ModuleSO(const QJsonObject& j) { + if (const auto v = j["module_id"]; v.isString()) { + module_id = v.toString(); + } + + if (const auto v = j["module_version"]; v.isString()) { + module_version = v.toString(); + } + + if (const auto v = j["module_hash"]; v.isString()) { + module_hash = v.toString(); + } + + if (const auto v = j["auto_activate"]; v.isBool()) { + auto_activate = v.toBool(); + } + + if (const auto v = j["set_by_user"]; v.isBool()) { + set_by_user = v.toBool(); + } + } + + [[nodiscard]] auto ToJson() const -> QJsonObject { + QJsonObject j; + j["module_id"] = module_id; + j["module_version"] = module_version; + j["module_hash"] = module_hash; + j["auto_activate"] = auto_activate; + j["set_by_user"] = set_by_user; + return j; + } +}; +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h index 8a93ad0b..fe1555ec 100644 --- a/src/core/thread/TaskRunner.h +++ b/src/core/thread/TaskRunner.h @@ -76,8 +76,6 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QObject { */ auto IsRunning() -> bool; - public slots: - /** * @brief * diff --git a/src/core/typedef/GpgTypedef.h b/src/core/typedef/GpgTypedef.h index cf0887bf..599c5c59 100644 --- a/src/core/typedef/GpgTypedef.h +++ b/src/core/typedef/GpgTypedef.h @@ -28,7 +28,7 @@ #pragma once -#include <tuple> +#include <gpgme.h> #include "core/model/DataObject.h" diff --git a/src/core/utils/AsyncUtils.cpp b/src/core/utils/AsyncUtils.cpp index 9ce94247..3c007fb6 100644 --- a/src/core/utils/AsyncUtils.cpp +++ b/src/core/utils/AsyncUtils.cpp @@ -45,7 +45,7 @@ auto RunGpgOperaAsync(const GpgOperaRunnable& runnable, GF_CORE_LOG_DEBUG("got gnupg version from rt: {}, operation: {}", gnupg_version, operation); - if (CompareSoftwareVersion(gnupg_version, minial_version) < 0) { + if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { GF_CORE_LOG_ERROR("operaton {} not support for gnupg version: {}", operation, gnupg_version); callback(GPG_ERR_NOT_SUPPORTED, TransferParams()); @@ -85,7 +85,7 @@ auto RunGpgOperaSync(const GpgOperaRunnable& runnable, const QString& operation, GF_CORE_LOG_DEBUG("got gnupg version from rt: {}, operation: {}", gnupg_version, operation); - if (CompareSoftwareVersion(gnupg_version, minial_version) < 0) { + if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { GF_CORE_LOG_ERROR("operaton {} not support for gnupg version: {}", operation, gnupg_version); return {GPG_ERR_NOT_SUPPORTED, TransferParams()}; diff --git a/src/core/utils/BuildInfoUtils.cpp b/src/core/utils/BuildInfoUtils.cpp new file mode 100644 index 00000000..a7d914ef --- /dev/null +++ b/src/core/utils/BuildInfoUtils.cpp @@ -0,0 +1,26 @@ + +#include "BuildInfoUtils.h" + +#include "GpgFrontendBuildInfo.h" + +namespace GpgFrontend { + +auto GetProjectVersion() -> QString { + return QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + "." + + VERSION_PATCH; +} + +auto GetProjectBuildVersion() -> QString { return BUILD_VERSION; } + +auto GetProjectBuildTimestamp() -> QDateTime { + return QDateTime::fromString(BUILD_TIMESTAMP, Qt::ISODate); +} + +auto GetProjectBuildGitBranchName() -> QString { return GIT_BRANCH_NAME; } + +auto GetProjectBuildGitCommitHash() -> QString { return GIT_COMMIT_HASH; } + +auto GetProjectBuildGitVersion() -> QString { return GIT_VERSION; } + +auto GetHttpRequestUserAgent() -> QString { return HTTP_REQUEST_USER_AGENT; } +}; // namespace GpgFrontend
\ No newline at end of file diff --git a/src/module/integrated/version_checking_module/VersionCheckingModule.h b/src/core/utils/BuildInfoUtils.h index 0730feed..07b0bb21 100644 --- a/src/module/integrated/version_checking_module/VersionCheckingModule.h +++ b/src/core/utils/BuildInfoUtils.h @@ -28,34 +28,57 @@ #pragma once -#include "GpgFrontendModuleExport.h" -#include "SoftwareVersion.h" -#include "core/module/Module.h" +#include "core/GpgFrontendCoreExport.h" -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { +namespace GpgFrontend { -class GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT - VersionCheckingModule : public Module { - Q_OBJECT - public: - VersionCheckingModule(); - - ~VersionCheckingModule() override; - - auto Register() -> bool override; +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectVersion() -> QString; - auto Active() -> bool override; +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectBuildVersion() -> QString; - auto Exec(EventRefrernce) -> int override; +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectBuildTimestamp() -> QDateTime; - auto Deactive() -> bool override; +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitBranchName() -> QString; - signals: +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitCommitHash() -> QString; - void SignalVersionCheckDone(SoftwareVersion); +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitVersion() -> QString; - public slots: +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GetHttpRequestUserAgent() -> QString; - void SlotVersionCheckDone(SoftwareVersion); -}; -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/CacheUtils.h b/src/core/utils/CacheUtils.h index 48b9ac4b..eae45353 100644 --- a/src/core/utils/CacheUtils.h +++ b/src/core/utils/CacheUtils.h @@ -28,6 +28,8 @@ #pragma once +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { /** diff --git a/src/core/utils/CommonUtils.cpp b/src/core/utils/CommonUtils.cpp index 0b182241..d1704312 100644 --- a/src/core/utils/CommonUtils.cpp +++ b/src/core/utils/CommonUtils.cpp @@ -43,7 +43,7 @@ auto BeautifyFingerprint(QString fingerprint) -> QString { return out.readAll(); } -auto CompareSoftwareVersion(const QString& a, const QString& b) -> int { +auto GFCompareSoftwareVersion(const QString& a, const QString& b) -> int { auto remove_prefix = [](const QString& version) { return version.startsWith('v') ? version.mid(1) : version; }; @@ -71,4 +71,25 @@ auto CompareSoftwareVersion(const QString& a, const QString& b) -> int { return 0; } + +auto GFStrDup(const QString& str) -> char* { + auto utf8_str = str.toUtf8(); + auto* c_str = + static_cast<char*>(SecureMalloc((utf8_str.size() + 1) * sizeof(char))); + + memcpy(c_str, utf8_str.constData(), utf8_str.size()); + c_str[utf8_str.size()] = '\0'; + return c_str; +} + +auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(char* str) -> QString { + auto qt_str = QString::fromUtf8(str); + SecureFree(static_cast<void*>(const_cast<char*>(str))); + return qt_str; +} + +auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(const char* str) -> QString { + return GFUnStrDup(const_cast<char*>(str)); +} + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/CommonUtils.h b/src/core/utils/CommonUtils.h index a45c6056..6ef38fad 100644 --- a/src/core/utils/CommonUtils.h +++ b/src/core/utils/CommonUtils.h @@ -48,7 +48,21 @@ auto GPGFRONTEND_CORE_EXPORT BeautifyFingerprint(QString fingerprint) * @param b * @return int */ -auto GPGFRONTEND_CORE_EXPORT CompareSoftwareVersion(const QString& a, - const QString& b) -> int; +auto GPGFRONTEND_CORE_EXPORT GFCompareSoftwareVersion(const QString& a, + const QString& b) -> int; + +/** + * @brief + * + * @return char* + */ +auto GPGFRONTEND_CORE_EXPORT GFStrDup(const QString&) -> char*; + +/** + * @brief + * + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(const char*) -> QString; } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/FilesystemUtils.h b/src/core/utils/FilesystemUtils.h index 0b58bbb7..0bc90ac5 100644 --- a/src/core/utils/FilesystemUtils.h +++ b/src/core/utils/FilesystemUtils.h @@ -28,6 +28,8 @@ #pragma once +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { /** @@ -54,8 +56,8 @@ auto GPGFRONTEND_CORE_EXPORT GetOnlyFileNameWithPath(const QString& path) * @param filename_pattern The pattern of the file name, e.g. "*.txt" * @return int64_t */ -auto GPGFRONTEND_CORE_EXPORT GetFileSizeByPath( - const QString& path, const QString& filename_pattern) +auto GPGFRONTEND_CORE_EXPORT GetFileSizeByPath(const QString& path, + const QString& filename_pattern) -> int64_t; /** @@ -72,7 +74,7 @@ auto GPGFRONTEND_CORE_EXPORT GetHumanFriendlyFileSize(int64_t size) -> QString; * @param path * @param filename_pattern */ -void GPGFRONTEND_CORE_EXPORT DeleteAllFilesByPattern( - const QString& path, const QString& filename_pattern); +void GPGFRONTEND_CORE_EXPORT +DeleteAllFilesByPattern(const QString& path, const QString& filename_pattern); } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/IOUtils.cpp b/src/core/utils/IOUtils.cpp index 1002badd..0be11755 100644 --- a/src/core/utils/IOUtils.cpp +++ b/src/core/utils/IOUtils.cpp @@ -180,4 +180,42 @@ auto GetFullExtension(const QString& path) -> QString { return filename.mid(dot_index); } +auto CalculateBinaryChacksum(const QString& path) -> QString { + // check file info and access rights + QFileInfo info(path); + if (!info.exists() || !info.isFile() || !info.isReadable()) { + GF_CORE_LOG_ERROR("get info for file {} error, exists: {}", info.filePath(), + info.exists()); + return {}; + } + + // open and read file + QFile f(info.filePath()); + if (!f.open(QIODevice::ReadOnly)) { + GF_CORE_LOG_ERROR("open {} to calculate checksum error: {}", + path.toStdString(), f.errorString().toStdString()); + return {}; + } + + QCryptographicHash hash_sha(QCryptographicHash::Sha256); + + // read data by chunks + const qint64 buffer_size = 8192; // Define a suitable buffer size + while (!f.atEnd()) { + QByteArray const buffer = f.read(buffer_size); + if (buffer.isEmpty()) { + GF_CORE_LOG_ERROR("error reading file {} during checksum calculation", + path.toStdString()); + return {}; + } + hash_sha.addData(buffer); + } + + // close the file + f.close(); + + // return the SHA-256 hash of the file + return hash_sha.result().toHex(); +} + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/IOUtils.h b/src/core/utils/IOUtils.h index 2c48f38c..3e18394d 100644 --- a/src/core/utils/IOUtils.h +++ b/src/core/utils/IOUtils.h @@ -85,6 +85,15 @@ auto GPGFRONTEND_CORE_EXPORT CalculateHash(const QString &file_path) -> QString; * @brief * * @param path + * @return QString + */ +auto GPGFRONTEND_CORE_EXPORT CalculateBinaryChacksum(const QString &path) + -> QString; + +/** + * @brief + * + * @param path * @param out_buffer * @return true * @return false diff --git a/src/core/utils/LocalizedUtils.cpp b/src/core/utils/LocalizedUtils.cpp index 6c020ed7..e5c9b434 100644 --- a/src/core/utils/LocalizedUtils.cpp +++ b/src/core/utils/LocalizedUtils.cpp @@ -32,7 +32,12 @@ namespace GpgFrontend { -auto GetFormatedDateByTimestamp(time_t timestamp) -> QString { +auto GetLocalizedDateByTimestamp(time_t timestamp) -> QString { return QLocale().toString(QDateTime::fromSecsSinceEpoch(timestamp)); } + +auto GetUTCDateByTimestamp(time_t timestamp) -> QString { + return QLocale().toString(QDateTime::fromSecsSinceEpoch(timestamp).toUTC()); +} + } // namespace GpgFrontend diff --git a/src/core/utils/LocalizedUtils.h b/src/core/utils/LocalizedUtils.h index d7aaf0c8..10ada833 100644 --- a/src/core/utils/LocalizedUtils.h +++ b/src/core/utils/LocalizedUtils.h @@ -28,8 +28,12 @@ #pragma once +#include "core/GpgFrontendCoreExport.h" + namespace GpgFrontend { -auto GPGFRONTEND_CORE_EXPORT GetFormatedDateByTimestamp(time_t) -> QString; +auto GPGFRONTEND_CORE_EXPORT GetLocalizedDateByTimestamp(time_t) -> QString; + +auto GPGFRONTEND_CORE_EXPORT GetUTCDateByTimestamp(time_t) -> QString; -}
\ No newline at end of file +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/LogUtils.h b/src/core/utils/LogUtils.h index a1a5685a..e8dc6f3b 100644 --- a/src/core/utils/LogUtils.h +++ b/src/core/utils/LogUtils.h @@ -28,6 +28,49 @@ #pragma once +// spdlog library configuration +#undef SPDLOG_ACTIVE_LEVEL +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE +#include <spdlog/spdlog.h> + +// logger fmt +#include "core/GpgFrontendCoreExport.h" + +template <> +struct fmt::formatter<QString> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter<QByteArray> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; + namespace GpgFrontend { /** @@ -50,7 +93,7 @@ auto GPGFRONTEND_CORE_EXPORT GetCoreLogger() -> std::shared_ptr<spdlog::logger>; * * @return std::shared_ptr<spdlog::logger> */ -auto GPGFRONTEND_CORE_EXPORT GetLogger(const QString &) +auto GPGFRONTEND_CORE_EXPORT GetLogger(const QString&) -> std::shared_ptr<spdlog::logger>; /** @@ -65,7 +108,7 @@ void GPGFRONTEND_CORE_EXPORT SetDefaultLogLevel(spdlog::level::level_enum); * * @return auto */ -void GPGFRONTEND_CORE_EXPORT RegisterAsyncLogger(const QString &, +void GPGFRONTEND_CORE_EXPORT RegisterAsyncLogger(const QString&, spdlog::level::level_enum); /** @@ -73,7 +116,7 @@ void GPGFRONTEND_CORE_EXPORT RegisterAsyncLogger(const QString &, * * @return auto */ -void GPGFRONTEND_CORE_EXPORT RegisterSyncLogger(const QString &, +void GPGFRONTEND_CORE_EXPORT RegisterSyncLogger(const QString&, spdlog::level::level_enum); } // namespace GpgFrontend diff --git a/src/init.cpp b/src/init.cpp index 76c1fd4c..b3156d1f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -31,9 +31,9 @@ #include "core/GpgCoreInit.h" #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgAdvancedOperator.h" +#include "core/module/ModuleInit.h" #include "core/thread/TaskRunnerGetter.h" #include "core/utils/LogUtils.h" -#include "module/GpgFrontendModuleInit.h" #include "ui/GpgFrontendUIInit.h" // main @@ -106,7 +106,7 @@ void InitGlobalPathEnv() { } } -void InitGlobalBasicalEnv(const GFCxtWPtr &p_ctx, bool gui_mode) { +void InitGlobalBasicEnv(const GFCxtWPtr &p_ctx, bool gui_mode) { GFCxtSPtr ctx = p_ctx.lock(); if (ctx == nullptr) { return; @@ -161,7 +161,7 @@ void InitLocale() { QLocale::setDefault(target_locale); } -void ShutdownGlobalBasicalEnv(const GFCxtWPtr &p_ctx) { +void ShutdownGlobalBasicEnv(const GFCxtWPtr &p_ctx) { GFCxtSPtr ctx = p_ctx.lock(); if (ctx == nullptr) { return; @@ -56,13 +56,13 @@ void InitLocale(); * * @param args */ -void InitGlobalBasicalEnv(const GFCxtWPtr &, bool); +void InitGlobalBasicEnv(const GFCxtWPtr &, bool); /** * @brief * * @param p_ctx */ -void ShutdownGlobalBasicalEnv(const GFCxtWPtr &p_ctx); +void ShutdownGlobalBasicEnv(const GFCxtWPtr &p_ctx); } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index abc6ed56..a99f3e30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,9 +33,11 @@ #include "GpgFrontendContext.h" #include "app.h" #include "cmd.h" -#include "core/utils/MemoryUtils.h" #include "init.h" +// +#include "core/utils/MemoryUtils.h" + /** * * @param argc @@ -43,7 +45,7 @@ * @return */ auto main(int argc, char* argv[]) -> int { - GpgFrontend::GFCxtSPtr ctx = + GpgFrontend::GFCxtSPtr const ctx = GpgFrontend::SecureCreateSharedObject<GpgFrontend::GpgFrontendContext>( argc, argv); ctx->InitApplication(); @@ -79,17 +81,17 @@ auto main(int argc, char* argv[]) -> int { ctx->gather_external_gnupg_info = false; ctx->load_default_gpg_context = false; - InitGlobalBasicalEnv(ctx, false); + InitGlobalBasicEnv(ctx, false); rtn = RunTest(ctx); - ShutdownGlobalBasicalEnv(ctx); + ShutdownGlobalBasicEnv(ctx); return rtn; } ctx->gather_external_gnupg_info = true; ctx->load_default_gpg_context = true; - InitGlobalBasicalEnv(ctx, true); + InitGlobalBasicEnv(ctx, true); rtn = StartApplication(ctx); - ShutdownGlobalBasicalEnv(ctx); + ShutdownGlobalBasicEnv(ctx); return rtn; } diff --git a/src/module/CMakeLists.txt b/src/module/CMakeLists.txt index a741f0af..8d894b00 100644 --- a/src/module/CMakeLists.txt +++ b/src/module/CMakeLists.txt @@ -30,15 +30,16 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) aux_source_directory(sdk MODULE_SDK_SOURCE) add_library(gpgfrontend_module_sdk SHARED ${MODULE_SDK_SOURCE}) -set(_export_file_sdk "${CMAKE_CURRENT_SOURCE_DIR}/sdk/GpgFrontendModuleSDKExport.h") +set(_export_file_sdk "${CMAKE_CURRENT_SOURCE_DIR}/sdk/GFSDKExport.h") generate_export_header(gpgfrontend_module_sdk EXPORT_FILE_NAME "${_export_file_sdk}") -target_include_directories(gpgfrontend_module_sdk PUBLIC - sdk +target_include_directories(gpgfrontend_module_sdk PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_module_sdk_autogen/include ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) +target_include_directories(gpgfrontend_module_sdk PUBLIC sdk) + # link module system -target_link_libraries(gpgfrontend_module_sdk PUBLIC gpgfrontend_core) +target_link_libraries(gpgfrontend_module_sdk PRIVATE gpgfrontend_core) if (XCODE_BUILD) set_target_properties(gpgfrontend_module_sdk @@ -50,51 +51,14 @@ if (XCODE_BUILD) XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") endif () -# tracking integrated modules +# tracking modules set(all_integrated_module_libraries "") -file(GLOB children LIST_DIRECTORIES true "integrated/*") +file(GLOB children LIST_DIRECTORIES true "mods/*") foreach(child ${children}) if(IS_DIRECTORY ${child}) get_filename_component(dirName ${child} NAME) - add_subdirectory("integrated/${dirName}") - - string(REPLACE "_module" "" stripped_module ${dirName}) - set(integrated_lib_name "gpgfrontend_integrated_module_${stripped_module}") - list(APPEND all_integrated_module_libraries ${integrated_lib_name}) + add_subdirectory("mods/${dirName}") + + list(APPEND all_integrated_module_libraries ${dirName}) endif() -endforeach() - -aux_source_directory(. MODULE_SOURCE) -add_library(gpgfrontend_module SHARED ${MODULE_SOURCE}) - -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendModuleExport.h") -generate_export_header(gpgfrontend_module EXPORT_FILE_NAME "${_export_file}") - -# set up pch -target_precompile_headers(gpgfrontend_module PUBLIC GpgFrontendModule.h) - -# add ui generator include path -target_include_directories(gpgfrontend_module PUBLIC - ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_module_autogen/include - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) - -# link gpgfrontend_module_sdk -target_link_libraries(gpgfrontend_module PRIVATE gpgfrontend_module_sdk) - -if (XCODE_BUILD) - set_target_properties(gpgfrontend_module - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - - -# link all integrated modules -message(STATUS "All Module Libraries: ${all_integrated_module_libraries}") -target_link_libraries(gpgfrontend_module PRIVATE ${all_integrated_module_libraries}) - -# using std c++ 17 -target_compile_features(gpgfrontend_module PUBLIC cxx_std_17)
\ No newline at end of file +endforeach()
\ No newline at end of file diff --git a/src/module/GpgFrontendModuleExport.h b/src/module/GpgFrontendModuleExport.h deleted file mode 100644 index 33ecbd3b..00000000 --- a/src/module/GpgFrontendModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GPGFRONTEND_MODULE_EXPORT_H -#define GPGFRONTEND_MODULE_EXPORT_H - -#ifdef GPGFRONTEND_MODULE_STATIC_DEFINE -# define GPGFRONTEND_MODULE_EXPORT -# define GPGFRONTEND_MODULE_NO_EXPORT -#else -# ifndef GPGFRONTEND_MODULE_EXPORT -# ifdef gpgfrontend_module_EXPORTS - /* We are building this library */ -# define GPGFRONTEND_MODULE_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GPGFRONTEND_MODULE_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GPGFRONTEND_MODULE_NO_EXPORT -# define GPGFRONTEND_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GPGFRONTEND_MODULE_DEPRECATED -# define GPGFRONTEND_MODULE_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GPGFRONTEND_MODULE_DEPRECATED_EXPORT -# define GPGFRONTEND_MODULE_DEPRECATED_EXPORT GPGFRONTEND_MODULE_EXPORT GPGFRONTEND_MODULE_DEPRECATED -#endif - -#ifndef GPGFRONTEND_MODULE_DEPRECATED_NO_EXPORT -# define GPGFRONTEND_MODULE_DEPRECATED_NO_EXPORT GPGFRONTEND_MODULE_NO_EXPORT GPGFRONTEND_MODULE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GPGFRONTEND_MODULE_NO_DEPRECATED -# define GPGFRONTEND_MODULE_NO_DEPRECATED -# endif -#endif - -#endif /* GPGFRONTEND_MODULE_EXPORT_H */ diff --git a/src/module/GpgFrontendModuleInit.cpp b/src/module/GpgFrontendModuleInit.cpp deleted file mode 100644 index 6f88b9ec..00000000 --- a/src/module/GpgFrontendModuleInit.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GpgFrontendModuleInit.h" - -#include <core/module/ModuleManager.h> - -#include "core/thread/Task.h" -#include "core/thread/TaskRunnerGetter.h" - -// integrated modules -#include "integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.h" -#include "integrated/version_checking_module/VersionCheckingModule.h" -#include "spdlog/common.h" - -namespace GpgFrontend::Module { - -void LoadGpgFrontendModules(ModuleInitArgs) { - // must init at default thread before core - Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( - new Thread::Task( - [](const DataObjectPtr&) -> int { - MODULE_LOG_INFO("loading integrated module..."); - - // VersionCheckingModule - RegisterAndActivateModule< - Integrated::VersionCheckingModule::VersionCheckingModule>(); - - // VersionCheckingModule - RegisterAndActivateModule<Integrated::GnuPGInfoGatheringModule:: - GnuPGInfoGatheringModule>(); - - MODULE_LOG_INFO("load integrated module done."); - return 0; - }, - "modules_system_init_task")); -} - -void ShutdownGpgFrontendModules() {} - -} // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp deleted file mode 100644 index a1e5cd5a..00000000 --- a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GnuPGInfoGatheringModule.h" - -#include <vector> - -#include "GpgInfo.h" -#include "Log.h" -#include "core/function/gpg/GpgCommandExecutor.h" -#include "core/module/ModuleManager.h" - -namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule { - -auto CheckBinaryChacksum(QString path) -> std::optional<QString> { - // check file info and access rights - QFileInfo info(path); - if (!info.exists() || !info.isFile() || !info.isReadable()) { - MODULE_LOG_ERROR("get info for file {} error, exists: {}", info.filePath(), - info.exists()); - return {}; - } - - // open and read file - QFile f(info.filePath()); - if (!f.open(QIODevice::ReadOnly)) { - MODULE_LOG_ERROR("open {} to calculate check sum error: {}", path, - f.errorString()); - return {}; - } - - // read all data from file - auto buffer = f.readAll(); - f.close(); - - auto hash_sha = QCryptographicHash(QCryptographicHash::Sha256); - // md5 - hash_sha.addData(buffer); - return QString(hash_sha.result().toHex()).left(6); -} - -GnuPGInfoGatheringModule::GnuPGInfoGatheringModule() - : Module( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "1.0.0", - ModuleMetaData{{"description", "try to gathering gnupg informations"}, - {"author", "saturneric"}}) {} - -GnuPGInfoGatheringModule::~GnuPGInfoGatheringModule() = default; - -auto GnuPGInfoGatheringModule::Register() -> bool { - MODULE_LOG_DEBUG("gnupg info gathering module registering"); - listenEvent("GPGFRONTEND_CORE_INITLIZED"); - return true; -} - -auto GnuPGInfoGatheringModule::Active() -> bool { - MODULE_LOG_DEBUG("gnupg info gathering module activating"); - return true; -} - -auto GnuPGInfoGatheringModule::Exec(EventRefrernce event) -> int { - MODULE_LOG_DEBUG("gnupg info gathering module executing, event id: {}", - event->GetIdentifier()); - - const auto gpgme_version = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.version", QString{"0.0.0"}); - MODULE_LOG_DEBUG("got gpgme version from rt: {}", gpgme_version); - - const auto gpgconf_path = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gpgconf_path", QString{}); - MODULE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); - - MODULE_LOG_DEBUG("start to load extra info at module gnupginfogathering..."); - - // get all components - GpgCommandExecutor::ExecuteSync( - {gpgconf_path, QStringList{"--list-components"}, - [this, gpgme_version, gpgconf_path](int exit_code, const QString &p_out, - const QString &p_err) { - MODULE_LOG_DEBUG( - "gpgconf components exit_code: {} process stdout size: {}", - exit_code, p_out.size()); - - if (exit_code != 0) { - MODULE_LOG_ERROR( - "gpgconf execute error, process stderr: {}, " - "process stdout: {}", - p_err, p_out); - return; - } - - std::vector<GpgComponentInfo> component_infos; - GpgComponentInfo c_i_gpgme; - c_i_gpgme.name = "gpgme"; - c_i_gpgme.desc = "GPG Made Easy"; - c_i_gpgme.version = gpgme_version; - c_i_gpgme.path = tr("Embedded In"); - c_i_gpgme.binary_checksum = "/"; - - GpgComponentInfo c_i_gpgconf; - c_i_gpgconf.name = "gpgconf"; - c_i_gpgconf.desc = "GPG Configure"; - c_i_gpgconf.version = "/"; - c_i_gpgconf.path = gpgconf_path; - auto gpgconf_binary_checksum = CheckBinaryChacksum(gpgconf_path); - c_i_gpgconf.binary_checksum = (gpgconf_binary_checksum.has_value() - ? gpgconf_binary_checksum.value() - : QString("/")); - - component_infos.push_back(c_i_gpgme); - component_infos.push_back(c_i_gpgconf); - - auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); - auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); - UpsertRTValue(GetModuleIdentifier(), "gnupg.components.gpgme", - QJsonDocument(jsonlized_gpgme_component_info).toJson()); - UpsertRTValue( - GetModuleIdentifier(), "gnupg.components.gpgconf", - QJsonDocument(jsonlized_gpgconf_component_info).toJson()); - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - if (info_split_list.size() != 3) continue; - - auto component_name = info_split_list[0].trimmed(); - auto component_desc = info_split_list[1].trimmed(); - auto component_path = info_split_list[2].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows platform - component_path.replace("%3a", ":"); -#endif - - auto binary_checksum = CheckBinaryChacksum(component_path); - - MODULE_LOG_DEBUG( - "gnupg component name: {} desc: {} checksum: {} path: {} ", - component_name, component_desc, - binary_checksum.has_value() ? binary_checksum.value() : "/", - component_path); - - QString version = "/"; - - if (component_name == "gpg") { - version = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); - } - if (component_name == "gpg-agent") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.gpg_agent_path", - QString(component_path)); - } - if (component_name == "dirmngr") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.dirmngr_path", - QString(component_path)); - } - if (component_name == "keyboxd") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.keyboxd_path", - QString(component_path)); - } - - { - GpgComponentInfo c_i; - c_i.name = component_name; - c_i.desc = component_desc; - c_i.version = version; - c_i.path = component_path; - c_i.binary_checksum = - (binary_checksum.has_value() ? binary_checksum.value() - : QString("/")); - - auto const jsonlized_component_info = c_i.Json(); - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.components.%1").arg(component_name), - QJsonDocument(jsonlized_component_info).toJson()); - - component_infos.push_back(c_i); - } - } - }, - getTaskRunner()}); - - GpgCommandExecutor::ExecuteContexts exec_contexts; -#ifdef QT5_BUILD - exec_contexts.push_back(GpgCommandExecutor::ExecuteContext{ -#else - exec_contexts.emplace_back(GpgCommandExecutor::ExecuteContext{ -#endif - gpgconf_path, QStringList{"--list-dirs"}, - [this](int exit_code, const QString &p_out, const QString &p_err) { - if (exit_code != 0) return; - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - MODULE_LOG_DEBUG("gpgconf direcrotries info line: {} info size: {}", - line, info_split_list.size()); - - if (info_split_list.size() != 2) continue; - - auto configuration_name = info_split_list[0].trimmed(); - auto configuration_value = info_split_list[1].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows platform - configuration_value.replace("%3a", ":"); -#endif - - // record gnupg home path - if (configuration_name == "homedir") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.home_path", - configuration_value); - } - - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.dirs.%1").arg(configuration_name), - configuration_value); - } - }, - getTaskRunner()}); - - auto components = ListRTChildKeys(GetModuleIdentifier(), "gnupg.components"); - - for (const auto &component : components) { - auto component_info_json = RetrieveRTValueTypedOrDefault( - GetModuleIdentifier(), QString("gnupg.components.%1").arg(component), - QByteArray{}); - - auto jsonlized_component_info = - QJsonDocument::fromJson(component_info_json); - assert(jsonlized_component_info.isObject()); - - auto component_info = GpgComponentInfo(jsonlized_component_info.object()); - MODULE_LOG_DEBUG("gpgconf check options ready, component: {}", - component_info.name); - - if (component_info.name == "gpgme" || component_info.name == "gpgconf") { - continue; - } - -#ifdef QT5_BUILD - exec_contexts.push_back(GpgCommandExecutor::ExecuteContext{ -#else - exec_contexts.emplace_back(GpgCommandExecutor::ExecuteContext{ -#endif - gpgconf_path, QStringList{"--list-options", component_info.name}, - [this, component_info](int exit_code, const QString &p_out, - const QString &p_err) { - MODULE_LOG_DEBUG( - "gpgconf {} avaliable options exit_code: {} process stdout " - "size: {} ", - component_info.name, exit_code, p_out.size()); - - if (exit_code != 0) { - MODULE_LOG_ERROR( - "gpgconf {} avaliable options execute error, process stderr: " - "{} , process stdout:", - component_info.name, p_err, p_out); - return; - } - - std::vector<GpgOptionsInfo> options_infos; - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - MODULE_LOG_DEBUG( - "component {} avaliable options line: {} info size: {}", - component_info.name, line, info_split_list.size()); - - if (info_split_list.size() < 10) continue; - - // The format of each line is: - // name:flags:level:description:type:alt-type:argname:default:argdef:value - - auto option_name = info_split_list[0].trimmed(); - auto option_flags = info_split_list[1].trimmed(); - auto option_level = info_split_list[2].trimmed(); - auto option_desc = info_split_list[3].trimmed(); - auto option_type = info_split_list[4].trimmed(); - auto option_alt_type = info_split_list[5].trimmed(); - auto option_argname = info_split_list[6].trimmed(); - auto option_default = info_split_list[7].trimmed(); - auto option_argdef = info_split_list[8].trimmed(); - auto option_value = info_split_list[9].trimmed(); - - GpgOptionsInfo info; - info.name = option_name; - info.flags = option_flags; - info.level = option_level; - info.description = option_desc; - info.type = option_type; - info.alt_type = option_alt_type; - info.argname = option_argname; - info.default_value = option_default; - info.argdef = option_argdef; - info.value = option_value; - - auto const jsonlized_option_info = info.Json(); - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.components.%1.options.%2") - .arg(component_info.name) - .arg(option_name), - QJsonDocument(jsonlized_option_info).toJson()); - options_infos.push_back(info); - } - }, - getTaskRunner()}); - } - - GpgCommandExecutor::ExecuteConcurrentlySync(exec_contexts); - UpsertRTValue(GetModuleIdentifier(), "gnupg.gathering_done", true); - event->ExecuteCallback(GetModuleIdentifier(), TransferParams(true)); - - MODULE_LOG_DEBUG("gnupg external info gathering done"); - return 0; -} - -auto GnuPGInfoGatheringModule::Deactive() -> bool { return true; } - -} // namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule diff --git a/src/module/integrated/gnupg_info_gathering_module/GpgFrontendModuleExport.h b/src/module/integrated/gnupg_info_gathering_module/GpgFrontendModuleExport.h deleted file mode 100644 index 3a5ba68b..00000000 --- a/src/module/integrated/gnupg_info_gathering_module/GpgFrontendModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT_H -#define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT_H - -#ifdef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_STATIC_DEFINE -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_EXPORT -#else -# ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT -# ifdef gpgfrontend_integrated_module_gnupg_info_gathering_EXPORTS - /* We are building this library */ -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED_EXPORT GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED_NO_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED_NO_EXPORT GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_EXPORT GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_DEPRECATED -# define GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_NO_DEPRECATED -# endif -#endif - -#endif /* GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT_H */ diff --git a/src/module/integrated/version_checking_module/GpgFrontendModuleExport.h b/src/module/integrated/version_checking_module/GpgFrontendModuleExport.h deleted file mode 100644 index 0ac60b2f..00000000 --- a/src/module/integrated/version_checking_module/GpgFrontendModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT_H -#define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT_H - -#ifdef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_STATIC_DEFINE -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_EXPORT -#else -# ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT -# ifdef gpgfrontend_integrated_module_version_checking_EXPORTS - /* We are building this library */ -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED_EXPORT GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED -#endif - -#ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED_NO_EXPORT -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED_NO_EXPORT GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_EXPORT GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_DEPRECATED -# define GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_NO_DEPRECATED -# endif -#endif - -#endif /* GPGFRONTEND_INTEGRATED_MODULE_VERSION_CHECKING_EXPORT_H */ diff --git a/src/module/integrated/version_checking_module/SoftwareVersion.cpp b/src/module/integrated/version_checking_module/SoftwareVersion.cpp deleted file mode 100644 index 7d41b1c5..00000000 --- a/src/module/integrated/version_checking_module/SoftwareVersion.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "SoftwareVersion.h" - -#include "core/utils/CommonUtils.h" -#include "module/sdk/Log.h" - -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { - -auto VersionCheckingModule::SoftwareVersion::NeedUpgrade() const -> bool { - MODULE_LOG_DEBUG("compair version current {} latest {}, result {}", - current_version, latest_version, - CompareSoftwareVersion(current_version, latest_version)); - - MODULE_LOG_DEBUG("load done: {}, pre-release: {}, draft: {}", loading_done, - latest_prerelease_version_from_remote, - latest_draft_from_remote); - return loading_done && !latest_prerelease_version_from_remote && - !latest_draft_from_remote && - CompareSoftwareVersion(current_version, latest_version) < 0; -} - -auto VersionCheckingModule::SoftwareVersion::VersionWithdrawn() const -> bool { - return loading_done && !current_version_publish_in_remote && - current_version_is_a_prerelease && !current_version_is_drafted; -} - -auto VersionCheckingModule::SoftwareVersion::CurrentVersionReleased() const - -> bool { - return loading_done && current_version_publish_in_remote; -} -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule
\ No newline at end of file diff --git a/src/module/integrated/version_checking_module/VersionCheckingModule.cpp b/src/module/integrated/version_checking_module/VersionCheckingModule.cpp deleted file mode 100644 index 9b62a9c8..00000000 --- a/src/module/integrated/version_checking_module/VersionCheckingModule.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "VersionCheckingModule.h" - -#include "Log.h" -#include "SoftwareVersion.h" -#include "VersionCheckTask.h" -#include "core/module/Module.h" -#include "core/module/ModuleManager.h" - -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { - -VersionCheckingModule::VersionCheckingModule() - : Module("com.bktus.gpgfrontend.module.integrated.version-checking", - "1.0.0", - ModuleMetaData{{"description", "try to check gpgfrontend version"}, - {"author", "saturneric"}}) {} - -VersionCheckingModule::~VersionCheckingModule() = default; - -auto VersionCheckingModule::Register() -> bool { - MODULE_LOG_INFO("version checking module registering"); - listenEvent("APPLICATION_LOADED"); - listenEvent("CHECK_APPLICATION_VERSION"); - return true; -} - -auto VersionCheckingModule::Active() -> bool { - MODULE_LOG_INFO("version checking module activating"); - return true; -} - -auto VersionCheckingModule::Exec(EventRefrernce event) -> int { - MODULE_LOG_INFO("version checking module executing, event id: {}", - event->GetIdentifier()); - - auto* task = new VersionCheckTask(); - connect(task, &VersionCheckTask::SignalUpgradeVersion, this, - &VersionCheckingModule::SignalVersionCheckDone); - connect(this, &VersionCheckingModule::SignalVersionCheckDone, this, - [this, event](SoftwareVersion version) { - SlotVersionCheckDone(std::move(version)); - event->ExecuteCallback(GetModuleIdentifier(), - TransferParams(version.loading_done)); - }); - getTaskRunner()->PostTask(task); - return 0; -} - -auto VersionCheckingModule::Deactive() -> bool { return true; } - -void VersionCheckingModule::SlotVersionCheckDone(SoftwareVersion version) { - MODULE_LOG_DEBUG("registering software information info to rt"); - UpsertRTValue(GetModuleIdentifier(), "version.current_version", - version.current_version); - UpsertRTValue(GetModuleIdentifier(), "version.latest_version", - version.latest_version); - UpsertRTValue(GetModuleIdentifier(), "version.current_version_is_drafted", - version.current_version_is_drafted); - UpsertRTValue(GetModuleIdentifier(), - "version.current_version_is_a_prerelease", - version.current_version_is_a_prerelease); - UpsertRTValue(GetModuleIdentifier(), - "version.current_version_publish_in_remote", - version.current_version_publish_in_remote); - UpsertRTValue(GetModuleIdentifier(), - "version.latest_prerelease_version_from_remote", - version.latest_prerelease_version_from_remote); - UpsertRTValue(GetModuleIdentifier(), "version.need_upgrade", - version.NeedUpgrade()); - UpsertRTValue(GetModuleIdentifier(), "version.current_version_released", - version.CurrentVersionReleased()); - UpsertRTValue(GetModuleIdentifier(), "version.current_a_withdrawn_version", - version.VersionWithdrawn()); - UpsertRTValue(GetModuleIdentifier(), "version.loading_done", - version.loading_done); - MODULE_LOG_DEBUG("register software information to rt done"); -} -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule diff --git a/src/module/integrated/gnupg_info_gathering_module/CMakeLists.txt b/src/module/mods/gpg_info/CMakeLists.txt index 48dbd0de..6660f5cb 100644 --- a/src/module/integrated/gnupg_info_gathering_module/CMakeLists.txt +++ b/src/module/mods/gpg_info/CMakeLists.txt @@ -23,31 +23,54 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering +# com.bktus.gpgfrontend.module.integrated.gnupg_info_gathering aux_source_directory(. INTEGRATED_MODULE_SOURCE) # define libgpgfrontend_module -add_library(gpgfrontend_integrated_module_gnupg_info_gathering SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendModuleExport.h") -generate_export_header(gpgfrontend_integrated_module_gnupg_info_gathering EXPORT_FILE_NAME "${_export_file}") +add_library(mod_gpg_info SHARED ${INTEGRATED_MODULE_SOURCE}) +set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") +generate_export_header(mod_gpg_info + BASE_NAME "GF_MODULE" + EXPORT_FILE_NAME "${_export_file}") + +target_include_directories(mod_gpg_info PRIVATE + ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + +# set output directory +set_target_properties(mod_gpg_info PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods) if (XCODE_BUILD) - set_target_properties(gpgfrontend_integrated_module_gnupg_info_gathering + set_target_properties(mod_gpg_info PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") endif () +if (LINUX AND LINUX_INSTALL_SOFTWARE) + install(TARGETS mod_gpg_info + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/mods/") +endif() + # link sdk -target_link_libraries(gpgfrontend_integrated_module_gnupg_info_gathering PRIVATE - gpgfrontend_module_sdk) +target_link_libraries(mod_gpg_info PRIVATE + gpgfrontend_module_sdk) + +if(GPGFRONTEND_QT5_BUILD) + # link Qt core + target_link_libraries(mod_gpg_info PRIVATE Qt5::Core) +else() + # link Qt core + target_link_libraries(mod_gpg_info PRIVATE Qt6::Core) +endif() # property -set_property(TARGET gpgfrontend_integrated_module_gnupg_info_gathering PROPERTY AUTOMOC ON) +set_property(TARGET mod_gpg_info PROPERTY AUTOMOC ON) # using std c++ 17 -target_compile_features(gpgfrontend_integrated_module_gnupg_info_gathering PRIVATE cxx_std_17)
\ No newline at end of file +target_compile_features(mod_gpg_info PRIVATE cxx_std_17)
\ No newline at end of file diff --git a/src/module/mods/gpg_info/GFModuleExport.h b/src/module/mods/gpg_info/GFModuleExport.h new file mode 100644 index 00000000..a1fc1053 --- /dev/null +++ b/src/module/mods/gpg_info/GFModuleExport.h @@ -0,0 +1,42 @@ + +#ifndef GF_MODULE_EXPORT_H +#define GF_MODULE_EXPORT_H + +#ifdef GF_MODULE_STATIC_DEFINE +# define GF_MODULE_EXPORT +# define GF_MODULE_NO_EXPORT +#else +# ifndef GF_MODULE_EXPORT +# ifdef mod_gpg_info_EXPORTS + /* We are building this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef GF_MODULE_NO_EXPORT +# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef GF_MODULE_DEPRECATED +# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef GF_MODULE_DEPRECATED_EXPORT +# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED +#endif + +#ifndef GF_MODULE_DEPRECATED_NO_EXPORT +# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef GF_MODULE_NO_DEPRECATED +# define GF_MODULE_NO_DEPRECATED +# endif +#endif + +#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp b/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp new file mode 100644 index 00000000..8d400c89 --- /dev/null +++ b/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp @@ -0,0 +1,526 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GnuPGInfoGatheringModule.h" + +#include <GFSDKBasic.h> +#include <GFSDKBuildInfo.h> +#include <GFSDKLog.h> +#include <spdlog/spdlog.h> + +// qt +#include <QCryptographicHash> +#include <QFileInfo> +#include <QJsonDocument> +#include <QString> + +// c++ +#include <optional> + +#include "GpgInfo.h" + +template <> +struct fmt::formatter<QString> { + // Parses format specifications. + constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QString &qstr, FormatContext &ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter<QByteArray> { + // Parses format specifications. + constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QByteArray &qarray, FormatContext &ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; + +extern auto CalculateBinaryChacksum(const QString &path) + -> std::optional<QString>; + +extern void GetGpgComponentInfos(void *, int, const char *, const char *); + +extern void GetGpgDirectoryInfos(void *, int, const char *, const char *); + +extern void GetGpgOptionInfos(void *, int, const char *, const char *); + +using Context = struct { + QString gpgme_version; + QString gpgconf_path; + GpgComponentInfo component_info; +}; + +auto GFGetModuleGFSDKVersion() -> const char * { + return GFModuleStrDup(GF_SDK_VERSION_STR); +} + +auto GFGetModuleQtEnvVersion() -> const char * { + return GFModuleStrDup(QT_VERSION_STR); +} + +auto GFGetModuleID() -> const char * { + return GFModuleStrDup("com.bktus.gpgfrontend.module.gnupg_info_gathering"); +} + +auto GFGetModuleVersion() -> const char * { return GFModuleStrDup("1.0.0"); } + +auto GFGetModuleMetaData() -> GFModuleMetaData * { + auto *p_meta = static_cast<GFModuleMetaData *>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + auto *h_meta = p_meta; + + p_meta->key = "Name"; + p_meta->value = "GatherGnupgInfo"; + p_meta->next = static_cast<GFModuleMetaData *>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Description"; + p_meta->value = "Try gathering gnupg informations"; + p_meta->next = static_cast<GFModuleMetaData *>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Author"; + p_meta->value = "Saturneric"; + p_meta->next = nullptr; + return h_meta; +} + +auto GFRegisterModule() -> int { + GFModuleLogDebug("gnupg info gathering module registering"); + return 0; +} + +auto GFActiveModule() -> int { + GFModuleLogDebug("gnupg info gathering module activating"); + GFModuleListenEvent(GFGetModuleID(), + GFModuleStrDup("REQUEST_GATHERING_GNUPG_INFO")); + return 0; +} + +auto GFExecuteModule(GFModuleEvent *event) -> int { + GFModuleLogDebug( + fmt::format("gnupg info gathering module executing, event id: {}", + event->id) + .c_str()); + + GFModuleLogDebug("start to load extra info at module gnupginfogathering..."); + + const auto *const gpgme_version = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.version"), + GFModuleStrDup("0.0.0")); + GFModuleLogDebug( + fmt::format("got gpgme version from rt: {}", gpgme_version).c_str()); + + const auto *const gpgconf_path = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gpgconf_path"), + GFModuleStrDup("")); + GFModuleLogDebug( + fmt::format("got gpgconf path from rt: {}", gpgconf_path).c_str()); + + auto context = Context{gpgme_version, gpgconf_path}; + + // get all components + const char *argv[] = {GFModuleStrDup("--list-components")}; + GFExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context); + GFModuleLogDebug("load gnupg component info done."); + +#ifdef QT5_BUILD + QVector<GFCommandExecuteContext> exec_contexts; +#else + QList<GFCommandExecuteContext> exec_contexts; +#endif + + const char **argv_0 = + static_cast<const char **>(GFAllocateMemory(sizeof(const char *))); + argv_0[0] = GFModuleStrDup("--list-dirs"); + + exec_contexts.push_back( + {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr}); + + char **components_c_array; + int ret = GFModuleListRTChildKeys( + GFGetModuleID(), GFModuleStrDup("gnupg.components"), &components_c_array); + if (components_c_array == nullptr || ret == 0) return -1; + + QStringList components; + auto *p_a = components_c_array; + for (int i = 0; i < ret; i++) components.append(QString::fromUtf8(p_a[i])); + + for (const auto &component : components) { + const auto *component_info_json = GFModuleRetrieveRTValueOrDefault( + GFGetModuleID(), + GFModuleStrDup(QString("gnupg.components.%1").arg(component).toUtf8()), + nullptr); + + if (component_info_json == nullptr) continue; + + auto jsonlized_component_info = + QJsonDocument::fromJson(component_info_json); + assert(jsonlized_component_info.isObject()); + + auto component_info = GpgComponentInfo(jsonlized_component_info.object()); + GFModuleLogDebug(fmt::format("gpgconf check options ready, " + "component: {}", + component_info.name) + .c_str()); + + if (component_info.name == "gpgme" || component_info.name == "gpgconf") { + continue; + } + + auto *context = new (GFAllocateMemory(sizeof(Context))) + Context{gpgme_version, gpgconf_path, component_info}; + + const char **argv_0 = + static_cast<const char **>(GFAllocateMemory(sizeof(const char *) * 2)); + argv_0[0] = GFModuleStrDup("--list-options"), + argv_0[1] = GFModuleStrDup(component_info.name.toUtf8()); + exec_contexts.push_back( + {gpgconf_path, 2, argv_0, GetGpgOptionInfos, context}); + } + + GFExecuteCommandBatchSync(static_cast<int32_t>(exec_contexts.size()), + exec_contexts.constData()); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("gnupg.gathering_done"), 1); + + char **event_argv = + static_cast<char **>(GFAllocateMemory(sizeof(char **) * 1)); + event_argv[0] = GFModuleStrDup("0"); + + GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, event_argv); + + GFModuleLogDebug("gnupg external info gathering done"); + return 0; +} + +auto GFDeactiveModule() -> int { return 0; } + +auto GFUnregisterModule() -> int { + GFModuleLogDebug("gnupg info gathering module unregistering"); + return 0; +} + +auto CalculateBinaryChacksum(const QString &path) -> std::optional<QString> { + // check file info and access rights + QFileInfo info(path); + if (!info.exists() || !info.isFile() || !info.isReadable()) { + GFModuleLogError(fmt::format("get info for file {} error, exists: {}", + info.filePath(), info.exists()) + .c_str()); + return {}; + } + + // open and read file + QFile f(info.filePath()); + if (!f.open(QIODevice::ReadOnly)) { + GFModuleLogError(fmt::format("open {} to calculate checksum error: {}", + path.toStdString(), + f.errorString().toStdString()) + .c_str()); + return {}; + } + + QCryptographicHash hash_sha(QCryptographicHash::Sha256); + + // read data by chunks + const qint64 buffer_size = 8192; // Define a suitable buffer size + while (!f.atEnd()) { + QByteArray const buffer = f.read(buffer_size); + if (buffer.isEmpty()) { + GFModuleLogError(fmt::format("error reading file {} during " + "checksum calculation", + path.toStdString()) + .c_str()); + return {}; + } + hash_sha.addData(buffer); + } + + // close the file + f.close(); + + // return the first 6 characters of the SHA-256 hash + // of the file + return QString(hash_sha.result().toHex()).left(6); +} + +void GetGpgComponentInfos(void *data, int exit_code, const char *out, + const char *err) { + auto *context = reinterpret_cast<Context *>(data); + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + + GFModuleLogDebug(fmt::format("gpgconf components exit_code: {} " + "process stdout size: {}", + exit_code, p_out.size()) + .c_str()); + + if (exit_code != 0) { + GFModuleLogError(fmt::format("gpgconf execute error, process " + "stderr: {}, " + "process stdout: {}", + p_err, p_out) + .c_str()); + return; + } + + std::vector<GpgComponentInfo> component_infos; + GpgComponentInfo c_i_gpgme; + c_i_gpgme.name = "gpgme"; + c_i_gpgme.desc = "GPG Made Easy"; + c_i_gpgme.version = context->gpgme_version; + c_i_gpgme.path = "Embedded In"; + c_i_gpgme.binary_checksum = "/"; + + GpgComponentInfo c_i_gpgconf; + c_i_gpgconf.name = "gpgconf"; + c_i_gpgconf.desc = "GPG Configure"; + c_i_gpgconf.version = "/"; + c_i_gpgconf.path = context->gpgconf_path; + auto gpgconf_binary_checksum = CalculateBinaryChacksum(context->gpgconf_path); + c_i_gpgconf.binary_checksum = + (gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value() + : QString("/")); + + component_infos.push_back(c_i_gpgme); + component_infos.push_back(c_i_gpgconf); + + auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); + auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgme"), + GFModuleStrDup(QJsonDocument(jsonlized_gpgme_component_info).toJson())); + GFModuleUpsertRTValue( + GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgconf"), + GFModuleStrDup(QJsonDocument(jsonlized_gpgconf_component_info).toJson())); + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + if (info_split_list.size() != 3) continue; + + auto component_name = info_split_list[0].trimmed(); + auto component_desc = info_split_list[1].trimmed(); + auto component_path = info_split_list[2].trimmed(); + +#ifdef WINDOWS + // replace some special substrings on windows + // platform + component_path.replace("%3a", ":"); +#endif + + auto binary_checksum = CalculateBinaryChacksum(component_path); + + GFModuleLogDebug( + fmt::format("gnupg component name: {} desc: " + "{} checksum: {} path: {} ", + component_name, component_desc, + binary_checksum.has_value() ? binary_checksum.value() : "/", + component_path) + .c_str()); + + QString version = "/"; + + if (component_name == "gpg") { + version = GFModuleRetrieveRTValueOrDefault( + GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gnupg_version"), + GFModuleStrDup("2.0.0")); + } + if (component_name == "gpg-agent") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.gpg_agent_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + if (component_name == "dirmngr") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.dirmngr_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + if (component_name == "keyboxd") { + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("gnupg.keyboxd_path"), + GFModuleStrDup(QString(component_path).toUtf8())); + } + + { + GpgComponentInfo c_i; + c_i.name = component_name; + c_i.desc = component_desc; + c_i.version = version; + c_i.path = component_path; + c_i.binary_checksum = + (binary_checksum.has_value() ? binary_checksum.value() + : QString("/")); + + auto const jsonlized_component_info = c_i.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup( + QString("gnupg.components.%1").arg(component_name).toUtf8()), + GFModuleStrDup(QJsonDocument(jsonlized_component_info).toJson())); + + component_infos.push_back(c_i); + } + + GFModuleLogDebug("load gnupg component info actually done."); + } +} + +void GetGpgDirectoryInfos(void *, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; + + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + GFModuleLogDebug(fmt::format("gpgconf direcrotries info line: " + "{} info size: {}", + line, info_split_list.size()) + .c_str()); + + if (info_split_list.size() != 2) continue; + + auto configuration_name = info_split_list[0].trimmed(); + auto configuration_value = info_split_list[1].trimmed(); + +#ifdef WINDOWS + // replace some special substrings on windows + // platform + configuration_value.replace("%3a", ":"); +#endif + + // record gnupg home path + if (configuration_name == "homedir") { + GFModuleUpsertRTValue(GFGetModuleID(), GFModuleStrDup("gnupg.home_path"), + GFModuleStrDup(configuration_value.toUtf8())); + } + + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup( + QString("gnupg.dirs.%1").arg(configuration_name).toUtf8()), + GFModuleStrDup(configuration_value.toUtf8())); + } +} + +void GetGpgOptionInfos(void *data, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; + + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto *context = reinterpret_cast<Context *>(data); + auto component_name = context->component_info.name; + + GFModuleLogDebug(fmt::format("gpgconf {} avaliable options " + "exit_code: {} process stdout " + "size: {} ", + component_name, exit_code, p_out.size()) + .c_str()); + + std::vector<GpgOptionsInfo> options_infos; + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + GFModuleLogDebug(fmt::format("component {} avaliable options " + "line: {} info size: {}", + component_name, line, info_split_list.size()) + .c_str()); + + if (info_split_list.size() < 10) continue; + + // The format of each line is: + // name:flags:level:description:type:alt-type:argname:default:argdef:value + + auto option_name = info_split_list[0].trimmed(); + auto option_flags = info_split_list[1].trimmed(); + auto option_level = info_split_list[2].trimmed(); + auto option_desc = info_split_list[3].trimmed(); + auto option_type = info_split_list[4].trimmed(); + auto option_alt_type = info_split_list[5].trimmed(); + auto option_argname = info_split_list[6].trimmed(); + auto option_default = info_split_list[7].trimmed(); + auto option_argdef = info_split_list[8].trimmed(); + auto option_value = info_split_list[9].trimmed(); + + GpgOptionsInfo info; + info.name = option_name; + info.flags = option_flags; + info.level = option_level; + info.description = option_desc; + info.type = option_type; + info.alt_type = option_alt_type; + info.argname = option_argname; + info.default_value = option_default; + info.argdef = option_argdef; + info.value = option_value; + + auto const jsonlized_option_info = info.Json(); + GFModuleUpsertRTValue( + GFGetModuleID(), + GFModuleStrDup(QString("gnupg.components.%1.options.%2") + .arg(component_name) + .arg(option_name) + .toUtf8()), + GFModuleStrDup(QJsonDocument(jsonlized_option_info).toJson())); + options_infos.push_back(info); + } + + context->~Context(); + GFFreeMemory(context); +} diff --git a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.h b/src/module/mods/gpg_info/GnuPGInfoGatheringModule.h new file mode 100644 index 00000000..35ee4ac3 --- /dev/null +++ b/src/module/mods/gpg_info/GnuPGInfoGatheringModule.h @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include <GFSDKModule.h> + +#include "GFModuleExport.h" + +extern "C" { + +auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; + +auto GF_MODULE_EXPORT GFRegisterModule() -> int; + +auto GF_MODULE_EXPORT GFActiveModule() -> int; + +auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; + +auto GF_MODULE_EXPORT GFDeactiveModule() -> int; + +auto GF_MODULE_EXPORT GFUnregisterModule() -> int; +}; diff --git a/src/module/integrated/gnupg_info_gathering_module/GpgInfo.cpp b/src/module/mods/gpg_info/GpgInfo.cpp index 2015bc0a..680f4a8a 100644 --- a/src/module/integrated/gnupg_info_gathering_module/GpgInfo.cpp +++ b/src/module/mods/gpg_info/GpgInfo.cpp @@ -26,9 +26,7 @@ * */ -#include "module/integrated/gnupg_info_gathering_module/GpgInfo.h" - -namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule { +#include "GpgInfo.h" GpgOptionsInfo::GpgOptionsInfo(const QJsonObject &j) { if (const auto v = j["name"]; v.isString()) name = v.toString(); @@ -38,8 +36,9 @@ GpgOptionsInfo::GpgOptionsInfo(const QJsonObject &j) { if (const auto v = j["type"]; v.isString()) type = v.toString(); if (const auto v = j["alt_type"]; v.isString()) alt_type = v.toString(); if (const auto v = j["argname"]; v.isString()) argname = v.toString(); - if (const auto v = j["default_value"]; v.isString()) + if (const auto v = j["default_value"]; v.isString()) { default_value = v.toString(); + } if (const auto v = j["argdef"]; v.isString()) argdef = v.toString(); if (const auto v = j["value"]; v.isString()) value = v.toString(); } @@ -74,7 +73,7 @@ GpgComponentInfo::GpgComponentInfo(const QJsonObject &j) { if (const auto v = j["desc"]; v.isString()) desc = v.toString(); if (const auto v = j["version"]; v.isString()) version = v.toString(); if (const auto v = j["path"]; v.isString()) path = v.toString(); - if (const auto v = j["binary_checksum"]; v.isString()) + if (const auto v = j["binary_checksum"]; v.isString()) { binary_checksum = v.toString(); + } } -} // namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule diff --git a/src/module/integrated/gnupg_info_gathering_module/GpgInfo.h b/src/module/mods/gpg_info/GpgInfo.h index fb12b811..1aacc207 100644 --- a/src/module/integrated/gnupg_info_gathering_module/GpgInfo.h +++ b/src/module/mods/gpg_info/GpgInfo.h @@ -28,7 +28,10 @@ #pragma once -namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule { +#include <QJsonObject> +#include <QString> +#include <map> + /** * @brief Use to record some info about gnupg * @@ -83,5 +86,3 @@ struct GpgOptionsInfo { [[nodiscard]] auto Json() const -> QJsonObject; }; - -} // namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule diff --git a/src/core/log/QtLoggerFmt.h b/src/module/mods/gpg_info/QtLoggerFmt.h index e7ac2c82..23997465 100644 --- a/src/core/log/QtLoggerFmt.h +++ b/src/module/mods/gpg_info/QtLoggerFmt.h @@ -28,6 +28,10 @@ #pragma once +#include <spdlog/spdlog.h> + +#include <QString> + template <> struct fmt::formatter<QString> { // Parses format specifications. diff --git a/src/module/integrated/version_checking_module/CMakeLists.txt b/src/module/mods/ver_check/CMakeLists.txt index 76459b0e..b07a499a 100644 --- a/src/module/integrated/version_checking_module/CMakeLists.txt +++ b/src/module/mods/ver_check/CMakeLists.txt @@ -23,39 +23,54 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# com.bktus.gpgfrontend.module.integrated.version-checking +# com.bktus.gpgfrontend.module.integrated.version_checking aux_source_directory(. INTEGRATED_MODULE_SOURCE) # define libgpgfrontend_module -add_library(gpgfrontend_integrated_module_version_checking SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendModuleExport.h") -generate_export_header(gpgfrontend_integrated_module_version_checking EXPORT_FILE_NAME "${_export_file}") +add_library(mod_ver_check SHARED ${INTEGRATED_MODULE_SOURCE}) +set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") +generate_export_header(mod_ver_check + BASE_NAME "GF_MODULE" + EXPORT_FILE_NAME "${_export_file}") + +target_include_directories(mod_ver_check PRIVATE + ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + +# set output directory +set_target_properties(mod_ver_check PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods) if (XCODE_BUILD) - set_target_properties(gpgfrontend_integrated_module_version_checking + set_target_properties(mod_ver_check PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") endif () +if (LINUX AND LINUX_INSTALL_SOFTWARE) + install(TARGETS mod_ver_check + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/mods/") +endif() + # link sdk -target_link_libraries(gpgfrontend_integrated_module_version_checking PRIVATE - gpgfrontend_module_sdk) +target_link_libraries(mod_ver_check PRIVATE + gpgfrontend_module_sdk) if(GPGFRONTEND_QT5_BUILD) # link Qt - target_link_libraries(gpgfrontend_integrated_module_version_checking PUBLIC Qt5::Network) + target_link_libraries(mod_ver_check PUBLIC Qt5::Core Qt5::Network) else() # link Qt - target_link_libraries(gpgfrontend_integrated_module_version_checking PUBLIC Qt6::Network) + target_link_libraries(mod_ver_check PUBLIC Qt6::Core Qt6::Network) endif() # property -set_property(TARGET gpgfrontend_integrated_module_version_checking PROPERTY AUTOMOC ON) +set_property(TARGET mod_ver_check PROPERTY AUTOMOC ON) # using std c++ 17 -target_compile_features(gpgfrontend_integrated_module_version_checking PRIVATE cxx_std_17)
\ No newline at end of file +target_compile_features(mod_ver_check PRIVATE cxx_std_17)
\ No newline at end of file diff --git a/src/module/mods/ver_check/GFModuleExport.h b/src/module/mods/ver_check/GFModuleExport.h new file mode 100644 index 00000000..ce663b5f --- /dev/null +++ b/src/module/mods/ver_check/GFModuleExport.h @@ -0,0 +1,42 @@ + +#ifndef GF_MODULE_EXPORT_H +#define GF_MODULE_EXPORT_H + +#ifdef GF_MODULE_STATIC_DEFINE +# define GF_MODULE_EXPORT +# define GF_MODULE_NO_EXPORT +#else +# ifndef GF_MODULE_EXPORT +# ifdef mod_ver_check_EXPORTS + /* We are building this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define GF_MODULE_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef GF_MODULE_NO_EXPORT +# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef GF_MODULE_DEPRECATED +# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef GF_MODULE_DEPRECATED_EXPORT +# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED +#endif + +#ifndef GF_MODULE_DEPRECATED_NO_EXPORT +# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef GF_MODULE_NO_DEPRECATED +# define GF_MODULE_NO_DEPRECATED +# endif +#endif + +#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/module/mods/ver_check/QtLoggerFmt.h b/src/module/mods/ver_check/QtLoggerFmt.h new file mode 100644 index 00000000..23997465 --- /dev/null +++ b/src/module/mods/ver_check/QtLoggerFmt.h @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include <spdlog/spdlog.h> + +#include <QString> + +template <> +struct fmt::formatter<QString> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter<QByteArray> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; diff --git a/src/module/mods/ver_check/SoftwareVersion.cpp b/src/module/mods/ver_check/SoftwareVersion.cpp new file mode 100644 index 00000000..cd864195 --- /dev/null +++ b/src/module/mods/ver_check/SoftwareVersion.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "SoftwareVersion.h" + +#include <GFSDKBasic.h> +#include <GFSDKExtra.h> +#include <GFSDKLog.h> +#include <spdlog/spdlog.h> + +#include <QString> + +template <> +struct fmt::formatter<QString> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QString& qstr, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + QByteArray utf8_array = qstr.toUtf8(); + return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); + } +}; + +template <> +struct fmt::formatter<QByteArray> { + // Parses format specifications. + constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + // Formats the QString qstr and writes it to the output. + template <typename FormatContext> + auto format(const QByteArray& qarray, FormatContext& ctx) const + -> decltype(ctx.out()) { + // Convert QString to UTF-8 QString (to handle Unicode characters + // correctly) + return fmt::format_to(ctx.out(), "{}", qarray.constData()); + } +}; + +auto SoftwareVersion::NeedUpgrade() const -> bool { + GFModuleLogDebug( + fmt::format( + "compair version current {} latest {}, result {}", current_version, + latest_version, + GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), + GFModuleStrDup(latest_version.toUtf8()))) + .c_str()); + + GFModuleLogDebug(fmt::format("load done: {}, pre-release: {}, draft: {}", + loading_done, + latest_prerelease_version_from_remote, + latest_draft_from_remote) + .c_str()); + return loading_done && !latest_prerelease_version_from_remote && + !latest_draft_from_remote && + GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), + GFModuleStrDup(latest_version.toUtf8())) < 0; +} + +auto SoftwareVersion::VersionWithdrawn() const -> bool { + return loading_done && !current_version_publish_in_remote && + current_version_is_a_prerelease && !current_version_is_drafted; +} + +auto SoftwareVersion::CurrentVersionReleased() const -> bool { + return loading_done && current_version_publish_in_remote; +}
\ No newline at end of file diff --git a/src/module/integrated/version_checking_module/SoftwareVersion.h b/src/module/mods/ver_check/SoftwareVersion.h index 43f718fa..6b05d413 100644 --- a/src/module/integrated/version_checking_module/SoftwareVersion.h +++ b/src/module/mods/ver_check/SoftwareVersion.h @@ -28,9 +28,8 @@ #pragma once -#include <module/sdk/GpgFrontendModuleSDK.h> +#include <QString> -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { /** * @brief * @@ -53,7 +52,7 @@ struct SoftwareVersion { * @return true * @return false */ - [[nodiscard]] bool InfoValid() const { return loading_done; } + [[nodiscard]] auto InfoValid() const -> bool { return loading_done; } /** * @brief @@ -61,7 +60,7 @@ struct SoftwareVersion { * @return true * @return false */ - [[nodiscard]] bool NeedUpgrade() const; + [[nodiscard]] auto NeedUpgrade() const -> bool; /** * @brief @@ -69,7 +68,7 @@ struct SoftwareVersion { * @return true * @return false */ - [[nodiscard]] bool VersionWithdrawn() const; + [[nodiscard]] auto VersionWithdrawn() const -> bool; /** * @brief @@ -77,9 +76,8 @@ struct SoftwareVersion { * @return true * @return false */ - [[nodiscard]] bool CurrentVersionReleased() const; + [[nodiscard]] auto CurrentVersionReleased() const -> bool; private: - static int version_compare(const QString& a, const QString& b); + static auto version_compare(const QString& a, const QString& b) -> int; }; -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule diff --git a/src/module/integrated/version_checking_module/VersionCheckTask.cpp b/src/module/mods/ver_check/VersionCheckTask.cpp index 83844af8..5ea9c48e 100644 --- a/src/module/integrated/version_checking_module/VersionCheckTask.cpp +++ b/src/module/mods/ver_check/VersionCheckTask.cpp @@ -28,30 +28,30 @@ #include "VersionCheckTask.h" +#include <GFSDKBasic.h> +#include <GFSDKExtra.h> +#include <GFSDKLog.h> + #include <QMetaType> #include <QtNetwork> -#include "GpgFrontendBuildInfo.h" - -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { - VersionCheckTask::VersionCheckTask() - : Task("version_check_task"), - network_manager_(new QNetworkAccessManager(this)), - current_version_(QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + - "." + VERSION_PATCH) { - HoldOnLifeCycle(true); + : network_manager_(new QNetworkAccessManager(this)), + current_version_(GFProjectVersion()) { qRegisterMetaType<SoftwareVersion>("SoftwareVersion"); version_.current_version = current_version_; } auto VersionCheckTask::Run() -> int { - MODULE_LOG_DEBUG("current project version: {}", current_version_); + GFModuleLogDebug( + fmt::format("current project version: {}", current_version_).c_str()); QString latest_version_url = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - QNetworkRequest latest_request; - latest_request.setUrl(QUrl(latest_version_url)); + QNetworkRequest latest_request(latest_version_url); + latest_request.setHeader(QNetworkRequest::UserAgentHeader, + GFHttpRequestUserAgent()); + latest_reply_ = network_manager_->get(latest_request); connect(latest_reply_, &QNetworkReply::finished, this, &VersionCheckTask::slot_parse_latest_version_info); @@ -63,8 +63,9 @@ void VersionCheckTask::slot_parse_latest_version_info() { version_.latest_version = current_version_; version_.loading_done = false; } else if (latest_reply_->error() != QNetworkReply::NoError) { - MODULE_LOG_ERROR("latest version request error: ", - latest_reply_->errorString()); + GFModuleLogError(fmt::format("latest version request error: ", + latest_reply_->errorString()) + .c_str()); version_.latest_version = current_version_; } else { latest_reply_bytes_ = latest_reply_->readAll(); @@ -77,11 +78,15 @@ void VersionCheckTask::slot_parse_latest_version_info() { auto version_match = re.match(latest_version); if (version_match.hasMatch()) { latest_version = version_match.captured(0); - MODULE_LOG_INFO("latest version from github: {}", latest_version); + GFModuleLogInfo(fmt::format("latest released version from github: {}", + latest_version) + .c_str()); } else { latest_version = current_version_; - MODULE_LOG_WARN("latest version unknown, set to current version: {}", - current_version_); + GFModuleLogWarn( + fmt::format("latest version unknown, set to current version: {}", + current_version_) + .c_str()); } bool prerelease = latest_reply_json["prerelease"].toBool(); @@ -94,8 +99,9 @@ void VersionCheckTask::slot_parse_latest_version_info() { version_.publish_date = publish_date; version_.release_note = release_note; } else { - MODULE_LOG_WARN("cannot parse data got from github: {}", - latest_reply_bytes_); + GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", + latest_reply_bytes_) + .c_str()); } } @@ -107,17 +113,20 @@ void VersionCheckTask::slot_parse_latest_version_info() { QString current_version_url = "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + current_version_; - MODULE_LOG_DEBUG("current version info query url: {}", current_version_url); + GFModuleLogDebug( + fmt::format("current version info query url: {}", current_version_url) + .c_str()); + + QNetworkRequest current_request(current_version_url); + current_request.setHeader(QNetworkRequest::UserAgentHeader, + GFHttpRequestUserAgent()); - QNetworkRequest current_request; - current_request.setUrl(QUrl(current_version_url)); current_reply_ = network_manager_->get(current_request); connect(current_reply_, &QNetworkReply::finished, this, &VersionCheckTask::slot_parse_current_version_info); } catch (...) { - MODULE_LOG_ERROR("current version request create error"); - emit SignalTaskShouldEnd(-1); + GFModuleLogError("current version request create error"); } } @@ -127,8 +136,9 @@ void VersionCheckTask::slot_parse_current_version_info() { version_.loading_done = false; } else if (current_reply_->error() != QNetworkReply::NoError) { - MODULE_LOG_ERROR("current version request network error: {}", - current_reply_->errorString()); + GFModuleLogError(fmt::format("current version request network error: {}", + current_reply_->errorString()) + .c_str()); // loading done version_.loading_done = true; @@ -146,17 +156,16 @@ void VersionCheckTask::slot_parse_current_version_info() { // loading done version_.loading_done = true; } else { - MODULE_LOG_WARN("cannot parse data got from github: {}", - current_reply_bytes_); + GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", + current_reply_bytes_) + .c_str()); } } - MODULE_LOG_DEBUG("current version parse done: {}", - version_.current_version_publish_in_remote); + GFModuleLogDebug(fmt::format("current version parse done: {}", + version_.current_version_publish_in_remote) + .c_str()); if (current_reply_ != nullptr) current_reply_->deleteLater(); emit SignalUpgradeVersion(version_); - emit SignalTaskShouldEnd(0); } - -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule diff --git a/src/module/integrated/version_checking_module/VersionCheckTask.h b/src/module/mods/ver_check/VersionCheckTask.h index f5091819..df801570 100644 --- a/src/module/integrated/version_checking_module/VersionCheckTask.h +++ b/src/module/mods/ver_check/VersionCheckTask.h @@ -29,20 +29,17 @@ #pragma once #include <core/thread/Task.h> -#include <module/sdk/GpgFrontendModuleSDK.h> #include "SoftwareVersion.h" class QNetworkReply; class QNetworkAccessManager; -namespace GpgFrontend::Module::Integrated::VersionCheckingModule { - /** * @brief * */ -class VersionCheckTask : public Thread::Task { +class VersionCheckTask : public QObject { Q_OBJECT public: /** @@ -51,22 +48,21 @@ class VersionCheckTask : public Thread::Task { */ VersionCheckTask(); - signals: - /** * @brief * - * @param version + * @return int */ - void SignalUpgradeVersion(SoftwareVersion version); + auto Run() -> int; + + signals: - protected: /** * @brief - * + * @param version */ - auto Run() -> int override; + void SignalUpgradeVersion(SoftwareVersion version); private slots: @@ -91,6 +87,3 @@ class VersionCheckTask : public Thread::Task { QString current_version_; SoftwareVersion version_; }; - -} // namespace GpgFrontend::Module::Integrated::VersionCheckingModule - // GpgFrontend::Module::Custom::IntegradedModule::VersionCheckingModule diff --git a/src/module/mods/ver_check/VersionCheckingModule.cpp b/src/module/mods/ver_check/VersionCheckingModule.cpp new file mode 100644 index 00000000..35d3b82e --- /dev/null +++ b/src/module/mods/ver_check/VersionCheckingModule.cpp @@ -0,0 +1,164 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "VersionCheckingModule.h" + +#include <GFSDKBasic.h> +#include <GFSDKBuildInfo.h> +#include <GFSDKExtra.h> +#include <GFSDKLog.h> +#include <spdlog/spdlog.h> + +#include <QMetaType> +#include <QtNetwork> + +#include "SoftwareVersion.h" +#include "VersionCheckTask.h" + +extern void VersionCheckDone(const SoftwareVersion& version); + +auto GFGetModuleGFSDKVersion() -> const char* { + return GFModuleStrDup(GF_SDK_VERSION_STR); +} + +auto GFGetModuleQtEnvVersion() -> const char* { + return GFModuleStrDup(QT_VERSION_STR); +} + +auto GFGetModuleID() -> const char* { + return GFModuleStrDup("com.bktus.gpgfrontend.module.version_checking"); +} + +auto GFGetModuleVersion() -> const char* { return GFModuleStrDup("1.0.0"); } + +auto GFGetModuleMetaData() -> GFModuleMetaData* { + auto* p_meta = static_cast<GFModuleMetaData*>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + auto* h_meta = p_meta; + + p_meta->key = "Name"; + p_meta->value = "VersionChecking"; + p_meta->next = static_cast<GFModuleMetaData*>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Description"; + p_meta->value = "Try checking gpgfrontend version"; + p_meta->next = static_cast<GFModuleMetaData*>( + GFAllocateMemory(sizeof(GFModuleMetaData))); + p_meta = p_meta->next; + + p_meta->key = "Author"; + p_meta->value = "Saturneric"; + p_meta->next = nullptr; + + return h_meta; +} + +auto GFRegisterModule() -> int { + GFModuleLogInfo("version checking module registering"); + return 0; +} + +auto GFActiveModule() -> int { + GFModuleLogInfo("version checking module activating"); + + GFModuleListenEvent(GFGetModuleID(), GFModuleStrDup("APPLICATION_LOADED")); + GFModuleListenEvent(GFGetModuleID(), + GFModuleStrDup("CHECK_APPLICATION_VERSION")); + return 0; +} + +auto GFExecuteModule(GFModuleEvent* event) -> int { + GFModuleLogInfo( + fmt::format("version checking module executing, event id: {}", event->id) + .c_str()); + + auto* task = new VersionCheckTask(); + QObject::connect( + task, &VersionCheckTask::SignalUpgradeVersion, QThread::currentThread(), + [event](const SoftwareVersion& version) { + VersionCheckDone(version); + + char** event_argv = + static_cast<char**>(GFAllocateMemory(sizeof(char**) * 1)); + event_argv[0] = GFModuleStrDup("0"); + + GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, + event_argv); + }); + QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, task, + &QObject::deleteLater); + task->Run(); + + return 0; +} + +auto GFDeactiveModule() -> int { return 0; } + +auto GFUnregisterModule() -> int { return 0; } + +void VersionCheckDone(const SoftwareVersion& version) { + GFModuleLogDebug("filling software information info in rt..."); + + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("version.current_version"), + GFModuleStrDup(version.current_version.toUtf8())); + GFModuleUpsertRTValue(GFGetModuleID(), + GFModuleStrDup("version.latest_version"), + GFModuleStrDup(version.latest_version.toUtf8())); + GFModuleUpsertRTValueBool( + GFGetModuleID(), GFModuleStrDup("version.current_version_is_drafted"), + version.current_version_is_drafted ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.current_version_is_a_prerelease"), + version.current_version_is_a_prerelease ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.current_version_publish_in_remote"), + version.current_version_publish_in_remote ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), + GFModuleStrDup("version.latest_prerelease_version_from_remote"), + version.latest_prerelease_version_from_remote ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.need_upgrade"), + version.NeedUpgrade() ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.current_version_released"), + version.CurrentVersionReleased() ? 1 : 0); + GFModuleUpsertRTValueBool( + GFGetModuleID(), GFModuleStrDup("version.current_a_withdrawn_version"), + version.VersionWithdrawn() ? 1 : 0); + GFModuleUpsertRTValueBool(GFGetModuleID(), + GFModuleStrDup("version.loading_done"), + version.loading_done ? 1 : 0); + + GFModuleLogDebug("software information filled in rt"); +} diff --git a/src/module/mods/ver_check/VersionCheckingModule.h b/src/module/mods/ver_check/VersionCheckingModule.h new file mode 100644 index 00000000..35ee4ac3 --- /dev/null +++ b/src/module/mods/ver_check/VersionCheckingModule.h @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include <GFSDKModule.h> + +#include "GFModuleExport.h" + +extern "C" { + +auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; + +auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; + +auto GF_MODULE_EXPORT GFRegisterModule() -> int; + +auto GF_MODULE_EXPORT GFActiveModule() -> int; + +auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; + +auto GF_MODULE_EXPORT GFDeactiveModule() -> int; + +auto GF_MODULE_EXPORT GFUnregisterModule() -> int; +}; diff --git a/src/module/sdk/GFSDK.h b/src/module/sdk/GFSDK.h new file mode 100644 index 00000000..77e019af --- /dev/null +++ b/src/module/sdk/GFSDK.h @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "GFSDKExport.h" + +extern "C" { + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogTrace(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogDebug(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogInfo(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogWarn(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogError(const char*); +}
\ No newline at end of file diff --git a/src/module/sdk/GFSDKBasic.cpp b/src/module/sdk/GFSDKBasic.cpp new file mode 100644 index 00000000..4d8af6c8 --- /dev/null +++ b/src/module/sdk/GFSDKBasic.cpp @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GFSDKBasic.h" + +#include "core/function/SecureMemoryAllocator.h" +#include "core/function/gpg/GpgCommandExecutor.h" +#include "core/utils/BuildInfoUtils.h" +#include "core/utils/CommonUtils.h" + +auto GFAllocateMemory(uint32_t size) -> void* { + return GpgFrontend::SecureMemoryAllocator::Allocate(size); +} + +void GFFreeMemory(void* ptr) { + return GpgFrontend::SecureMemoryAllocator::Deallocate(ptr); +} + +auto GFProjectVersion() -> const char* { + return GpgFrontend::GFStrDup(GpgFrontend::GetProjectVersion()); +} + +auto GFQtEnvVersion() -> const char* { + return GpgFrontend::GFStrDup(QT_VERSION_STR); +} + +void GFExecuteCommandSync(const char* cmd, int32_t argc, const char** argv, + GFCommandExeucteCallback cb, void* data) { + QStringList args; + for (int i = 0; i < argc; i++) { + args.append(GpgFrontend::GFUnStrDup(argv[i])); + } + + GpgFrontend::GpgCommandExecutor::ExecuteContext const context{ + cmd, args, [=](int exit_code, const QString& out, const QString& err) { + cb(data, exit_code, out.toUtf8(), err.toUtf8()); + }}; + + GpgFrontend::GpgCommandExecutor::ExecuteSync(context); +} + +void GFExecuteCommandBatchSync(int32_t context_size, + const GFCommandExecuteContext* context) { + QList<GpgFrontend::GpgCommandExecutor::ExecuteContext> contexts; + + for (int i = 0; i < context_size; i++) { + const auto& exec_context = context[i]; + + QStringList args; + const char** argv = exec_context.argv; + for (int j = 0; j < exec_context.argc; j++) { + args.append(GpgFrontend::GFUnStrDup(argv[j])); + } + + contexts.append( + {exec_context.cmd, args, + [data = exec_context.data, cb = exec_context.cb]( + int exit_code, const QString& out, const QString& err) { + cb(data, exit_code, out.toUtf8(), err.toUtf8()); + }}); + } + + GpgFrontend::GpgCommandExecutor::ExecuteConcurrentlySync(contexts); +} + +auto StrlenSafe(const char* str, size_t max_len) -> size_t { + const char* end = static_cast<const char*>(memchr(str, '\0', max_len)); + if (end == nullptr) return max_len; + return end - str; +} + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char* src) -> char* { + auto len = StrlenSafe(src, kGfStrlenMax); + if (len > kGfStrlenMax) return nullptr; + + char* dst = static_cast<char*>(GFAllocateMemory((len + 1) * sizeof(char))); + memcpy(dst, src, len); + dst[len] = '\0'; + + return dst; +}
\ No newline at end of file diff --git a/src/module/sdk/GFSDKBasic.h b/src/module/sdk/GFSDKBasic.h new file mode 100644 index 00000000..07ff6ed7 --- /dev/null +++ b/src/module/sdk/GFSDKBasic.h @@ -0,0 +1,107 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include <cstddef> +#include <cstdint> + +#include "GFSDKExport.h" + +extern "C" { + +constexpr int32_t kGfStrlenMax = static_cast<const int32_t>(1024 * 8); + +using GFCommandExeucteCallback = void (*)(void* data, int errcode, + const char* out, const char* err); + +using GFCommandExecuteContext = struct { + const char* cmd; + int32_t argc; + const char** argv; + GFCommandExeucteCallback cb; + void* data; +}; + +/** + * @brief + * + * @param size + * @return void* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFAllocateMemory(uint32_t size) -> void*; + +/** + * @brief + * + * @return const char* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFProjectVersion() -> const char*; + +/** + * @brief + * + * @return const char* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFQtEnvVersion() -> const char*; + +/** + * @brief + * + */ +void GPGFRONTEND_MODULE_SDK_EXPORT GFFreeMemory(void*); + +/** + * @brief + * + * @param cmd + * @param argc + * @param argv + * @param cb + * @param data + */ +void GPGFRONTEND_MODULE_SDK_EXPORT +GFExecuteCommandSync(const char* cmd, int32_t argc, const char** argv, + GFCommandExeucteCallback cb, void* data); + +/** + * @brief + * + * @param context_size + * @param context + */ +void GPGFRONTEND_MODULE_SDK_EXPORT GFExecuteCommandBatchSync( + int32_t context_size, const GFCommandExecuteContext* context); + +/** + * @brief + * + * @return char* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char*) -> char*; +}
\ No newline at end of file diff --git a/src/module/sdk/Basic.h b/src/module/sdk/GFSDKBuildInfo.h index 62a547b3..a64d95c5 100644 --- a/src/module/sdk/Basic.h +++ b/src/module/sdk/GFSDKBuildInfo.h @@ -28,9 +28,9 @@ #pragma once -namespace GpgFrontend::Module::SDK { +#define GF_SDK_VERSION_MAJOR "2" +#define GF_SDK_VERSION_MINOR "1" +#define GF_SDK_VERSION_PATCH "3" - - - -}
\ No newline at end of file +#define GF_SDK_VERSION_STR \ + GF_SDK_VERSION_MAJOR "." GF_SDK_VERSION_MINOR "." GF_SDK_VERSION_PATCH diff --git a/src/module/sdk/GpgFrontendModuleSDK.h b/src/module/sdk/GFSDKBuildInfo.h.in index 97769462..508c35d4 100644 --- a/src/module/sdk/GpgFrontendModuleSDK.h +++ b/src/module/sdk/GFSDKBuildInfo.h.in @@ -28,6 +28,9 @@ #pragma once -#include <core/module/GpgFrontendModuleSystem.h> -#include <module/sdk/GpgFrontendModuleSDKExport.h> -#include <module/sdk/Log.h>
\ No newline at end of file +#define GF_SDK_VERSION_MAJOR "@CMAKE_PROJECT_VERSION_MAJOR@" +#define GF_SDK_VERSION_MINOR "@CMAKE_PROJECT_VERSION_MINOR@" +#define GF_SDK_VERSION_PATCH "@CMAKE_PROJECT_VERSION_PATCH@" + +#define GF_SDK_VERSION_STR \ + GF_SDK_VERSION_MAJOR "." GF_SDK_VERSION_MINOR "." GF_SDK_VERSION_PATCH
\ No newline at end of file diff --git a/src/module/sdk/GpgFrontendModuleSDKExport.h b/src/module/sdk/GFSDKExport.h index a62168bc..a62168bc 100644 --- a/src/module/sdk/GpgFrontendModuleSDKExport.h +++ b/src/module/sdk/GFSDKExport.h diff --git a/src/module/sdk/Log.cpp b/src/module/sdk/GFSDKExtra.cpp index 384fac1d..bbfa8575 100644 --- a/src/module/sdk/Log.cpp +++ b/src/module/sdk/GFSDKExtra.cpp @@ -26,11 +26,17 @@ * */ -#include "Log.h" +#include "GFSDKExtra.h" +#include "core/utils/BuildInfoUtils.h" +#include "core/utils/CommonUtils.h" -#include <stdexcept> - -#include "core/function/GlobalSettingStation.h" - -namespace GpgFrontend::Module::SDK {} // namespace GpgFrontend::Module::SDK +auto GFCompareSoftwareVersion(const char *current_version, + const char *latest_version) -> int { + return GpgFrontend::GFCompareSoftwareVersion( + GpgFrontend::GFUnStrDup(current_version), + GpgFrontend::GFUnStrDup(latest_version)); +} +auto GFHttpRequestUserAgent() -> const char * { + return GpgFrontend::GFStrDup(GpgFrontend::GetHttpRequestUserAgent()); +}
\ No newline at end of file diff --git a/src/module/GpgFrontendModule.h b/src/module/sdk/GFSDKExtra.h index cf7d8557..3d7f4226 100644 --- a/src/module/GpgFrontendModule.h +++ b/src/module/sdk/GFSDKExtra.h @@ -28,9 +28,12 @@ #pragma once -/** - * Project internal dependencies - */ -#include "GpgFrontend.h" -#include "GpgFrontendModuleExport.h" -#include "core/GpgFrontendCore.h" +#include "GFSDKExport.h" + +extern "C" { + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFCompareSoftwareVersion( + const char *current_version, const char *latest_version) -> int; + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFHttpRequestUserAgent() -> const char *; +}
\ No newline at end of file diff --git a/src/module/sdk/Basic.cpp b/src/module/sdk/GFSDKGpg.cpp index 63859763..63859763 100644 --- a/src/module/sdk/Basic.cpp +++ b/src/module/sdk/GFSDKGpg.cpp diff --git a/src/module/sdk/UI.cpp b/src/module/sdk/GFSDKGpg.h index 63859763..8823bfc5 100644 --- a/src/module/sdk/UI.cpp +++ b/src/module/sdk/GFSDKGpg.h @@ -24,4 +24,10 @@ * * SPDX-License-Identifier: GPL-3.0-or-later * - */
\ No newline at end of file + */ + +#pragma once + +extern "C" { + +}
\ No newline at end of file diff --git a/src/module/sdk/Log.h b/src/module/sdk/GFSDKLog.cpp index 0c40a097..603cc325 100644 --- a/src/module/sdk/Log.h +++ b/src/module/sdk/GFSDKLog.cpp @@ -26,10 +26,9 @@ * */ -#pragma once +#include "GFSDKLog.h" #include "core/utils/LogUtils.h" -#include "module/sdk/GpgFrontendModuleSDK.h" #define MODULE_LOG_TRACE(...) GF_LOG_TRACE("module", __VA_ARGS__) #define MODULE_LOG_DEBUG(...) GF_LOG_DEBUG("module", __VA_ARGS__) @@ -37,35 +36,12 @@ #define MODULE_LOG_WARN(...) GF_LOG_WARN("module", __VA_ARGS__) #define MODULE_LOG_ERROR(...) GF_LOG_ERROR("module", __VA_ARGS__) -namespace spdlog { -class logger; -} +void GFModuleLogTrace(const char* l) { MODULE_LOG_TRACE(l); } -namespace GpgFrontend::Module::SDK { +void GFModuleLogDebug(const char* l) { MODULE_LOG_DEBUG(l); } -template <typename... Args> -void ModuleLogTrace(const char* fmt, const Args&... args) { - MODULE_LOG_TRACE(fmt, args...); -} +void GFModuleLogInfo(const char* l) { MODULE_LOG_INFO(l); } -template <typename... Args> -void ModuleLogDebug(const char* fmt, const Args&... args) { - MODULE_LOG_DEBUG(fmt, args...); -} +void GFModuleLogWarn(const char* l) { MODULE_LOG_WARN(l); } -template <typename... Args> -void ModuleLogInfo(const char* fmt, const Args&... args) { - MODULE_LOG_INFO(fmt, args...); -} - -template <typename... Args> -void ModuleLogWarn(const char* fmt, const Args&... args) { - MODULE_LOG_WARN(fmt, args...); -} - -template <typename... Args> -void ModuleLogError(const char* fmt, const Args&... args) { - MODULE_LOG_ERROR(fmt, args...); -} - -} // namespace GpgFrontend::Module::SDK +void GFModuleLogError(const char* l) { MODULE_LOG_ERROR(l); } diff --git a/src/module/sdk/GFSDKLog.h b/src/module/sdk/GFSDKLog.h new file mode 100644 index 00000000..77e019af --- /dev/null +++ b/src/module/sdk/GFSDKLog.h @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "GFSDKExport.h" + +extern "C" { + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogTrace(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogDebug(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogInfo(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogWarn(const char*); + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleLogError(const char*); +}
\ No newline at end of file diff --git a/src/module/sdk/GFSDKModule.cpp b/src/module/sdk/GFSDKModule.cpp new file mode 100644 index 00000000..00594488 --- /dev/null +++ b/src/module/sdk/GFSDKModule.cpp @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GFSDKModule.h" + +#include <core/module/ModuleManager.h> +#include <core/utils/CommonUtils.h> + +#include "GFSDKBasic.h" + +void GFModuleListenEvent(const char *module_id, const char *event_id) { + return GpgFrontend::Module::ModuleManager::GetInstance().ListenEvent( + GpgFrontend::GFUnStrDup(module_id).toLower(), + GpgFrontend::GFUnStrDup(event_id).toUpper()); +} + +auto GFModuleRetrieveRTValueOrDefault(const char *namespace_, const char *key, + const char *default_value) -> const + char * { + return GpgFrontend::GFStrDup( + GpgFrontend::Module::RetrieveRTValueTypedOrDefault( + GpgFrontend::GFUnStrDup(namespace_), GpgFrontend::GFUnStrDup(key), + GpgFrontend::GFUnStrDup(default_value))); +} + +void GFModuleUpsertRTValue(const char *namespace_, const char *key, + const char *vaule) { + GpgFrontend::Module::UpsertRTValue( + GpgFrontend::GFUnStrDup(namespace_).toLower(), + GpgFrontend::GFUnStrDup(key).toLower(), GpgFrontend::GFUnStrDup(vaule)); +} + +void GFModuleUpsertRTValueBool(const char *namespace_, const char *key, + int value) { + GpgFrontend::Module::UpsertRTValue( + GpgFrontend::GFUnStrDup(namespace_).toLower(), + GpgFrontend::GFUnStrDup(key).toLower(), value != 0); +} + +auto GFModuleListRTChildKeys(const char *namespace_, const char *key, + char ***child_keys) -> int32_t { + *child_keys = nullptr; + auto keys = GpgFrontend::Module::ListRTChildKeys( + GpgFrontend::GFUnStrDup(namespace_).toLower(), + GpgFrontend::GFUnStrDup(key).toLower()); + + if (keys.empty()) return 0; + + *child_keys = + static_cast<char **>(GFAllocateMemory(sizeof(char **) * keys.size())); + + for (int i = 0; i < keys.size(); i++) { + (*child_keys)[i] = GpgFrontend::GFStrDup(keys[i]); + } + + return static_cast<int32_t>(keys.size()); +} + +void GFModuleTriggerModuleEventCallback(GFModuleEvent *module_event, + const char *module_id, int argc, + char **argv) { + auto data_object = GpgFrontend::TransferParams(); + for (int i = 0; i < argc; i++) { + data_object->AppendObject(GpgFrontend::GFUnStrDup(argv[i])); + } + + auto event = GpgFrontend::Module::ModuleManager::GetInstance().SearchEvent( + GpgFrontend::GFUnStrDup(module_event->trigger_id).toLower()); + if (!event) return; + + event.value()->ExecuteCallback(GpgFrontend::GFUnStrDup(module_id), + data_object); +}
\ No newline at end of file diff --git a/src/module/sdk/GFSDKModule.h b/src/module/sdk/GFSDKModule.h new file mode 100644 index 00000000..67c1f492 --- /dev/null +++ b/src/module/sdk/GFSDKModule.h @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "GFSDKExport.h" + +extern "C" { + +#include <stdint.h> + +struct GFModuleMetaData { + const char *key; + const char *value; + GFModuleMetaData *next; +}; + +struct GFModuleEventParam { + const char *name; + const char *value; + GFModuleEventParam *next; +}; + +struct GFModuleEvent { + const char *id; + const char *trigger_id; + GFModuleEventParam *params; +}; + +using GFModuleAPIGetModuleGFSDKVersion = auto (*)() -> const char *; + +using GFModuleAPIGetModuleQtEnvVersion = auto (*)() -> const char *; + +using GFModuleAPIGetModuleID = auto (*)() -> const char *; + +using GFModuleAPIGetModuleVersion = auto (*)() -> const char *; + +using GFModuleAPIGetModuleMetaData = auto (*)() -> GFModuleMetaData *; + +using GFModuleAPIRegisterModule = auto (*)() -> int; + +using GFModuleAPIActivateModule = auto (*)() -> int; + +using GFModuleAPIExecuteModule = auto (*)(GFModuleEvent *) -> int; + +using GFModuleAPIDeactivateModule = auto (*)() -> int; + +using GFModuleAPIUnregisterModule = auto (*)() -> int; + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleListenEvent(const char *module_id, + const char *event_id); + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleRetrieveRTValueOrDefault( + const char *namespace_, const char *key, const char *default_value) -> const + char *; + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleUpsertRTValue(const char *namespace_, + const char *key, + const char *vaule); + +void GPGFRONTEND_MODULE_SDK_EXPORT +GFModuleUpsertRTValueBool(const char *namespace_, const char *key, int value); + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleListRTChildKeys( + const char *namespace_, const char *key, char ***child_keys) -> int32_t; + +void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleTriggerModuleEventCallback( + GFModuleEvent *event, const char *module_id, int argc, char **argv); +};
\ No newline at end of file diff --git a/src/module/sdk/Gpg.cpp b/src/module/sdk/GFSDKUI.cpp index 63859763..63859763 100644 --- a/src/module/sdk/Gpg.cpp +++ b/src/module/sdk/GFSDKUI.cpp diff --git a/src/module/sdk/Gpg.h b/src/module/sdk/GFSDKUI.h index 0702632a..0702632a 100644 --- a/src/module/sdk/Gpg.h +++ b/src/module/sdk/GFSDKUI.h diff --git a/src/module/sdk/UI.h b/src/module/sdk/GFSDKUtils.cpp index 0702632a..fcb510e3 100644 --- a/src/module/sdk/UI.h +++ b/src/module/sdk/GFSDKUtils.cpp @@ -26,4 +26,4 @@ * */ -#pragma once
\ No newline at end of file +#include "GFSDKUtils.h"
\ No newline at end of file diff --git a/src/module/sdk/GFSDKUtils.h b/src/module/sdk/GFSDKUtils.h new file mode 100644 index 00000000..7d72e9ee --- /dev/null +++ b/src/module/sdk/GFSDKUtils.h @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +extern "C" { + + +}
\ No newline at end of file diff --git a/src/pinentry/CMakeLists.txt b/src/pinentry/CMakeLists.txt index 3145719a..cce5fcfb 100644 --- a/src/pinentry/CMakeLists.txt +++ b/src/pinentry/CMakeLists.txt @@ -45,30 +45,18 @@ else() target_link_libraries(gpgfrontend_pinentry PUBLIC Qt6::Widgets) endif() +if (XCODE_BUILD) + set_target_properties(gpgfrontend_pinentry + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") +endif () + # spdlog target_link_libraries(gpgfrontend_pinentry PRIVATE spdlog) # using std c++ 17 target_compile_features(gpgfrontend_pinentry PUBLIC cxx_std_17) - -# link for different platforms -if (MINGW) - message(STATUS "Link GPG Static Library For MINGW") - target_link_libraries(gpgfrontend_pinentry PUBLIC wsock32) -elseif (APPLE) - message(STATUS "Link GPG Static Library For macOS") - target_link_libraries(gpgfrontend_pinentry PUBLIC dl) - if (XCODE_BUILD) - set_target_properties(gpgfrontend_pinentry - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") - endif () -else () - # linux - message(STATUS "Link GPG Static Library For Unix") - target_link_libraries(gpgfrontend_pinentry PUBLIC pthread dl) -endif () diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 3f0686e2..e6b41b50 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -36,7 +36,7 @@ aux_source_directory(thread UI_SOURCE) aux_source_directory(dialog/details UI_SOURCE) aux_source_directory(struct UI_SOURCE) aux_source_directory(dialog/import_export UI_SOURCE) -aux_source_directory(dialog/gnupg UI_SOURCE) +aux_source_directory(dialog/controller UI_SOURCE) aux_source_directory(dialog UI_SOURCE) aux_source_directory(function UI_SOURCE) @@ -54,7 +54,7 @@ if(GPGFRONTEND_QT5_BUILD) else() # link Qt target_link_libraries(gpgfrontend_ui - Qt6::Core Qt6::Widgets Qt6::Network Qt6::PrintSupport Qt6::Core5Compat) + Qt6::Core Qt6::Widgets Qt6::Network Qt6::PrintSupport) endif() diff --git a/src/ui/GpgFrontendApplication.cpp b/src/ui/GpgFrontendApplication.cpp index 1304aad5..b3c12de6 100644 --- a/src/ui/GpgFrontendApplication.cpp +++ b/src/ui/GpgFrontendApplication.cpp @@ -28,30 +28,28 @@ #include "ui/GpgFrontendApplication.h" -#include <QTextCodec> - -#include "GpgFrontendBuildInfo.h" +#include "core/utils/BuildInfoUtils.h" namespace GpgFrontend::UI { GpgFrontendApplication::GpgFrontendApplication(int &argc, char *argv[]) : QApplication(argc, argv) { -#ifndef MACOS - this->setWindowIcon(QIcon(":/icons/gpgfrontend.png")); +#if defined(DEBUG) || !defined(MACOS) + GpgFrontend::UI::GpgFrontendApplication::setWindowIcon( + QIcon(":/icons/gpgfrontend.png")); #endif // set the extra information of the build - GpgFrontendApplication::setApplicationVersion(BUILD_VERSION); - GpgFrontendApplication::setApplicationName(PROJECT_NAME); - GpgFrontendApplication::setApplicationDisplayName(PROJECT_NAME); - GpgFrontendApplication::setOrganizationName(PROJECT_NAME); + GpgFrontendApplication::setApplicationVersion(GetProjectBuildVersion()); + GpgFrontendApplication::setApplicationName(QString::fromUtf8((PROJECT_NAME))); + GpgFrontendApplication::setApplicationDisplayName( + QString::fromUtf8((PROJECT_NAME))); + GpgFrontendApplication::setOrganizationName( + QString::fromUtf8((PROJECT_NAME))); GpgFrontendApplication::setQuitOnLastWindowClosed(true); // don't show icons in menus GpgFrontendApplication::setAttribute(Qt::AA_DontShowIconsInMenus); - - // unicode in source - QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8")); } bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index 08cf012d..046c25d7 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -41,6 +41,8 @@ namespace GpgFrontend::UI { +QList<QTranslator*> registered_translators; + extern void InitUITranslations(); void WaitEnvCheckingProcess() { @@ -75,14 +77,14 @@ void WaitEnvCheckingProcess() { &QEventLoop::quit); QApplication::connect(waiting_dialog, &QProgressDialog::canceled, [=]() { - GF_UI_LOG_DEBUG("cancel clicked on wairing dialog"); + GF_UI_LOG_DEBUG("cancel clicked on waiting dialog"); QApplication::quit(); exit(0); }); auto env_state = Module::RetrieveRTValueTypedOrDefault<>("core", "env.state.basic", 0); - GF_UI_LOG_DEBUG("ui is ready to wating for env initialized, env_state: {}", + GF_UI_LOG_DEBUG("ui is ready to waiting for env initialized, env_state: {}", env_state); // check twice to avoid some unlucky sitations @@ -108,11 +110,22 @@ void InitGpgFrontendUI(QApplication* /*app*/) { // init locale InitUITranslations(); + auto settings = GlobalSettingStation::GetInstance().GetSettings(); + auto theme = settings.value("appearance/theme").toString(); + #ifdef WINDOWS - // support dark mode on windows - QApplication::setStyle("fusion"); + if (theme.isEmpty()) { + // support dark mode on windows + QApplication::setStyle(QStyleFactory::create("Fusion")); + } #endif + auto available_styles = QStyleFactory::keys(); + for (QString& s : available_styles) s = s.toLower(); + if (!theme.isEmpty() && available_styles.contains(theme)) { + QApplication::setStyle(QStyleFactory::create(theme)); + } + // register meta types qRegisterMetaType<QSharedPointer<GpgPassphraseContext> >( "QSharedPointer<GpgPassphraseContext>"); @@ -123,10 +136,8 @@ void InitGpgFrontendUI(QApplication* /*app*/) { // init common utils CommonUtils::GetInstance(); - auto settings = GlobalSettingStation::GetInstance().GetSettings(); - // application proxy configure - bool proxy_enable = settings.value("proxy/enable", false).toBool(); + auto proxy_enable = settings.value("proxy/enable", false).toBool(); // if enable proxy for application if (proxy_enable) { @@ -136,9 +147,9 @@ void InitGpgFrontendUI(QApplication* /*app*/) { QString proxy_host = settings.value("proxy/proxy_host", QString{}).toString(); int proxy_port = settings.value("prox/port", 0).toInt(); - QString proxy_username = + QString const proxy_username = settings.value("proxy/username", QString{}).toString(); - QString proxy_password = + QString const proxy_password = settings.value("proxy/password", QString{}).toString(); GF_UI_LOG_DEBUG("proxy settings: type {}, host {}, port: {}", proxy_type, proxy_host, proxy_port); @@ -191,7 +202,7 @@ auto RunGpgFrontendUI(QApplication* app) -> int { // pre-check, if application need to restart if (CommonUtils::GetInstance()->isApplicationNeedRestart()) { - GF_UI_LOG_DEBUG("application need to restart, before mian window init"); + GF_UI_LOG_DEBUG("application need to restart, before main window init"); return kDeepRestartCode; } @@ -213,31 +224,38 @@ void GPGFRONTEND_UI_EXPORT DestroyGpgFrontendUI() {} * */ void InitUITranslations() { + for (const auto& translator : registered_translators) { + QCoreApplication::removeTranslator(translator); + } + registered_translators.clear(); + auto* translator = new QTranslator(QCoreApplication::instance()); - if (translator->load(QLocale(), QLatin1String(PROJECT_NAME), - QLatin1String("."), QLatin1String(":/i18n"), - QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load target translation file done, locale: {}", + if (translator->load(QLocale(), QLatin1String("qt"), QLatin1String("_"), + QLatin1String(":/i18n_qt"), QLatin1String(".qm"))) { + GF_UI_LOG_DEBUG("load qt translation file done, locale: {}", QLocale().name()); + QCoreApplication::installTranslator(translator); + registered_translators.append(translator); } - auto* base_translation = new QTranslator(QCoreApplication::instance()); - if (base_translation->load(QLocale(), QLatin1String("qt"), QLatin1String("_"), - QLatin1String(":/i18n_qt"), - QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load qt translation file done, locale: {}", + translator = new QTranslator(QCoreApplication::instance()); + if (translator->load(QLocale(), QLatin1String("qtbase"), QLatin1String("_"), + QLatin1String(":/i18n_qt"), QLatin1String(".qm"))) { + GF_UI_LOG_DEBUG("load qtbase translation file done, locale: {}", QLocale().name()); - QCoreApplication::installTranslator(base_translation); + QCoreApplication::installTranslator(translator); + registered_translators.append(translator); } - base_translation = new QTranslator(QCoreApplication::instance()); - if (base_translation->load(QLocale(), QLatin1String("qtbase"), - QLatin1String("_"), QLatin1String(":/i18n_qt"), - QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load qtbase translation file done, locale: {}", + translator = new QTranslator(QCoreApplication::instance()); + if (translator->load(QLocale(), QLatin1String(PROJECT_NAME), + QLatin1String("."), QLatin1String(":/i18n"), + QLatin1String(".qm"))) { + GF_UI_LOG_DEBUG("load target translation file done, locale: {}", QLocale().name()); - QCoreApplication::installTranslator(base_translation); + QCoreApplication::installTranslator(translator); + registered_translators.append(translator); } } diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index ab8aeac9..806ceb9e 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -33,21 +33,22 @@ #include "core/GpgConstants.h" #include "core/function/CoreSignalStation.h" #include "core/function/gpg/GpgKeyGetter.h" +#include "core/model/CacheObject.h" #include "core/model/GpgImportInformation.h" +#include "core/model/SettingsObject.h" #include "core/module/ModuleManager.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" #include "core/typedef/GpgTypedef.h" +#include "core/utils/BuildInfoUtils.h" #include "core/utils/GpgUtils.h" #include "core/utils/IOUtils.h" #include "thread/KeyServerImportTask.h" #include "ui/UISignalStation.h" #include "ui/dialog/WaitingDialog.h" -#include "ui/dialog/gnupg/GnuPGControllerDialog.h" +#include "ui/dialog/controller/GnuPGControllerDialog.h" #include "ui/dialog/import_export/KeyServerImportDialog.h" -#include "ui/struct/CacheObject.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "ui/struct/settings_object/KeyServerSO.h" #include "ui/widgets/TextEdit.h" namespace GpgFrontend::UI { @@ -64,8 +65,8 @@ void show_verify_details(QWidget *parent, InfoBoardWidget *info_board, [=]() { VerifyDetailsDialog(parent, error, verify_result); }); } -void import_unknown_key_from_keyserver( - QWidget *parent, const GpgVerifyResultAnalyse &verify_res) { +void ImportUnknownKeyFromKeyserver( + QWidget *parent, const GpgVerifyResultAnalyse &verify_result) { QMessageBox::StandardButton reply; reply = QMessageBox::question( parent, QCoreApplication::tr("Public key not found locally"), @@ -77,7 +78,7 @@ void import_unknown_key_from_keyserver( if (reply == QMessageBox::Yes) { auto dialog = KeyServerImportDialog(parent); auto key_ids = std::make_unique<KeyIdArgsList>(); - auto *signature = verify_res.GetSignatures(); + auto *signature = verify_result.GetSignatures(); while (signature != nullptr) { GF_UI_LOG_DEBUG("signature fpr: {}", signature->fpr); key_ids->push_back(signature->fpr); @@ -428,7 +429,11 @@ void CommonUtils::SlotImportKeyFromKeyServer( GF_UI_LOG_DEBUG("request url: {}", req_url.toString()); // Waiting for reply - QNetworkReply *reply = network_manager->get(QNetworkRequest(req_url)); + auto request = QNetworkRequest(req_url); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); + + QNetworkReply *reply = network_manager->get(request); QEventLoop loop; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index 728e825f..304ba37b 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -63,7 +63,7 @@ void show_verify_details(QWidget* parent, InfoBoardWidget* info_board, * @param parent * @param verify_res */ -void import_unknown_key_from_keyserver( +void ImportUnknownKeyFromKeyserver( QWidget* parent, const GpgVerifyResultAnalyse& verify_res); /** diff --git a/src/ui/dialog/GeneralDialog.cpp b/src/ui/dialog/GeneralDialog.cpp index 386573a3..2015322f 100644 --- a/src/ui/dialog/GeneralDialog.cpp +++ b/src/ui/dialog/GeneralDialog.cpp @@ -28,8 +28,8 @@ #include "GeneralDialog.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/WindowStateSO.h" +#include "core/model/SettingsObject.h" +#include "ui/struct/settings_object/WindowStateSO.h" namespace GpgFrontend { diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp index 378a58c7..9c342cc7 100644 --- a/src/ui/dialog/SignersPicker.cpp +++ b/src/ui/dialog/SignersPicker.cpp @@ -78,7 +78,7 @@ SignersPicker::SignersPicker(QWidget* parent) } auto SignersPicker::GetCheckedSigners() -> GpgFrontend::KeyIdArgsListPtr { - return key_list_->GetPrivateChecked(); + return key_list_->GetCheckedPrivateKey(); } auto SignersPicker::GetStatus() const -> bool { return this->accepted_; } diff --git a/src/ui/dialog/SignersPicker.h b/src/ui/dialog/SignersPicker.h index c7e1bfa5..cea8dd9a 100644 --- a/src/ui/dialog/SignersPicker.h +++ b/src/ui/dialog/SignersPicker.h @@ -56,13 +56,13 @@ class SignersPicker : public GeneralDialog { * * @return GpgFrontend::KeyIdArgsListPtr */ - KeyIdArgsListPtr GetCheckedSigners(); + auto GetCheckedSigners() -> KeyIdArgsListPtr; /** * * @return */ - [[nodiscard]] bool GetStatus() const; + [[nodiscard]] auto GetStatus() const -> bool; private: KeyList* key_list_; ///< diff --git a/src/ui/dialog/Wizard.cpp b/src/ui/dialog/Wizard.cpp index 8b15e9b7..e65366dd 100644 --- a/src/ui/dialog/Wizard.cpp +++ b/src/ui/dialog/Wizard.cpp @@ -28,7 +28,6 @@ #include "Wizard.h" -#include "core/GpgModel.h" #include "core/function/GlobalSettingStation.h" namespace GpgFrontend::UI { @@ -43,10 +42,8 @@ Wizard::Wizard(QWidget* parent) : QWizard(parent) { #endif setWindowTitle(tr("First Start Wizard")); - // http://www.flickr.com/photos/laureenp/6141822934/ - setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/keys2.jpg")); - setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/logo_small.png")); - setPixmap(QWizard::BannerPixmap, QPixmap(":/icons/banner.png")); + setPixmap(QWizard::LogoPixmap, + QPixmap(":/icons/gpgfrontend_logo.png").scaled(64, 64)); int next_page_id = GlobalSettingStation::GetInstance() .GetSettings() @@ -74,10 +71,8 @@ IntroPage::IntroPage(QWidget* parent) : QWizardPage(parent) { setTitle(tr("Getting Started...")); setSubTitle(tr("... with GpgFrontend")); - auto* topLabel = new QLabel( - QString( - tr("Welcome to GpgFrontend for decrypting and signing text or " - "files!")) + + auto* top_label = new QLabel( + tr("Welcome to GpgFrontend for decrypting and signing text or files!") + " <br><br><a href='https://gpgfrontend.bktus.com'>GpgFrontend</a> " + tr("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and " "Installation-Free OpenPGP Crypto Tool. ") + @@ -86,10 +81,10 @@ IntroPage::IntroPage(QWidget* parent) : QWizardPage(parent) { tr("Overview") + "</a> (" + tr("by clicking the link, the page will open in your web browser") + "). <br>"); - topLabel->setTextFormat(Qt::RichText); - topLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - topLabel->setOpenExternalLinks(true); - topLabel->setWordWrap(true); + top_label->setTextFormat(Qt::RichText); + top_label->setTextInteractionFlags(Qt::TextBrowserInteraction); + top_label->setOpenExternalLinks(true); + top_label->setWordWrap(true); // QComboBox for language selection auto* lang_label = @@ -99,7 +94,7 @@ IntroPage::IntroPage(QWidget* parent) : QWizardPage(parent) { // set layout and add widgets auto* layout = new QVBoxLayout; - layout->addWidget(topLabel); + layout->addWidget(top_label); layout->addStretch(); layout->addWidget(lang_label); @@ -122,7 +117,7 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) { keygen_label->setOpenExternalLinks(true); keygen_label->setWordWrap(true); - auto* encr_decy_text_label = new QLabel( + auto* encr_decy_text_label = new QLabel( tr("If you want to learn how to encrypt, decrypt, sign and verify text, " "you can read ") + "<a href=\"https://gpgfrontend.bktus.com/guides/encrypt-decrypt-text\">" + @@ -135,12 +130,12 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) { encr_decy_text_label->setOpenExternalLinks(true); encr_decy_text_label->setWordWrap(true); - auto* sign_verify_text_label = - new QLabel(tr("If you want to operate file, you can read ") + - "<a href=\"https://gpgfrontend.bktus.com/guides/encrypt-decrypt-file\">" + - tr("Encrypt & Sign File") + "</a> " + tr("or") + - " <a href=\"https://gpgfrontend.bktus.com/guides/sign-verify-file\">" + - tr("Sign & Verify File") + "</a><hr>"); + auto* sign_verify_text_label = new QLabel( + tr("If you want to operate file, you can read ") + + "<a href=\"https://gpgfrontend.bktus.com/guides/encrypt-decrypt-file\">" + + tr("Encrypt & Sign File") + "</a> " + tr("or") + + " <a href=\"https://gpgfrontend.bktus.com/guides/sign-verify-file\">" + + tr("Sign & Verify File") + "</a><hr>"); sign_verify_text_label->setTextFormat(Qt::RichText); sign_verify_text_label->setTextInteractionFlags(Qt::TextBrowserInteraction); sign_verify_text_label->setOpenExternalLinks(true); @@ -157,9 +152,9 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) { int ChoosePage::nextId() const { return next_page_; } void ChoosePage::slot_jump_page(const QString& page) { - QMetaObject qmo = Wizard::staticMetaObject; - int index = qmo.indexOfEnumerator("WizardPages"); - QMetaEnum m = qmo.enumerator(index); + QMetaObject const qmo = Wizard::staticMetaObject; + int const index = qmo.indexOfEnumerator("WizardPages"); + QMetaEnum const m = qmo.enumerator(index); next_page_ = m.keyToValue(page.toUtf8().data()); wizard()->next(); @@ -225,7 +220,8 @@ ConclusionPage::ConclusionPage(QWidget* parent) : QWizardPage(parent) { open_help_check_box_ = new QCheckBox(tr("Open offline help.")); open_help_check_box_->setChecked(true); - dont_show_wizard_checkbox_ = new QCheckBox(tr("Don't show the wizard again.")); + dont_show_wizard_checkbox_ = + new QCheckBox(tr("Don't show the wizard again.")); dont_show_wizard_checkbox_->setChecked(true); registerField("showWizard", dont_show_wizard_checkbox_); diff --git a/src/ui/dialog/gnupg/GnuPGControllerDialog.cpp b/src/ui/dialog/controller/GnuPGControllerDialog.cpp index ea0a27c9..1874e255 100644 --- a/src/ui/dialog/gnupg/GnuPGControllerDialog.cpp +++ b/src/ui/dialog/controller/GnuPGControllerDialog.cpp @@ -52,16 +52,18 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) ui_->gpgmeDebugLogCheckBox->setText(tr("Enable GpgME Debug Log")); ui_->useCustomGnuPGInstallPathCheckBox->setText(tr("Use Custom GnuPG")); ui_->useCustomGnuPGInstallPathButton->setText(tr("Select GnuPG Path")); - ui_->keyDatabseUseCustomCheckBox->setText( + ui_->keyDatabaseUseCustomCheckBox->setText( tr("Use Custom GnuPG Key Database Path")); ui_->customKeyDatabasePathSelectButton->setText( tr("Select Key Database Path")); ui_->restartGpgAgentOnStartCheckBox->setText( tr("Restart Gpg Agent on start")); + ui_->killAllGnuPGDaemonCheckBox->setText( + tr("Kill all gnupg daemon at close")); // tips ui_->customGnuPGPathTipsLabel->setText( - tr("Tips: please select a directroy where \"gpgconf\" is located in.")); + tr("Tips: please select a directory where \"gpgconf\" is located in.")); ui_->restartTipsLabel->setText( tr("Tips: notice that modify any of these settings will cause an " "Application restart.")); @@ -71,7 +73,7 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) UISignalStation::GetInstance(), &UISignalStation::SignalRestartApplication); - connect(ui_->keyDatabseUseCustomCheckBox, &QCheckBox::stateChanged, this, + connect(ui_->keyDatabaseUseCustomCheckBox, &QCheckBox::stateChanged, this, [=](int state) { ui_->customKeyDatabasePathSelectButton->setDisabled( state != Qt::CheckState::Checked); @@ -83,7 +85,7 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) state != Qt::CheckState::Checked); }); - connect(ui_->keyDatabseUseCustomCheckBox, &QCheckBox::stateChanged, this, + connect(ui_->keyDatabaseUseCustomCheckBox, &QCheckBox::stateChanged, this, &GnuPGControllerDialog::slot_update_custom_key_database_path_label); connect(ui_->useCustomGnuPGInstallPathCheckBox, &QCheckBox::stateChanged, @@ -98,7 +100,7 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) this, tr("Open Directory"), {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - GF_UI_LOG_DEBUG("key databse path selected: {}", + GF_UI_LOG_DEBUG("key database path selected: {}", selected_custom_key_database_path); custom_key_database_path_ = selected_custom_key_database_path; @@ -108,7 +110,7 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) // update ui this->slot_update_custom_key_database_path_label( - this->ui_->keyDatabseUseCustomCheckBox->checkState()); + this->ui_->keyDatabaseUseCustomCheckBox->checkState()); }); connect( @@ -185,9 +187,6 @@ void GnuPGControllerDialog::SlotAccept() { void GnuPGControllerDialog::slot_update_custom_key_database_path_label( int state) { - // announce the restart - this->slot_set_restart_needed(kDeepRestartCode); - // hide label (not necessary to show the default path) this->ui_->currentKeyDatabasePathLabel->setHidden(state != Qt::CheckState::Checked); @@ -225,9 +224,6 @@ void GnuPGControllerDialog::slot_update_custom_key_database_path_label( void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label( int state) { - // announce the restart - this->slot_set_restart_needed(kDeepRestartCode); - // hide label (not necessary to show the default path) this->ui_->currentCustomGnuPGInstallPathLabel->setHidden( state != Qt::CheckState::Checked); @@ -269,52 +265,61 @@ void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label( void GnuPGControllerDialog::set_settings() { auto settings = GlobalSettingStation::GetInstance().GetSettings(); - bool non_ascii_at_file_operation = + auto non_ascii_at_file_operation = settings.value("gnupg/non_ascii_at_file_operation", true).toBool(); - if (non_ascii_at_file_operation) + if (non_ascii_at_file_operation) { ui_->asciiModeCheckBox->setCheckState(Qt::Checked); + } - bool const use_custom_key_database_path = + auto use_custom_key_database_path = settings.value("gnupg/use_custom_key_database_path", false).toBool(); if (use_custom_key_database_path) { - ui_->keyDatabseUseCustomCheckBox->setCheckState(Qt::Checked); + ui_->keyDatabaseUseCustomCheckBox->setCheckState(Qt::Checked); } - bool const enable_gpgme_debug_log = + auto enable_gpgme_debug_log = settings.value("gnupg/enable_gpgme_debug_log", false).toBool(); if (enable_gpgme_debug_log) { ui_->gpgmeDebugLogCheckBox->setCheckState(Qt::Checked); } + auto kill_all_gnupg_daemon_at_close = + settings.value("gnupg/kill_all_gnupg_daemon_at_close", false).toBool(); + if (kill_all_gnupg_daemon_at_close) { + ui_->killAllGnuPGDaemonCheckBox->setCheckState(Qt::Checked); + } + this->slot_update_custom_key_database_path_label( - ui_->keyDatabseUseCustomCheckBox->checkState()); + ui_->keyDatabaseUseCustomCheckBox->checkState()); - bool const use_custom_gnupg_install_path = + auto use_custom_gnupg_install_path = settings.value("gnupg/use_custom_gnupg_install_path", false).toBool(); if (use_custom_gnupg_install_path) { ui_->useCustomGnuPGInstallPathCheckBox->setCheckState(Qt::Checked); } - bool const use_pinentry_as_password_input_dialog = - settings.value("gnupg/use_pinentry_as_password_input_dialog", true) + auto use_pinentry_as_password_input_dialog = + settings + .value("gnupg/use_pinentry_as_password_input_dialog", + QString::fromLocal8Bit(qgetenv("container")) != "flatpak") .toBool(); if (use_pinentry_as_password_input_dialog) { ui_->usePinentryAsPasswordInputDialogCheckBox->setCheckState(Qt::Checked); } - bool const restart_gpg_agent_on_start = + auto restart_gpg_agent_on_start = settings.value("gnupg/restart_gpg_agent_on_start", false).toBool(); if (restart_gpg_agent_on_start) { ui_->restartGpgAgentOnStartCheckBox->setCheckState(Qt::Checked); } - this->slot_set_restart_needed(false); - this->slot_update_custom_key_database_path_label( use_custom_key_database_path ? Qt::Checked : Qt::Unchecked); this->slot_update_custom_gnupg_install_path_label( use_custom_gnupg_install_path ? Qt::Checked : Qt::Unchecked); + + this->slot_set_restart_needed(kNonRestartCode); } void GnuPGControllerDialog::apply_settings() { @@ -324,7 +329,7 @@ void GnuPGControllerDialog::apply_settings() { settings.setValue("gnupg/non_ascii_at_file_operation", ui_->asciiModeCheckBox->isChecked()); settings.setValue("gnupg/use_custom_key_database_path", - ui_->keyDatabseUseCustomCheckBox->isChecked()); + ui_->keyDatabaseUseCustomCheckBox->isChecked()); settings.setValue("gnupg/use_custom_gnupg_install_path", ui_->useCustomGnuPGInstallPathCheckBox->isChecked()); settings.setValue("gnupg/use_pinentry_as_password_input_dialog", @@ -337,20 +342,23 @@ void GnuPGControllerDialog::apply_settings() { ui_->currentCustomGnuPGInstallPathLabel->text()); settings.setValue("gnupg/restart_gpg_agent_on_start", ui_->restartGpgAgentOnStartCheckBox->isChecked()); + settings.setValue("gnupg/kill_all_gnupg_daemon_at_close", + ui_->killAllGnuPGDaemonCheckBox->isChecked()); } -int GnuPGControllerDialog::get_restart_needed() const { - return this->restart_needed_; +auto GnuPGControllerDialog::get_restart_needed() const -> int { + return this->restart_mode_; } void GnuPGControllerDialog::slot_set_restart_needed(int mode) { - this->restart_needed_ = mode; + GF_UI_LOG_INFO("announce restart needed, mode: {}", mode); + this->restart_mode_ = mode; } auto GnuPGControllerDialog::check_custom_gnupg_path(QString path) -> bool { if (path.isEmpty()) return false; - QFileInfo dir_info(path); + QFileInfo const dir_info(path); if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) { QMessageBox::critical( this, tr("Illegal GnuPG Path"), @@ -358,15 +366,15 @@ auto GnuPGControllerDialog::check_custom_gnupg_path(QString path) -> bool { return false; } - QDir dir(path); + QDir const dir(path); if (!dir.isAbsolute()) { QMessageBox::critical(this, tr("Illegal GnuPG Path"), tr("Target GnuPG Path is not an absolute path.")); } #ifdef WINDOWS - QFileInfo gpgconf_info(path + "/gpgconf.exe"); + QFileInfo const gpgconf_info(path + "/gpgconf.exe"); #else - QFileInfo gpgconf_info(path + "/gpgconf"); + QFileInfo const gpgconf_info(path + "/gpgconf"); #endif if (!gpgconf_info.exists() || !gpgconf_info.isFile() || @@ -384,7 +392,7 @@ auto GnuPGControllerDialog::check_custom_gnupg_key_database_path(QString path) -> bool { if (path.isEmpty()) return false; - QFileInfo dir_info(path); + QFileInfo const dir_info(path); if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) { QMessageBox::critical(this, tr("Illegal GnuPG Key Database Path"), tr("Target GnuPG Key Database Path is not an " diff --git a/src/ui/dialog/gnupg/GnuPGControllerDialog.h b/src/ui/dialog/controller/GnuPGControllerDialog.h index 6e8ef797..e8a4b83c 100644 --- a/src/ui/dialog/gnupg/GnuPGControllerDialog.h +++ b/src/ui/dialog/controller/GnuPGControllerDialog.h @@ -83,7 +83,7 @@ class GnuPGControllerDialog : public GeneralDialog { private: std::shared_ptr<Ui_GnuPGControllerDialog> ui_; ///< - int restart_needed_{0}; ///< + int restart_mode_{0}; ///< QString custom_key_database_path_; QString custom_gnupg_path_; diff --git a/src/ui/dialog/controller/ModuleControllerDialog.cpp b/src/ui/dialog/controller/ModuleControllerDialog.cpp new file mode 100644 index 00000000..4c727b48 --- /dev/null +++ b/src/ui/dialog/controller/ModuleControllerDialog.cpp @@ -0,0 +1,186 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "ModuleControllerDialog.h" + +#include "core/function/GlobalSettingStation.h" +#include "core/model/SettingsObject.h" +#include "core/struct/settings_object/ModuleSO.h" +#include "ui_ModuleControllerDialog.h" + +// +#include "core/module/ModuleManager.h" +#include "ui/widgets/ModuleListView.h" + +namespace GpgFrontend::UI { + +ModuleControllerDialog::ModuleControllerDialog(QWidget* parent) + : QDialog(parent), + ui_(std::make_shared<Ui_ModuleControllerDialog>()), + module_manager_(&Module::ModuleManager::GetInstance()) { + ui_->setupUi(this); + ui_->actionsGroupBox->hide(); + + ui_->moduleInfoLabel->setText(tr("Module Informations")); + ui_->actionsGroupBox->setTitle(tr("Actions")); + ui_->showModsDirButton->setText(tr("Show Mods Directory")); + + ui_->tabWidget->setTabText(0, tr("Registered Modules")); + ui_->tabWidget->setTabText(1, tr("Global Register Table")); + ui_->tabWidget->setTabText(2, tr("Debugger")); + + ui_->tipsLabel->setText( + tr("Tips: Module name front with \"*\" stands for integrated module.")); + + this->setWindowTitle(tr("Module Controller")); + + connect(ui_->moduleListView, &ModuleListView::SignalSelectModule, this, + &ModuleControllerDialog::slot_load_module_details); + + connect(ui_->activateOrDeactiveButton, &QPushButton::clicked, this, [=]() { + auto module_id = ui_->moduleListView->GetCurrentModuleID(); + if (module_id.isEmpty()) return; + + if (!module_manager_->IsModuleActivated(module_id)) { + module_manager_->ActiveModule(module_id); + } else { + module_manager_->DeactiveModule(module_id); + } + + QTimer::singleShot(1000, [=]() { slot_load_module_details(module_id); }); + }); + + connect(ui_->autoActivateButton, &QPushButton::clicked, this, [=]() { + auto module_id = ui_->moduleListView->GetCurrentModuleID(); + SettingsObject so(QString("module.%1.so").arg(module_id)); + ModuleSO module_so(so); + + module_so.auto_activate = + ui_->autoActivateButton->text() == tr("Enable Auto Activate"); + so.Store(module_so.ToJson()); + + QTimer::singleShot(1000, [=]() { slot_load_module_details(module_id); }); + }); + + connect(ui_->triggerEventButton, &QPushButton::clicked, this, [=]() { + auto event_id = + QInputDialog::getText(this, "Please provide an Event ID", "Event ID"); + Module::TriggerEvent(event_id); + }); + + connect(ui_->showModsDirButton, &QPushButton::clicked, this, [=]() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + GlobalSettingStation::GetInstance().GetModulesDir())); + }); + +#ifdef RELEASE + ui_->tabWidget->setTabEnabled(2, false); +#endif +} + +void ModuleControllerDialog::slot_load_module_details( + Module::ModuleIdentifier module_id) { + GF_UI_LOG_DEBUG("loading module details, module id: {}", module_id); + auto module = module_manager_->SearchModule(module_id); + SettingsObject so(QString("module.%1.so").arg(module_id)); + ModuleSO module_so(so); + + if (module_id.isEmpty() || module == nullptr) { + ui_->actionsGroupBox->hide(); + return; + } + + ui_->actionsGroupBox->show(); + + if (module_so.module_id != module_id || + module_so.module_hash != module->GetModuleHash()) { + module_so.module_id = module_id; + module_so.module_hash = module->GetModuleHash(); + module_so.auto_activate = false; + GF_UI_LOG_DEBUG("reseting module settings object, module id: {}", + module_id); + so.Store(module_so.ToJson()); + } + + QString buffer; + QTextStream info(&buffer); + + info << "# " << tr("BASIC INFO") << Qt::endl << Qt::endl; + + info << " - " << tr("ID") << ": " << module->GetModuleIdentifier() + << Qt::endl; + info << " - " << tr("Version") << ": " << module->GetModuleVersion() + << Qt::endl; + info << " - " << tr("SDK Version") << ": " << module->GetModuleSDKVersion() + << Qt::endl; + info << " - " << tr("Qt ENV Version") << ": " + << module->GetModuleQtEnvVersion() << Qt::endl; + info << " - " << tr("Hash") << ": " << module->GetModuleHash() << Qt::endl; + info << " - " << tr("Path") << ": " << module->GetModulePath() << Qt::endl; + + auto if_activated = module_manager_->IsModuleActivated(module_id); + + info << " - " << tr("Auto Activate") << ": " + << (module_so.auto_activate ? tr("True") : tr("False")) << Qt::endl; + info << " - " << tr("Active") << ": " + << (if_activated ? tr("True") : tr("False")) << Qt::endl; + + info << Qt::endl; + + info << "# " << tr("METADATA") << Qt::endl << Qt::endl; + +#ifdef QT5_BUILD + auto map = module->GetModuleMetaData(); + for (auto it = map.keyValueBegin(); it != map.keyValueEnd(); ++it) { + info << " - " << it->first << ": " << it->second << "\n"; + } +#else + for (const auto& metadata : module->GetModuleMetaData().asKeyValueRange()) { + info << " - " << metadata.first << ": " << metadata.second << "\n"; + } +#endif + + info << Qt::endl; + + if (if_activated) { + info << "# " << tr("Listening Event") << Qt::endl << Qt::endl; + + auto listening_event_ids = module_manager_->GetModuleListening(module_id); + for (const auto& event_id : listening_event_ids) { + info << " - " << event_id << "\n"; + } + } + + ui_->moduleInfoTextBrowser->setText(buffer); + ui_->activateOrDeactiveButton->setText(if_activated ? tr("Deactivate") + : tr("Activate")); + ui_->autoActivateButton->setText(module_so.auto_activate + ? tr("Disable Auto Activate") + : tr("Enable Auto Activate")); +} +} // namespace GpgFrontend::UI diff --git a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.h b/src/ui/dialog/controller/ModuleControllerDialog.h index 88f64d7d..6ded4808 100644 --- a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.h +++ b/src/ui/dialog/controller/ModuleControllerDialog.h @@ -28,28 +28,34 @@ #pragma once -#include "GpgFrontendModuleExport.h" #include "core/module/Module.h" -namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule { +class Ui_ModuleControllerDialog; -/** - * @brief Use to record some info about gnupg - * - */ -class GPGFRONTEND_INTEGRATED_MODULE_GNUPG_INFO_GATHERING_EXPORT - GnuPGInfoGatheringModule : public Module { - public: - GnuPGInfoGatheringModule(); - - ~GnuPGInfoGatheringModule() override; +namespace GpgFrontend::UI { - auto Register() -> bool override; +class ModuleListView; - auto Active() -> bool override; - - auto Exec(EventRefrernce) -> int override; - - auto Deactive() -> bool override; +class ModuleControllerDialog : public QDialog { + Q_OBJECT + public: + /** + * @brief Construct a new Module Controller Dialog object + * + * @param parent + */ + explicit ModuleControllerDialog(QWidget* parent); + + private slots: + /** + * @brief + * + */ + void slot_load_module_details(Module::ModuleIdentifier); + + private: + std::shared_ptr<Ui_ModuleControllerDialog> ui_; ///< + Module::ModuleManager* module_manager_; }; -} // namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule + +} // namespace GpgFrontend::UI diff --git a/src/ui/dialog/help/AboutDialog.cpp b/src/ui/dialog/help/AboutDialog.cpp index e4a189a3..0735ddba 100644 --- a/src/ui/dialog/help/AboutDialog.cpp +++ b/src/ui/dialog/help/AboutDialog.cpp @@ -30,35 +30,46 @@ #include <openssl/opensslv.h> -#include <any> - -#include "GpgFrontendBuildInfo.h" -#include "core/function/GlobalSettingStation.h" #include "core/module/ModuleManager.h" +#include "core/utils/BuildInfoUtils.h" #include "ui/dialog/help/GnupgTab.h" namespace GpgFrontend::UI { -AboutDialog::AboutDialog(int defaultIndex, QWidget* parent) +AboutDialog::AboutDialog(const QString& default_tab_name, QWidget* parent) : GeneralDialog(typeid(AboutDialog).name(), parent) { this->setWindowTitle(tr("About") + " " + qApp->applicationName()); auto* tab_widget = new QTabWidget; auto* info_tab = new InfoTab(); - auto* gnupg_tab = new GnupgTab(); auto* translators_tab = new TranslatorsTab(); - update_tab_ = new UpdateTab(); tab_widget->addTab(info_tab, tr("About GpgFrontend")); - tab_widget->addTab(gnupg_tab, tr("GnuPG")); + + if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + auto* gnupg_tab = new GnupgTab(); + tab_widget->addTab(gnupg_tab, tr("GnuPG")); + } + tab_widget->addTab(translators_tab, tr("Translators")); - tab_widget->addTab(update_tab_, tr("Update")); + + if (Module::IsModuleActivate(kVersionCheckingModuleID)) { + auto* update_tab = new UpdateTab(); + tab_widget->addTab(update_tab, tr("Update")); + } connect(tab_widget, &QTabWidget::currentChanged, this, [&](int index) { GF_UI_LOG_DEBUG("current index: {}", index); }); - if (defaultIndex < tab_widget->count() && defaultIndex >= 0) { - tab_widget->setCurrentIndex(defaultIndex); + int default_index = 0; + for (int i = 0; i < tab_widget->count(); i++) { + if (tab_widget->tabText(i) == default_tab_name) { + default_index = i; + } + } + + if (default_index < tab_widget->count() && default_index >= 0) { + tab_widget->setCurrentIndex(default_index); } auto* button_box = new QDialogButtonBox(QDialogButtonBox::Ok); @@ -69,7 +80,7 @@ AboutDialog::AboutDialog(int defaultIndex, QWidget* parent) main_layout->addWidget(button_box); setLayout(main_layout); - this->resize(550, 650); + this->resize(520, 620); this->setMinimumWidth(450); this->show(); } @@ -81,11 +92,13 @@ InfoTab::InfoTab(QWidget* parent) : QWidget(parent) { "core", "gpgme.version", QString{"2.0.0"}); GF_UI_LOG_DEBUG("got gpgme version from rt: {}", gpgme_version); - auto* pixmap = new QPixmap(":/icons/gpgfrontend-logo.png"); - auto* text = new QString( + auto pixmap = QPixmap(":/icons/gpgfrontend_logo.png"); + pixmap = pixmap.scaled(128, 128); + + auto text = "<center><h2>" + qApp->applicationName() + "</h2></center>" + - "<center><b>" + qApp->applicationVersion() + "</b></center>" + - "<center>" + GIT_VERSION + "</center>" + "<br><center>" + + "<center><b>" + "v" + qApp->applicationVersion() + "</b></center>" + + "<center>" + GetProjectBuildGitVersion() + "</center>" + "<br><center>" + tr("GpgFrontend is an easy-to-use, compact, cross-platform, " "and installation-free GnuPG Frontend." "It visualizes most of the common operations of GnuPG." @@ -100,14 +113,15 @@ InfoTab::InfoTab(QWidget* parent) : QWidget(parent) { "href=\"mailto:[email protected]\">[email protected]</a>." + "<br><br> " + tr("Built with Qt") + " " + qVersion() + ", " + OPENSSL_VERSION_TEXT + " " + tr("and") + " " + "GPGME" + " " + gpgme_version + "<br>" + - tr("Built at") + " " + BUILD_TIMESTAMP + "</center>"); + tr("Built at") + " " + QLocale().toString(GetProjectBuildTimestamp()) + + "</center>"; auto* layout = new QGridLayout(); auto* pixmap_label = new QLabel(); - pixmap_label->setPixmap(*pixmap); + pixmap_label->setPixmap(pixmap); layout->addWidget(pixmap_label, 0, 0, 1, -1, Qt::AlignCenter); auto* about_label = new QLabel(); - about_label->setText(*text); + about_label->setText(text); about_label->setWordWrap(true); about_label->setOpenExternalLinks(true); layout->addWidget(about_label, 1, 0, 1, -1); @@ -139,14 +153,9 @@ TranslatorsTab::TranslatorsTab(QWidget* parent) : QWidget(parent) { } UpdateTab::UpdateTab(QWidget* parent) : QWidget(parent) { - auto* pixmap = new QPixmap(":/icons/gpgfrontend-logo.png"); auto* layout = new QGridLayout(); - auto* pixmap_label = new QLabel(); - pixmap_label->setPixmap(*pixmap); - layout->addWidget(pixmap_label, 0, 0, 1, -1, Qt::AlignCenter); - current_version_ = - QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + "." + VERSION_PATCH; + current_version_ = GetProjectVersion(); auto* tips_label = new QLabel(); tips_label->setText( @@ -194,17 +203,15 @@ void UpdateTab::showEvent(QShowEvent* event) { GF_UI_LOG_DEBUG("loading version loading info from rt"); auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.loading_done", false); + kVersionCheckingModuleID, "version.loading_done", false); if (!is_loading_done) { Module::ListenRTPublishEvent( - this, "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.loading_done", + this, kVersionCheckingModuleID, "version.loading_done", [=](Module::Namespace, Module::Key, int, std::any) { GF_UI_LOG_DEBUG( - "versionchecking version.loading_done changed, calling slot " - "version upgrade"); + "version_checking module version.loading_done changed, calling " + "slot version upgrade"); this->slot_show_version_status(); }); Module::TriggerEvent("CHECK_APPLICATION_VERSION"); @@ -218,29 +225,24 @@ void UpdateTab::slot_show_version_status() { this->pb_->setHidden(true); auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.loading_done", false); + kVersionCheckingModuleID, "version.loading_done", false); if (!is_loading_done) { - GF_UI_LOG_DEBUG("version info loading havn't been done yet."); + GF_UI_LOG_DEBUG("version info loading haven't been done yet."); return; } auto is_need_upgrade = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.need_upgrade", false); + kVersionCheckingModuleID, "version.need_upgrade", false); auto is_current_a_withdrawn_version = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.current_a_withdrawn_version", false); + kVersionCheckingModuleID, "version.current_a_withdrawn_version", false); auto is_current_version_released = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.current_version_released", false); + kVersionCheckingModuleID, "version.current_version_released", false); auto latest_version = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.latest_version", QString{}); + kVersionCheckingModuleID, "version.latest_version", QString{}); latest_version_label_->setText("<center><b>" + tr("Latest Version From Github") + ": " + diff --git a/src/ui/dialog/help/AboutDialog.h b/src/ui/dialog/help/AboutDialog.h index b7871a29..6d152afb 100644 --- a/src/ui/dialog/help/AboutDialog.h +++ b/src/ui/dialog/help/AboutDialog.h @@ -120,7 +120,7 @@ class AboutDialog : public GeneralDialog { * @param defaultIndex * @param parent */ - explicit AboutDialog(int defaultIndex, QWidget* parent); + explicit AboutDialog(const QString& default_tab_name, QWidget* parent); protected: /** @@ -129,9 +129,6 @@ class AboutDialog : public GeneralDialog { * @param ev */ void showEvent(QShowEvent* ev) override; - - private: - UpdateTab* update_tab_; ///< }; } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/help/GnupgTab.cpp b/src/ui/dialog/help/GnupgTab.cpp index 1aceed1a..ac018def 100644 --- a/src/ui/dialog/help/GnupgTab.cpp +++ b/src/ui/dialog/help/GnupgTab.cpp @@ -35,7 +35,9 @@ #include "core/module/ModuleManager.h" #include "ui_GnuPGInfo.h" -GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) +namespace GpgFrontend::UI { + +GnupgTab::GnupgTab(QWidget* parent) : QWidget(parent), ui_(GpgFrontend::SecureCreateSharedObject<Ui_GnuPGInfo>()) { ui_->setupUi(this); @@ -55,11 +57,11 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) ui_->componentDetailsTable->setSelectionBehavior( QAbstractItemView::SelectRows); - // tableitems not editable + // table items not editable ui_->componentDetailsTable->setEditTriggers( QAbstractItemView::NoEditTriggers); - // no focus (rectangle around tableitems) + // no focus (rectangle around table items) // may be it should focus on whole row ui_->componentDetailsTable->setFocusPolicy(Qt::NoFocus); ui_->componentDetailsTable->setAlternatingRowColors(true); @@ -68,7 +70,7 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) directories_column_titles << tr("Directory Type") << tr("Path"); ui_->directoriesDetailsTable->setColumnCount( - directories_column_titles.length()); + static_cast<int>(directories_column_titles.length())); ui_->directoriesDetailsTable->setHorizontalHeaderLabels( directories_column_titles); ui_->directoriesDetailsTable->horizontalHeader()->setStretchLastSection( @@ -76,11 +78,11 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) ui_->directoriesDetailsTable->setSelectionBehavior( QAbstractItemView::SelectRows); - // tableitems not editable + // table items not editable ui_->directoriesDetailsTable->setEditTriggers( QAbstractItemView::NoEditTriggers); - // no focus (rectangle around tableitems) + // no focus (rectangle around table items) // may be it should focus on whole row ui_->directoriesDetailsTable->setFocusPolicy(Qt::NoFocus); ui_->directoriesDetailsTable->setAlternatingRowColors(true); @@ -95,18 +97,23 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) ui_->optionDetailsTable->horizontalHeader()->setStretchLastSection(false); ui_->optionDetailsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - // tableitems not editable + // table items not editable ui_->optionDetailsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - // no focus (rectangle around tableitems) + // no focus (rectangle around table items) // may be it should focus on whole row ui_->optionDetailsTable->setFocusPolicy(Qt::NoFocus); ui_->optionDetailsTable->setAlternatingRowColors(true); - process_software_info(); + if (Module::RetrieveRTValueTypedOrDefault( + "ui", "env.state.gnupg_info_gathering", 0) == 1) { + process_software_info(); + } else { + gather_gnupg_info(); + } } -void GpgFrontend::UI::GnupgTab::process_software_info() { +void GnupgTab::process_software_info() { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); GF_UI_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); @@ -114,9 +121,8 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { ui_->gnupgVersionLabel->setText( QString::fromStdString(fmt::format("Version: {}", gnupg_version))); - auto components = Module::ListRTChildKeys( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "gnupg.components"); + auto components = + Module::ListRTChildKeys(kGnuPGInfoGatheringModuleID, "gnupg.components"); GF_UI_LOG_DEBUG("got gnupg components from rt, size: {}", components.size()); ui_->componentDetailsTable->setRowCount(components.size()); @@ -124,12 +130,12 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { int row = 0; for (auto& component : components) { auto component_info_json_bytes = Module::RetrieveRTValueTypedOrDefault( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - QString("gnupg.components.%1").arg(component), QByteArray{}); + kGnuPGInfoGatheringModuleID, + QString("gnupg.components.%1").arg(component), QString{}); GF_UI_LOG_DEBUG("got gnupg component {} info from rt", component); auto component_info_json = - QJsonDocument::fromJson(component_info_json_bytes); + QJsonDocument::fromJson(component_info_json_bytes.toUtf8()); if (!component_info_json.isObject()) { GF_UI_LOG_WARN("illegal gnupg component info, json: {}", QString(component_info_json_bytes)); @@ -170,17 +176,17 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { ui_->componentDetailsTable->resizeColumnsToContents(); - auto directories = Module::ListRTChildKeys( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - QString("gnupg.dirs")); + auto directories = Module::ListRTChildKeys(kGnuPGInfoGatheringModuleID, + QString("gnupg.dirs")); - ui_->directoriesDetailsTable->setRowCount(directories.size()); + ui_->directoriesDetailsTable->setRowCount( + static_cast<int>(directories.size())); row = 0; for (auto& dir : directories) { const auto dir_path = Module::RetrieveRTValueTypedOrDefault( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - QString("gnupg.dirs.%1").arg(dir), QString{}); + kGnuPGInfoGatheringModuleID, QString("gnupg.dirs.%1").arg(dir), + QString{}); if (dir_path.isEmpty()) continue; @@ -197,20 +203,21 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { ui_->directoriesDetailsTable->resizeColumnsToContents(); - // calcualte the total row number of configuration table + // calculate the total row number of configuration table row = 0; for (auto& component : components) { auto options = Module::ListRTChildKeys( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", + kGnuPGInfoGatheringModuleID, QString("gnupg.components.%1.options").arg(component)); for (auto& option : options) { const auto option_info_json = QJsonDocument::fromJson(Module::RetrieveRTValueTypedOrDefault( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - QString("gnupg.components.%1.options.%2") - .arg(component) - .arg(option), - QByteArray{})); + kGnuPGInfoGatheringModuleID, + QString("gnupg.components.%1.options.%2") + .arg(component) + .arg(option), + QString{}) + .toUtf8()); if (!option_info_json.isObject()) continue; @@ -228,18 +235,19 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { QString configuration_group; for (auto& component : components) { auto options = Module::ListRTChildKeys( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", + kGnuPGInfoGatheringModuleID, QString("gnupg.components.%1.options").arg(component)); for (auto& option : options) { auto option_info_json_bytes = Module::RetrieveRTValueTypedOrDefault( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", + kGnuPGInfoGatheringModuleID, QString("gnupg.components.%1.options.%2").arg(component).arg(option), - QByteArray{}); + QString{}); GF_UI_LOG_DEBUG("got gnupg component's option {} info from rt, info: {}", component, option_info_json_bytes); - auto option_info_json = QJsonDocument::fromJson(option_info_json_bytes); + auto option_info_json = + QJsonDocument::fromJson(option_info_json_bytes.toUtf8()); if (!option_info_json.isObject()) { GF_UI_LOG_WARN("illegal gnupg option info, json: {}", @@ -289,5 +297,40 @@ void GpgFrontend::UI::GnupgTab::process_software_info() { row++; } } - // ui_->configurationDetailsTable->resizeColumnsToContents(); + + ui_->loadProgressBar->hide(); + ui_->tabWidget->setDisabled(false); } + +void GnupgTab::gather_gnupg_info() { + // if gnupg_info_gathering module activated + if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + GF_CORE_LOG_DEBUG( + "module gnupg_info_gathering is activated, " + "loading external gnupg info..."); + + ui_->loadProgressBar->show(); + ui_->tabWidget->setDisabled(true); + + // gather external gnupg info + Module::TriggerEvent( + "REQUEST_GATHERING_GNUPG_INFO", + [=](const Module::EventIdentifier& /*e*/, + const Module::Event::ListenerIdentifier& l_id, DataObjectPtr o) { + GF_CORE_LOG_DEBUG( + "received event REQUEST_GATHERING_GNUPG_INFO callback " + "from module: {}", + l_id); + + if (l_id == kGnuPGInfoGatheringModuleID) { + Module::UpsertRTValue("ui", "env.state.gnupg_info_gathering", 1); + + // gnupg info gathering process finished + GF_CORE_LOG_INFO("gnupg information gathering finished"); + process_software_info(); + } + }); + } +} + +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/dialog/help/GnupgTab.h b/src/ui/dialog/help/GnupgTab.h index 9e6191db..60abd048 100644 --- a/src/ui/dialog/help/GnupgTab.h +++ b/src/ui/dialog/help/GnupgTab.h @@ -50,6 +50,16 @@ class GnupgTab : public QWidget { private: std::shared_ptr<Ui_GnuPGInfo> ui_; ///< + /** + * @brief + * + */ void process_software_info(); + + /** + * @brief + * + */ + void gather_gnupg_info(); }; } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/import_export/KeyServerImportDialog.cpp b/src/ui/dialog/import_export/KeyServerImportDialog.cpp index 296df539..575a97e4 100644 --- a/src/ui/dialog/import_export/KeyServerImportDialog.cpp +++ b/src/ui/dialog/import_export/KeyServerImportDialog.cpp @@ -28,14 +28,12 @@ #include "KeyServerImportDialog.h" -#include <QRegExp> - #include "core/GpgModel.h" #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyImportExporter.h" +#include "core/model/SettingsObject.h" #include "ui/UISignalStation.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "ui/struct/settings_object/KeyServerSO.h" #include "ui/thread/KeyServerImportTask.h" #include "ui/thread/KeyServerSearchTask.h" @@ -243,11 +241,14 @@ void KeyServerImportDialog::slot_search_finished( set_message("<h4>" + tr("Too many responses from keyserver!") + "</h4>", true); return; - } else if (text.contains("No keys found")) { + } + + if (text.contains("No keys found")) { + auto query = search_line_edit_->text(); + // if string looks like hex string, search again with 0x prepended - QRegExp rx("[0-9A-Fa-f]*"); - QString query = search_line_edit_->text(); - if (rx.exactMatch(query)) { + QRegularExpression rx("[0-9A-Fa-f]*"); + if (rx.match(query).hasMatch()) { set_message("<h4>" + tr("No keys found, input may be kexId, retrying search " "with 0x.") + @@ -257,102 +258,104 @@ void KeyServerImportDialog::slot_search_finished( this->slot_search(); return; } + set_message( "<h4>" + tr("No keys found containing the search string!") + "</h4>", true); return; + } - } else if (text.contains("Insufficiently specific words")) { + if (text.contains("Insufficiently specific words")) { set_message( "<h4>" + tr("Insufficiently specific search string!") + "</h4>", true); return; - } else { - set_message(text, true); - return; } - } else { - int row = 0; - bool strikeout = false; - - // read lines until end of steam - while (!stream.atEnd()) { - QStringList line = - QString::fromUtf8(QByteArray::fromPercentEncoding( - stream.readLine().trimmed().toUtf8())) - .split(":"); - - // TODO: have a look at two following pub lines - if (line[0] == "pub") { - strikeout = false; - - QString flags = line[line.size() - 1]; - keys_table_->setRowCount(row + 1); - - // flags can be "d" for disabled, "r" for revoked - // or "e" for expired - if (flags.contains("r") or flags.contains("d") or flags.contains("e")) { - strikeout = true; - if (flags.contains("e")) { - keys_table_->setItem(row, 3, - new QTableWidgetItem(QString("expired"))); - } - if (flags.contains("r")) { - keys_table_->setItem(row, 3, new QTableWidgetItem(tr("revoked"))); - } - if (flags.contains("d")) { - keys_table_->setItem(row, 3, new QTableWidgetItem(tr("disabled"))); - } - } - QStringList line2 = QString(QByteArray::fromPercentEncoding( - stream.readLine().trimmed().toUtf8())) - .split(":"); + set_message(text, true); + return; + } - auto* uid = new QTableWidgetItem(); - if (line2.size() > 1) { - uid->setText(line2[1]); - keys_table_->setItem(row, 0, uid); + int row = 0; + bool strikeout = false; + + // read lines until end of steam + while (!stream.atEnd()) { + QStringList line = + QString::fromUtf8(QByteArray::fromPercentEncoding( + stream.readLine().trimmed().toUtf8())) + .split(":"); + + // TODO: have a look at two following pub lines + if (line[0] == "pub") { + strikeout = false; + + QString flags = line[line.size() - 1]; + keys_table_->setRowCount(row + 1); + + // flags can be "d" for disabled, "r" for revoked + // or "e" for expired + if (flags.contains("r") or flags.contains("d") or flags.contains("e")) { + strikeout = true; + if (flags.contains("e")) { + keys_table_->setItem(row, 3, + new QTableWidgetItem(QString("expired"))); + } + if (flags.contains("r")) { + keys_table_->setItem(row, 3, new QTableWidgetItem(tr("revoked"))); + } + if (flags.contains("d")) { + keys_table_->setItem(row, 3, new QTableWidgetItem(tr("disabled"))); } - auto* creation_date = - new QTableWidgetItem(QDateTime::fromSecsSinceEpoch(line[4].toInt()) - .toString("dd. MMM. yyyy")); - keys_table_->setItem(row, 1, creation_date); - auto* keyid = new QTableWidgetItem(line[1]); - keys_table_->setItem(row, 2, keyid); + } + + QStringList line2 = QString(QByteArray::fromPercentEncoding( + stream.readLine().trimmed().toUtf8())) + .split(":"); + + auto* uid = new QTableWidgetItem(); + if (line2.size() > 1) { + uid->setText(line2[1]); + keys_table_->setItem(row, 0, uid); + } + auto* creation_date = + new QTableWidgetItem(QDateTime::fromSecsSinceEpoch(line[4].toInt()) + .toString("dd. MMM. yyyy")); + keys_table_->setItem(row, 1, creation_date); + auto* keyid = new QTableWidgetItem(line[1]); + keys_table_->setItem(row, 2, keyid); + if (strikeout) { + QFont strike = uid->font(); + strike.setStrikeOut(true); + uid->setFont(strike); + creation_date->setFont(strike); + keyid->setFont(strike); + } + row++; + } else { + if (line[0] == "uid") { + QStringList l; + int height = keys_table_->rowHeight(row - 1); + keys_table_->setRowHeight(row - 1, height + 16); + QString tmp = keys_table_->item(row - 1, 0)->text(); + tmp.append(QString("\n") + line[1]); + auto* tmp1 = new QTableWidgetItem(tmp); + keys_table_->setItem(row - 1, 0, tmp1); if (strikeout) { - QFont strike = uid->font(); + QFont strike = tmp1->font(); strike.setStrikeOut(true); - uid->setFont(strike); - creation_date->setFont(strike); - keyid->setFont(strike); - } - row++; - } else { - if (line[0] == "uid") { - QStringList l; - int height = keys_table_->rowHeight(row - 1); - keys_table_->setRowHeight(row - 1, height + 16); - QString tmp = keys_table_->item(row - 1, 0)->text(); - tmp.append(QString("\n") + line[1]); - auto* tmp1 = new QTableWidgetItem(tmp); - keys_table_->setItem(row - 1, 0, tmp1); - if (strikeout) { - QFont strike = tmp1->font(); - strike.setStrikeOut(true); - tmp1->setFont(strike); - } + tmp1->setFont(strike); } } - set_message( - QString("<h4>") + - tr("%1 keys found. Double click a key to import it.").arg(row) + - "</h4>", - false); } - keys_table_->resizeColumnsToContents(); - import_button_->setDisabled(keys_table_->size().isEmpty()); + set_message( + QString("<h4>") + + tr("%1 keys found. Double click a key to import it.").arg(row) + + "</h4>", + false); } + keys_table_->resizeColumnsToContents(); + import_button_->setDisabled(keys_table_->size().isEmpty()); } void KeyServerImportDialog::slot_import() { diff --git a/src/ui/dialog/import_export/KeyUploadDialog.cpp b/src/ui/dialog/import_export/KeyUploadDialog.cpp index f59f9daa..7ab34c49 100644 --- a/src/ui/dialog/import_export/KeyUploadDialog.cpp +++ b/src/ui/dialog/import_export/KeyUploadDialog.cpp @@ -33,10 +33,11 @@ #include "core/GpgModel.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/function/gpg/GpgKeyImportExporter.h" +#include "core/model/SettingsObject.h" +#include "core/utils/BuildInfoUtils.h" #include "core/utils/GpgUtils.h" #include "ui/UserInterfaceUtils.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "ui/struct/settings_object/KeyServerSO.h" namespace GpgFrontend::UI { @@ -115,6 +116,8 @@ void KeyUploadDialog::slot_upload_key_to_server( data.replace(" ", "+"); QNetworkRequest request(req_url); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); diff --git a/src/ui/dialog/key_generate/KeygenDialog.cpp b/src/ui/dialog/key_generate/KeygenDialog.cpp index 5251d15e..7585d6f0 100644 --- a/src/ui/dialog/key_generate/KeygenDialog.cpp +++ b/src/ui/dialog/key_generate/KeygenDialog.cpp @@ -141,7 +141,8 @@ void KeyGenDialog::slot_key_gen_accept() { if (!GlobalSettingStation::GetInstance() .GetSettings() - .value("gnupg/use_pinentry_as_password_input_dialog", true) + .value("gnupg/use_pinentry_as_password_input_dialog", + QString::fromLocal8Bit(qgetenv("container")) != "flatpak") .toBool() && !no_pass_phrase_check_box_->isChecked()) { SetCacheValue("PinentryContext", "NEW_PASSPHRASE"); diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp index 1528b7d8..2a9a4c96 100644 --- a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp @@ -319,7 +319,7 @@ void KeyPairSubkeyTab::slot_edit_subkey() { void KeyPairSubkeyTab::slot_revoke_subkey() {} void KeyPairSubkeyTab::contextMenuEvent(QContextMenuEvent* event) { - if (!subkey_list_->selectedItems().isEmpty()) { + if (key_.IsPrivateKey() && !subkey_list_->selectedItems().isEmpty()) { subkey_opera_menu_->exec(event->globalPos()); } } diff --git a/src/ui/dialog/settings/SettingsAppearance.cpp b/src/ui/dialog/settings/SettingsAppearance.cpp index d4f97c4c..f09f9823 100644 --- a/src/ui/dialog/settings/SettingsAppearance.cpp +++ b/src/ui/dialog/settings/SettingsAppearance.cpp @@ -28,9 +28,10 @@ #include "SettingsAppearance.h" +#include "core/function/GlobalSettingStation.h" +#include "core/model/SettingsObject.h" #include "core/utils/MemoryUtils.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/AppearanceSO.h" +#include "ui/struct/settings_object/AppearanceSO.h" #include "ui_AppearanceSettings.h" namespace GpgFrontend::UI { @@ -39,26 +40,28 @@ AppearanceTab::AppearanceTab(QWidget* parent) : QWidget(parent), ui_(SecureCreateSharedObject<Ui_AppearanceSettings>()) { ui_->setupUi(this); - ui_->iconSizeBox->setTitle(tr("Icon Size")); + ui_->generalBox->setTitle(tr("General")); + + ui_->themaLabel->setText(tr("Theme")); + ui_->windowStateCheckBox->setText( + tr("Save window size and position on exit.")); + + ui_->toolbarIconBox->setTitle(tr("Toolbar Icon")); + + ui_->toolbarIconSizeLabel->setText(tr("Size")); ui_->smallRadioButton->setText(tr("small")); ui_->mediumRadioButton->setText(tr("medium")); ui_->largeRadioButton->setText(tr("large")); - ui_->iconStyleBox->setTitle(tr("Icon Style")); + ui_->toolbarIconStyleLabel->setText(tr("Style")); ui_->justTextRadioButton->setText(tr("just text")); ui_->justIconRadioButton->setText(tr("just icons")); ui_->textAndIconsRadioButton->setText(tr("text and icons")); - ui_->windowStateBox->setTitle(tr("Window State")); - ui_->windowStateCheckBox->setText( - tr("Save window size and position on exit.")); - - ui_->textEditorBox->setTitle(tr("Text Editor")); - ui_->fontSizeTextEditorLabel->setText(tr("Font Size in Text Editor")); + ui_->fontSizeBox->setTitle(tr("Font Size")); - ui_->informationBoardBox->setTitle(tr("Information Board")); - ui_->fontSizeInformationBoardLabel->setText( - tr("Font Size in Information Board")); + ui_->fontSizeTextEditorLabel->setText(tr("Text Editor")); + ui_->fontSizeInformationBoardLabel->setText(tr("Information Board")); icon_size_group_ = new QButtonGroup(this); icon_size_group_->addButton(ui_->smallRadioButton, 1); @@ -71,10 +74,13 @@ AppearanceTab::AppearanceTab(QWidget* parent) icon_style_group_->addButton(ui_->textAndIconsRadioButton, 3); SetSettings(); + + connect(ui_->themeComboBox, qOverload<int>(&QComboBox::currentIndexChanged), + this, &AppearanceTab::SignalRestartNeeded); } void AppearanceTab::SetSettings() { - AppearanceSO appearance(SettingsObject("general_settings_state")); + AppearanceSO const appearance(SettingsObject("general_settings_state")); auto icon_size = QSize(appearance.tool_bar_icon_width, appearance.tool_bar_icon_height); @@ -123,6 +129,34 @@ void AppearanceTab::SetSettings() { text_editor_info_font_size = 10; } ui_->fontSizeTextEditorLabelSpinBox->setValue(text_editor_info_font_size); + + // init available styles + for (const auto& s : QStyleFactory::keys()) { + ui_->themeComboBox->addItem(s.toLower()); + } + + auto settings = GlobalSettingStation::GetInstance().GetSettings(); + auto theme = settings.value("appearance/theme").toString(); + + auto target_theme_index = ui_->themeComboBox->findText(theme); + if (theme.isEmpty() || target_theme_index == -1) { +#ifdef QT5_BUILD + GF_UI_LOG_DEBUG( + "There is not valid theme found from settings, " + "using current theme (qt5): {}", + QApplication::style()->metaObject()->className()); + ui_->themeComboBox->setCurrentIndex(ui_->themeComboBox->findText( + QApplication::style()->metaObject()->className())); +#else + GF_UI_LOG_DEBUG( + "There is not valid theme found from settings, using current theme: {}", + QApplication::style()->name()); + ui_->themeComboBox->setCurrentIndex( + ui_->themeComboBox->findText(QApplication::style()->name())); +#endif + } else { + ui_->themeComboBox->setCurrentIndex(target_theme_index); + } } void AppearanceTab::ApplySettings() { @@ -169,6 +203,9 @@ void AppearanceTab::ApplySettings() { ui_->fontSizeTextEditorLabelSpinBox->value(); general_settings_state.Store(appearance.ToJson()); + + auto settings = GlobalSettingStation::GetInstance().GetSettings(); + settings.setValue("appearance/theme", ui_->themeComboBox->currentText()); } } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/settings/SettingsAppearance.h b/src/ui/dialog/settings/SettingsAppearance.h index 6d426934..ca520ba7 100644 --- a/src/ui/dialog/settings/SettingsAppearance.h +++ b/src/ui/dialog/settings/SettingsAppearance.h @@ -70,7 +70,7 @@ class AppearanceTab : public QWidget { * * @param needed */ - void signalRestartNeeded(bool needed); + void SignalRestartNeeded(); }; } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/settings/SettingsDialog.cpp b/src/ui/dialog/settings/SettingsDialog.cpp index cb17eb0d..70b8c7b0 100644 --- a/src/ui/dialog/settings/SettingsDialog.cpp +++ b/src/ui/dialog/settings/SettingsDialog.cpp @@ -30,7 +30,6 @@ #include "core/GpgConstants.h" #include "core/GpgModel.h" -#include "core/function/GlobalSettingStation.h" #include "ui/dialog/settings/SettingsAppearance.h" #include "ui/dialog/settings/SettingsGeneral.h" #include "ui/dialog/settings/SettingsKeyServer.h" @@ -74,24 +73,17 @@ SettingsDialog::SettingsDialog(QWidget* parent) setLayout(main_layout); - // slots for handling the restart needed member - this->slot_set_restart_needed(0); - // restart ui connect(general_tab_, &GeneralTab::SignalRestartNeeded, this, - [=](bool needed) { - if (needed && restart_needed_ < kRestartCode) { - this->restart_needed_ = kRestartCode; - } - }); + &SettingsDialog::slot_declare_a_restart); // restart core and ui connect(general_tab_, &GeneralTab::SignalDeepRestartNeeded, this, - [=](bool needed) { - if (needed && restart_needed_ < kDeepRestartCode) { - this->restart_needed_ = kDeepRestartCode; - } - }); + &SettingsDialog::slot_declare_a_deep_restart); + + // restart core and ui + connect(appearance_tab_, &AppearanceTab::SignalRestartNeeded, this, + &SettingsDialog::slot_declare_a_restart); // announce main window connect(this, &SettingsDialog::SignalRestartNeeded, @@ -102,12 +94,16 @@ SettingsDialog::SettingsDialog(QWidget* parent) this->show(); } -auto SettingsDialog::get_restart_needed() const -> int { - return this->restart_needed_; +void SettingsDialog::slot_declare_a_restart() { + if (restart_mode_ < kRestartCode) { + this->restart_mode_ = kRestartCode; + } } -void SettingsDialog::slot_set_restart_needed(int mode) { - this->restart_needed_ = mode; +void SettingsDialog::slot_declare_a_deep_restart() { + if (restart_mode_ < kDeepRestartCode) { + this->restart_mode_ = kDeepRestartCode; + } } void SettingsDialog::SlotAccept() { @@ -116,9 +112,9 @@ void SettingsDialog::SlotAccept() { key_server_tab_->ApplySettings(); network_tab_->ApplySettings(); - GF_UI_LOG_DEBUG("restart needed: {}", get_restart_needed()); - if (get_restart_needed() != 0) { - emit SignalRestartNeeded(get_restart_needed()); + GF_UI_LOG_DEBUG("ui restart status: {}", restart_mode_); + if (restart_mode_ != kNonRestartCode) { + emit SignalRestartNeeded(restart_mode_); } close(); } @@ -127,7 +123,7 @@ auto SettingsDialog::ListLanguages() -> QHash<QString, QString> { QHash<QString, QString> languages; languages.insert(QString(), tr("System Default")); - QStringList filenames = QDir(QLatin1String(":/i18n")).entryList(); + auto filenames = QDir(QLatin1String(":/i18n")).entryList(); for (const auto& file : filenames) { GF_UI_LOG_DEBUG("get locale from locale directory: {}", file); diff --git a/src/ui/dialog/settings/SettingsDialog.h b/src/ui/dialog/settings/SettingsDialog.h index c99ac23c..f74b2cc0 100644 --- a/src/ui/dialog/settings/SettingsDialog.h +++ b/src/ui/dialog/settings/SettingsDialog.h @@ -82,26 +82,23 @@ class SettingsDialog : public GeneralDialog { void SignalRestartNeeded(int); private: - QTabWidget* tab_widget_; ///< - QDialogButtonBox* button_box_; ///< - int restart_needed_{0}; ///< + QTabWidget* tab_widget_; ///< + QDialogButtonBox* button_box_; ///< + int restart_mode_{kNonRestartCode}; ///< + + private slots: /** - * @brief Get the Restart Needed object + * @brief * - * @return true - * @return false */ - int get_restart_needed() const; - - private slots: + void slot_declare_a_restart(); /** * @brief * - * @param needed */ - void slot_set_restart_needed(int); + void slot_declare_a_deep_restart(); }; } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/settings/SettingsGeneral.cpp b/src/ui/dialog/settings/SettingsGeneral.cpp index bcf42867..9764b747 100644 --- a/src/ui/dialog/settings/SettingsGeneral.cpp +++ b/src/ui/dialog/settings/SettingsGeneral.cpp @@ -73,7 +73,7 @@ GeneralTab::GeneralTab(QWidget* parent) ui_->langSelectBox->addItem(l); } connect(ui_->langSelectBox, qOverload<int>(&QComboBox::currentIndexChanged), - this, &GeneralTab::slot_language_changed); + this, &GeneralTab::SignalRestartNeeded); connect(ui_->clearAllLogFilesButton, &QPushButton::clicked, this, [=]() { GlobalSettingStation::GetInstance().ClearAllLogFiles(); @@ -109,28 +109,28 @@ GeneralTab::GeneralTab(QWidget* parent) void GeneralTab::SetSettings() { auto settings = GlobalSettingStation::GetInstance().GetSettings(); - bool clear_gpg_password_cache = + auto clear_gpg_password_cache = settings.value("basic/clear_gpg_password_cache", true).toBool(); ui_->clearGpgPasswordCacheCheckBox->setCheckState( clear_gpg_password_cache ? Qt::Checked : Qt::Unchecked); - bool restore_text_editor_page = + auto restore_text_editor_page = settings.value("basic/restore_text_editor_page", true).toBool(); ui_->restoreTextEditorPageCheckBox->setCheckState( restore_text_editor_page ? Qt::Checked : Qt::Unchecked); - bool longer_expiration_date = + auto longer_expiration_date = settings.value("basic/longer_expiration_date", false).toBool(); ui_->longerKeyExpirationDateCheckBox->setCheckState( longer_expiration_date ? Qt::Checked : Qt::Unchecked); - bool confirm_import_keys = + auto confirm_import_keys = settings.value("basic/confirm_import_keys", false).toBool(); ui_->importConfirmationCheckBox->setCheckState( confirm_import_keys ? Qt::Checked : Qt::Unchecked); - QString lang_key = settings.value("basic/lang").toString(); - QString lang_value = lang_.value(lang_key); + auto lang_key = settings.value("basic/lang").toString(); + auto lang_value = lang_.value(lang_key); GF_UI_LOG_DEBUG("lang settings current: {}", lang_value); if (!lang_.empty()) { ui_->langSelectBox->setCurrentIndex( @@ -155,6 +155,4 @@ void GeneralTab::ApplySettings() { settings.setValue("basic/lang", lang_.key(ui_->langSelectBox->currentText())); } -void GeneralTab::slot_language_changed() { emit SignalRestartNeeded(true); } - } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/settings/SettingsGeneral.h b/src/ui/dialog/settings/SettingsGeneral.h index 284843d4..d6e954de 100644 --- a/src/ui/dialog/settings/SettingsGeneral.h +++ b/src/ui/dialog/settings/SettingsGeneral.h @@ -69,27 +69,19 @@ class GeneralTab : public QWidget { * * @param needed */ - void SignalRestartNeeded(bool needed); + void SignalRestartNeeded(); /** * @brief * * @param needed */ - void SignalDeepRestartNeeded(bool needed); + void SignalDeepRestartNeeded(); private: std::shared_ptr<Ui_GeneralSettings> ui_; ///< QHash<QString, QString> lang_; ///< std::vector<QString> key_ids_list_; ///< KeyList* m_key_list_{}; ///< - - private slots: - - /** - * @brief - * - */ - void slot_language_changed(); }; } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/settings/SettingsKeyServer.cpp b/src/ui/dialog/settings/SettingsKeyServer.cpp index 5613ed45..fb6e624c 100644 --- a/src/ui/dialog/settings/SettingsKeyServer.cpp +++ b/src/ui/dialog/settings/SettingsKeyServer.cpp @@ -31,10 +31,10 @@ #include <cstddef> #include "core/function/GlobalSettingStation.h" +#include "core/model/SettingsObject.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "ui/struct/settings_object/KeyServerSO.h" #include "ui/thread/ListedKeyServerTestTask.h" #include "ui_KeyServerSettings.h" diff --git a/src/ui/dialog/settings/SettingsNetwork.cpp b/src/ui/dialog/settings/SettingsNetwork.cpp index c7e1e9f6..d4840063 100644 --- a/src/ui/dialog/settings/SettingsNetwork.cpp +++ b/src/ui/dialog/settings/SettingsNetwork.cpp @@ -29,6 +29,7 @@ #include "SettingsNetwork.h" #include "core/function/GlobalSettingStation.h" +#include "core/module/ModuleManager.h" #include "ui/thread/ProxyConnectionTestTask.h" #include "ui_NetworkSettings.h" @@ -86,60 +87,62 @@ GpgFrontend::UI::NetworkTab::NetworkTab(QWidget *parent) ui_->forbidALLGnuPGNetworkConnectionCheckBox->setText( tr("Forbid all GnuPG network connection.")); - ui_->prohibitUpdateCheck->setText( - tr("Prohibit checking for version updates when the program starts.")); + + if (Module::IsModuleActivate(kVersionCheckingModuleID)) { + ui_->prohibitUpdateCheck->setText( + tr("Prohibit checking for version updates when the program starts.")); + } ui_->autoImportMissingKeyCheckBox->setText( tr("Automatically import a missing key for signature verification.")); ui_->networkAbilityTipsLabel->setText( tr("Tips: These Option Changes take effect only after the " "application restart.")); - SetSettings(); } void GpgFrontend::UI::NetworkTab::SetSettings() { auto settings = GlobalSettingStation::GetInstance().GetSettings(); - QString proxy_host = settings.value("proxy/proxy_host").toString(); + auto proxy_host = settings.value("proxy/proxy_host").toString(); ui_->proxyServerAddressEdit->setText(proxy_host); - QString username = settings.value("proxy/username").toString(); + auto username = settings.value("proxy/username").toString(); ui_->usernameEdit->setText(username); - QString password = settings.value("proxy/password").toString(); + auto password = settings.value("proxy/password").toString(); ui_->passwordEdit->setText(password); - int port = settings.value("proxy/port", 0).toInt(); + auto port = settings.value("proxy/port", 0).toInt(); ui_->portSpin->setValue(port); ui_->proxyTypeComboBox->setCurrentText("HTTP"); - QString proxy_type = settings.value("proxy/proxy_type").toString(); + auto proxy_type = settings.value("proxy/proxy_type").toString(); ui_->proxyTypeComboBox->setCurrentText(proxy_type); switch_ui_proxy_type(ui_->proxyTypeComboBox->currentText()); ui_->enableProxyCheckBox->setCheckState(Qt::Unchecked); - bool proxy_enable = settings.value("proxy/enable", false).toBool(); + auto proxy_enable = settings.value("proxy/enable", false).toBool(); ui_->enableProxyCheckBox->setCheckState(proxy_enable ? Qt::Checked : Qt::Unchecked); - bool forbid_all_gnupg_connection = + auto forbid_all_gnupg_connection = settings.value("network/forbid_all_gnupg_connection").toBool(); ui_->forbidALLGnuPGNetworkConnectionCheckBox->setCheckState( forbid_all_gnupg_connection ? Qt::Checked : Qt::Unchecked); - bool prohibit_update_checking = + auto prohibit_update_checking = settings.value("network/prohibit_update_checking").toBool(); ui_->prohibitUpdateCheck->setCheckState( prohibit_update_checking ? Qt::Checked : Qt::Unchecked); - bool auto_import_missing_key = + auto auto_import_missing_key = settings.value("network/auto_import_missing_key", true).toBool(); ui_->autoImportMissingKeyCheckBox->setCheckState( auto_import_missing_key ? Qt::Checked : Qt::Unchecked); - switch_ui_enabled(ui_->enableProxyCheckBox->isChecked()); switch_ui_proxy_type(ui_->proxyTypeComboBox->currentText()); + switch_ui_enabled(ui_->enableProxyCheckBox->isChecked()); } void GpgFrontend::UI::NetworkTab::ApplySettings() { @@ -171,7 +174,7 @@ void GpgFrontend::UI::NetworkTab::slot_test_proxy_connection_result() { tr("Server Url"), QLineEdit::Normal, "https://", &ok); if (ok && !url.isEmpty()) { - auto task = new ProxyConnectionTestTask(url, 800); + auto *task = new ProxyConnectionTestTask(url, 800); connect(task, &GpgFrontend::UI::ProxyConnectionTestTask:: SignalProxyConnectionTestResult, @@ -193,7 +196,7 @@ void GpgFrontend::UI::NetworkTab::slot_test_proxy_connection_result() { auto *waiting_dialog = new QProgressDialog(this); waiting_dialog->setMaximum(0); waiting_dialog->setMinimum(0); - auto waiting_dialog_label = new QLabel( + auto *waiting_dialog_label = new QLabel( tr("Test Proxy Server Connection...") + "<br /><br />" + tr("Is using your proxy settings to access the url. Note that this " "test " diff --git a/src/ui/main_window/GeneralMainWindow.cpp b/src/ui/main_window/GeneralMainWindow.cpp index f58326f9..3d662332 100644 --- a/src/ui/main_window/GeneralMainWindow.cpp +++ b/src/ui/main_window/GeneralMainWindow.cpp @@ -28,9 +28,9 @@ #include "GeneralMainWindow.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/AppearanceSO.h" -#include "ui/struct/settings/WindowStateSO.h" +#include "core/model/SettingsObject.h" +#include "ui/struct/settings_object/AppearanceSO.h" +#include "ui/struct/settings_object/WindowStateSO.h" namespace GpgFrontend::UI { @@ -65,6 +65,8 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { QByteArray::fromBase64(window_state.window_state_data.toUtf8())); } + this->setMinimumSize(640, 480); + // restore window size & location if (window_state.window_save) { pos_ = {window_state.x, window_state.y}; @@ -96,16 +98,16 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { parent_size.height()); if (parent_pos != QPoint{0, 0}) { - QPoint parent_center{parent_pos.x() + parent_size.width() / 2, - parent_pos.y() + parent_size.height() / 2}; + QPoint const parent_center{parent_pos.x() + parent_size.width() / 2, + parent_pos.y() + parent_size.height() / 2}; pos_ = {parent_center.x() - size_.width() / 2, parent_center.y() - size_.height() / 2}; } } - if (size_.width() < 600) size_.setWidth(600); - if (size_.height() < 400) size_.setHeight(400); + if (size_.width() < 640) size_.setWidth(640); + if (size_.height() < 480) size_.setHeight(480); this->move(pos_); this->resize(size_); @@ -114,7 +116,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { } // appearance - AppearanceSO appearance(SettingsObject("general_settings_state")); + AppearanceSO const appearance(SettingsObject("general_settings_state")); icon_size_ = {appearance.tool_bar_icon_width, appearance.tool_bar_icon_height}; @@ -125,7 +127,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { icon_style_ = toolButtonStyle(); } catch (...) { - GF_UI_LOG_ERROR("gernal main window: {}, caught exception", name_); + GF_UI_LOG_ERROR("general main window: {}, caught exception", name_); } } @@ -148,7 +150,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept { general_windows_state.Store(window_state.Json()); } catch (...) { - GF_UI_LOG_ERROR("gernal main window: {}, caught exception", name_); + GF_UI_LOG_ERROR("general main window: {}, caught exception", name_); } } diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp index 96df89d1..afc6129c 100644 --- a/src/ui/main_window/KeyMgmt.cpp +++ b/src/ui/main_window/KeyMgmt.cpp @@ -121,7 +121,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) this->statusBar()->show(); setWindowTitle(tr("KeyPair Management")); - setMinimumSize(QSize(600, 400)); + setMinimumSize(QSize(640, 480)); key_list_->AddMenuAction(generate_subkey_act_); key_list_->AddMenuAction(delete_selected_keys_act_); @@ -229,22 +229,26 @@ void KeyMgmt::create_actions() { &KeyMgmt::SlotExportAsOpenSSHFormat); delete_selected_keys_act_ = new QAction(tr("Delete Selected Key(s)"), this); + delete_selected_keys_act_->setIcon(QIcon(":/icons/button_delete.png")); delete_selected_keys_act_->setToolTip(tr("Delete the Selected keys")); connect(delete_selected_keys_act_, &QAction::triggered, this, &KeyMgmt::SlotDeleteSelectedKeys); delete_checked_keys_act_ = new QAction(tr("Delete Checked Key(s)"), this); - delete_checked_keys_act_->setToolTip(tr("Delete the Checked keys")); delete_checked_keys_act_->setIcon(QIcon(":/icons/button_delete.png")); + delete_checked_keys_act_->setToolTip(tr("Delete the Checked keys")); + connect(delete_checked_keys_act_, &QAction::triggered, this, &KeyMgmt::SlotDeleteCheckedKeys); show_key_details_act_ = new QAction(tr("Show Key Details"), this); + show_key_details_act_->setIcon(QIcon(":/icons/detail.png")); show_key_details_act_->setToolTip(tr("Show Details for this Key")); connect(show_key_details_act_, &QAction::triggered, this, &KeyMgmt::SlotShowKeyDetails); set_owner_trust_of_key_act_ = new QAction(tr("Set Owner Trust Level"), this); + set_owner_trust_of_key_act_->setIcon(QIcon(":/icons/stairs.png")); set_owner_trust_of_key_act_->setToolTip(tr("Set Owner Trust Level")); set_owner_trust_of_key_act_->setData(QVariant("set_owner_trust_level")); connect(set_owner_trust_of_key_act_, &QAction::triggered, this, [this]() { diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index a7bd63d8..c50cfc5e 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -31,13 +31,12 @@ #include "core/function/CacheManager.h" #include "core/function/CoreSignalStation.h" #include "core/function/GlobalSettingStation.h" -#include "core/function/gpg/GpgAdvancedOperator.h" #include "core/model/GpgPassphraseContext.h" +#include "core/model/SettingsObject.h" #include "core/module/ModuleManager.h" #include "ui/UISignalStation.h" #include "ui/main_window/GeneralMainWindow.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "ui/struct/settings_object/KeyServerSO.h" #include "ui/widgets/KeyList.h" #include "ui/widgets/TextEdit.h" @@ -120,7 +119,7 @@ void MainWindow::Init() noexcept { m_key_list_->AddMenuAction(copy_key_default_uid_to_clipboard_act_); m_key_list_->AddMenuAction(copy_key_id_to_clipboard_act_); m_key_list_->AddMenuAction(set_owner_trust_of_key_act_); - m_key_list_->AddMenuAction(add_key_2_favourtie_act_); + m_key_list_->AddMenuAction(add_key_2_favourite_act_); m_key_list_->AddMenuAction(remove_key_from_favourtie_act_); m_key_list_->AddSeparator(); @@ -131,13 +130,12 @@ void MainWindow::Init() noexcept { edit_->CurTextPage()->setFocus(); Module::ListenRTPublishEvent( - this, "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.loading_done", + this, kVersionCheckingModuleID, "version.loading_done", [=](Module::Namespace, Module::Key, int, std::any) { GF_UI_LOG_DEBUG( - "versionchecking version.loading_done changed, calling slot " + "version-checking version.loading_done changed, calling slot " "version upgrade"); - this->slot_version_upgrade_nofity(); + this->slot_version_upgrade_notify(); }); // loading process is done @@ -149,7 +147,7 @@ void MainWindow::Init() noexcept { // check if need to open wizard window auto settings = GlobalSettingStation::GetInstance().GetSettings(); - bool show_wizard = settings.value("wizard/show_wizard", true).toBool(); + auto show_wizard = settings.value("wizard/show_wizard", true).toBool(); if (show_wizard) slot_start_wizard(); } catch (...) { @@ -196,7 +194,7 @@ void MainWindow::recover_editor_unsaved_pages_from_cache() { bool first = true; - QJsonArray unsaved_page_array = json_data.array(); + auto unsaved_page_array = json_data.array(); for (const auto &value_ref : unsaved_page_array) { if (!value_ref.isObject()) continue; auto unsaved_page_json = value_ref.toObject(); @@ -206,8 +204,8 @@ void MainWindow::recover_editor_unsaved_pages_from_cache() { continue; } - QString title = unsaved_page_json["title"].toString(); - QString content = unsaved_page_json["content"].toString(); + auto title = unsaved_page_json["title"].toString(); + auto content = unsaved_page_json["content"].toString(); GF_UI_LOG_DEBUG( "recovering unsaved page from cache, page title: {}, content size", @@ -247,9 +245,6 @@ void MainWindow::closeEvent(QCloseEvent *event) { CacheManager::GetInstance().SaveDurableCache( "editor_unsaved_pages", QJsonDocument(QJsonArray()), true); - // clear password from memory - // GpgContext::GetInstance().clearPasswordCache(); - // call parent GeneralMainWindow::closeEvent(event); } diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index 523c14f0..f53a4a03 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -357,7 +357,7 @@ class MainWindow : public GeneralMainWindow { /** * @details called when need to upgrade. */ - void slot_version_upgrade_nofity(); + void slot_version_upgrade_notify(); /** * @details @@ -421,16 +421,11 @@ class MainWindow : public GeneralMainWindow { */ void recover_editor_unsaved_pages_from_cache(); - /** - * @brief return true, if restart is needed - */ - [[nodiscard]] int get_restart_needed() const; - TextEdit* edit_{}; ///< Tabwidget holding the edit-windows QMenu* file_menu_{}; ///< Submenu for file-operations QMenu* edit_menu_{}; ///< Submenu for text-operations QMenu* crypt_menu_{}; ///< Submenu for crypt-operations - QMenu* gpg_menu_{}; ///< Submenu for help-operations + QMenu* advance_menu_{}; ///< Submenu for help-operations QMenu* help_menu_{}; ///< Submenu for help-operations QMenu* key_menu_{}; ///< Submenu for key-operations QMenu* view_menu_{}; ///< Submenu for view operations @@ -473,6 +468,7 @@ class MainWindow : public GeneralMainWindow { ///< breaks QAction* gnupg_controller_open_act_{}; ///< + QAction* module_controller_open_act_{}; ///< QAction* clean_gpg_password_cache_act_{}; ///< QAction* reload_components_act_{}; ///< QAction* restart_components_act_{}; ///< @@ -488,7 +484,7 @@ class MainWindow : public GeneralMainWindow { QAction* copy_key_id_to_clipboard_act_{}; ///< QAction* copy_key_default_uid_to_clipboard_act_{}; ///< - QAction* add_key_2_favourtie_act_{}; ///< + QAction* add_key_2_favourite_act_{}; ///< QAction* remove_key_from_favourtie_act_{}; ///< QAction* set_owner_trust_of_key_act_{}; ///< @@ -522,7 +518,7 @@ class MainWindow : public GeneralMainWindow { InfoBoardWidget* info_board_{}; ///< bool attachment_dock_created_{}; ///< - int restart_needed_{0}; ///< + int restart_mode_{0}; ///< bool prohibit_update_checking_ = false; ///< }; diff --git a/src/ui/main_window/MainWindowGpgOperaFunction.cpp b/src/ui/main_window/MainWindowGpgOperaFunction.cpp index b1b22a6e..3cef497d 100644 --- a/src/ui/main_window/MainWindowGpgOperaFunction.cpp +++ b/src/ui/main_window/MainWindowGpgOperaFunction.cpp @@ -141,7 +141,7 @@ void MainWindow::SlotEncrypt() { void MainWindow::SlotSign() { if (edit_->SlotCurPageTextEdit() == nullptr) return; - auto key_ids = m_key_list_->GetPrivateChecked(); + auto key_ids = m_key_list_->GetCheckedPrivateKey(); if (key_ids->empty()) { QMessageBox::critical( this, tr("No Key Checked"), diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 6f0a99fb..7d50b85a 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -101,8 +101,9 @@ void MainWindow::slot_append_keys_create_datetime() { auto create_datetime_format_str_local = QLocale().toString(key.GetCreateTime()) + " (" + tr("Localize") + ") " + "\n"; - auto create_datetime_format_str = key.GetCreateTime().toString(Qt::ISODate) + - " (" + tr("UTC") + ") " + "\n "; + auto create_datetime_format_str = + QLocale().toString(key.GetCreateTime().toUTC()) + " (" + tr("UTC") + + ") " + "\n "; edit_->SlotAppendText2CurTextPage(create_datetime_format_str_local + create_datetime_format_str); } @@ -125,7 +126,7 @@ void MainWindow::slot_append_keys_expire_datetime() { QLocale().toString(key.GetCreateTime()) + " (" + tr("Local Time") + ") " + "\n"; auto expire_datetime_format_str = - key.GetCreateTime().toString(Qt::ISODate) + " (UTC) " + "\n"; + QLocale().toString(key.GetCreateTime().toUTC()) + " (UTC) " + "\n"; edit_->SlotAppendText2CurTextPage(expire_datetime_format_str_local + expire_datetime_format_str); @@ -261,12 +262,11 @@ void MainWindow::SlotOpenFile(const QString& path) { edit_->SlotOpenFile(path); } -void MainWindow::slot_version_upgrade_nofity() { +void MainWindow::slot_version_upgrade_notify() { GF_UI_LOG_DEBUG( "slot version upgrade notify called, checking version info from rt..."); auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.loading_done", false); + kVersionCheckingModuleID, "version.loading_done", false); GF_UI_LOG_DEBUG("checking version info from rt, is loading done state: {}", is_loading_done); @@ -276,20 +276,16 @@ void MainWindow::slot_version_upgrade_nofity() { } auto is_need_upgrade = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.need_upgrade", false); + kVersionCheckingModuleID, "version.need_upgrade", false); auto is_current_a_withdrawn_version = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.current_a_withdrawn_version", false); + kVersionCheckingModuleID, "version.current_a_withdrawn_version", false); auto is_current_version_released = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.current_version_released", false); + kVersionCheckingModuleID, "version.current_version_released", false); auto latest_version = Module::RetrieveRTValueTypedOrDefault<>( - "com.bktus.gpgfrontend.module.integrated.version-checking", - "version.latest_version", QString{}); + kVersionCheckingModuleID, "version.latest_version", QString{}); GF_UI_LOG_DEBUG( "got version info from rt, need upgrade: {}, with drawn: {}, " @@ -303,7 +299,7 @@ void MainWindow::slot_version_upgrade_nofity() { 30000); auto* update_button = new QPushButton("Update GpgFrontend", this); connect(update_button, &QPushButton::clicked, [=]() { - auto* about_dialog = new AboutDialog(2, this); + auto* about_dialog = new AboutDialog(tr("Update"), this); about_dialog->show(); }); statusBar()->addPermanentWidget(update_button, 0); diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index 99a26626..39ceedc6 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -28,13 +28,14 @@ #include "MainWindow.h" #include "core/GpgConstants.h" +#include "core/function/CacheManager.h" #include "core/model/GpgPassphraseContext.h" +#include "core/model/SettingsObject.h" #include "ui/UserInterfaceUtils.h" #include "ui/dialog/Wizard.h" #include "ui/function/RaisePinentry.h" #include "ui/main_window/KeyMgmt.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/AppearanceSO.h" +#include "ui/struct/settings_object/AppearanceSO.h" #include "ui/widgets/TextEdit.h" namespace GpgFrontend::UI { @@ -121,10 +122,13 @@ void MainWindow::slot_open_settings_dialog() { import_button_->setIconSize( QSize(appearance.tool_bar_icon_width, appearance.tool_bar_icon_height)); - // restart mainwindow if necessary - if (get_restart_needed() != 0) { + // restart main window if necessary + if (restart_mode_ != kNonRestartCode) { if (edit_->MaybeSaveAnyTab()) { - emit SignalRestartApplication(get_restart_needed()); + // clear cache of unsaved page + CacheManager::GetInstance().SaveDurableCache( + "editor_unsaved_pages", QJsonDocument(QJsonArray()), true); + emit SignalRestartApplication(restart_mode_); } } }); @@ -180,11 +184,9 @@ void MainWindow::slot_cut_pgp_header() { void MainWindow::SlotSetRestartNeeded(int mode) { GF_UI_LOG_DEBUG("restart mode: {}", mode); - this->restart_needed_ = mode; + this->restart_mode_ = mode; } -int MainWindow::get_restart_needed() const { return this->restart_needed_; } - void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) { MainWindow::CryptoMenu::OperationType opera_type = type; GF_UI_LOG_DEBUG("update crypto menu status, type: {}", opera_type); diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 8b6fc74c..8b611152 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -30,8 +30,9 @@ #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgAdvancedOperator.h" #include "core/module/ModuleManager.h" +#include "dialog/controller/ModuleControllerDialog.h" #include "ui/UserInterfaceUtils.h" -#include "ui/dialog/gnupg/GnuPGControllerDialog.h" +#include "ui/dialog/controller/GnuPGControllerDialog.h" #include "ui/dialog/help/AboutDialog.h" #include "ui/widgets/KeyList.h" #include "ui/widgets/TextEdit.h" @@ -82,6 +83,7 @@ void MainWindow::create_actions() { connect(print_act_, &QAction::triggered, edit_, &TextEdit::SlotPrint); close_tab_act_ = new QAction(tr("Close"), this); + close_tab_act_->setIcon(QIcon(":/icons/close.png")); close_tab_act_->setShortcut(QKeySequence::Close); close_tab_act_->setToolTip(tr("Close file")); connect(close_tab_act_, &QAction::triggered, edit_, &TextEdit::SlotCloseTab); @@ -95,20 +97,24 @@ void MainWindow::create_actions() { /* Edit Menu */ undo_act_ = new QAction(tr("Undo"), this); + undo_act_->setIcon(QIcon(":/icons/undo.png")); undo_act_->setShortcut(QKeySequence::Undo); undo_act_->setToolTip(tr("Undo Last Edit Action")); connect(undo_act_, &QAction::triggered, edit_, &TextEdit::SlotUndo); redo_act_ = new QAction(tr("Redo"), this); + redo_act_->setIcon(QIcon(":/icons/redo.png")); redo_act_->setShortcut(QKeySequence::Redo); redo_act_->setToolTip(tr("Redo Last Edit Action")); connect(redo_act_, &QAction::triggered, edit_, &TextEdit::SlotRedo); zoom_in_act_ = new QAction(tr("Zoom In"), this); + zoom_in_act_->setIcon(QIcon(":/icons/zoomin.png")); zoom_in_act_->setShortcut(QKeySequence::ZoomIn); connect(zoom_in_act_, &QAction::triggered, edit_, &TextEdit::SlotZoomIn); zoom_out_act_ = new QAction(tr("Zoom Out"), this); + zoom_out_act_->setIcon(QIcon(":/icons/zoomout.png")); zoom_out_act_->setShortcut(QKeySequence::ZoomOut); connect(zoom_out_act_, &QAction::triggered, edit_, &TextEdit::SlotZoomOut); @@ -343,7 +349,7 @@ void MainWindow::create_actions() { &MainWindow::slot_open_key_management); clean_gpg_password_cache_act_ = new QAction(tr("Clear Password Cache"), this); - clean_gpg_password_cache_act_->setIcon(QIcon(":/icons/configure.png")); + clean_gpg_password_cache_act_->setIcon(QIcon(":/icons/clear-f.png")); clean_gpg_password_cache_act_->setToolTip( tr("Clear Password Cache of GnuPG")); connect(clean_gpg_password_cache_act_, &QAction::triggered, this, [=]() { @@ -360,7 +366,7 @@ void MainWindow::create_actions() { }); reload_components_act_ = new QAction(tr("Reload All Components"), this); - reload_components_act_->setIcon(QIcon(":/icons/configure.png")); + reload_components_act_->setIcon(QIcon(":/icons/restart.png")); reload_components_act_->setToolTip(tr("Reload All GnuPG's Components")); connect(reload_components_act_, &QAction::triggered, this, [=]() { GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( @@ -378,7 +384,7 @@ void MainWindow::create_actions() { }); restart_components_act_ = new QAction(tr("Restart All Components"), this); - restart_components_act_->setIcon(QIcon(":/icons/configure.png")); + restart_components_act_->setIcon(QIcon(":/icons/restart.png")); restart_components_act_->setToolTip(tr("Restart All GnuPG's Components")); connect(restart_components_act_, &QAction::triggered, this, [=]() { GpgFrontend::GpgAdvancedOperator::RestartGpgComponents(); @@ -404,6 +410,12 @@ void MainWindow::create_actions() { connect(gnupg_controller_open_act_, &QAction::triggered, this, [this]() { (new GnuPGControllerDialog(this))->exec(); }); + module_controller_open_act_ = new QAction(tr("Open Module Controller"), this); + module_controller_open_act_->setIcon(QIcon(":/icons/module.png")); + module_controller_open_act_->setToolTip(tr("Open Module Controller Dialog")); + connect(module_controller_open_act_, &QAction::triggered, this, + [this]() { (new ModuleControllerDialog(this))->exec(); }); + /* * About Menu */ @@ -414,28 +426,30 @@ void MainWindow::create_actions() { connect(about_act_, &QAction::triggered, this, [=]() { new AboutDialog(0, this); }); - gnupg_act_ = new QAction(tr("GnuPG"), this); - gnupg_act_->setIcon(QIcon(":/icons/help.png")); - gnupg_act_->setToolTip(tr("Information about Gnupg")); - connect(gnupg_act_, &QAction::triggered, this, - [=]() { new AboutDialog(1, this); }); + if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + gnupg_act_ = new QAction(tr("GnuPG"), this); + gnupg_act_->setIcon(QIcon(":/icons/key.png")); + gnupg_act_->setToolTip(tr("Information about Gnupg")); + connect(gnupg_act_, &QAction::triggered, this, + [=]() { new AboutDialog(tr("GnuPG"), this); }); + } translate_act_ = new QAction(tr("Translate"), this); - translate_act_->setIcon(QIcon(":/icons/help.png")); + translate_act_->setIcon(QIcon(":/icons/translate.png")); translate_act_->setToolTip(tr("Information about translation")); connect(translate_act_, &QAction::triggered, this, - [=]() { new AboutDialog(2, this); }); + [=]() { new AboutDialog(tr("Translators"), this); }); - /* - * Check Update Menu - */ - check_update_act_ = new QAction(tr("Check for Updates"), this); - check_update_act_->setIcon(QIcon(":/icons/help.png")); - check_update_act_->setToolTip(tr("Check for updates")); - connect(check_update_act_, &QAction::triggered, this, - [=]() { new AboutDialog(3, this); }); + if (Module::IsModuleActivate(kVersionCheckingModuleID)) { + check_update_act_ = new QAction(tr("Check for Updates"), this); + check_update_act_->setIcon(QIcon(":/icons/update.png")); + check_update_act_->setToolTip(tr("Check for updates")); + connect(check_update_act_, &QAction::triggered, this, + [=]() { new AboutDialog(tr("Update"), this); }); + } start_wizard_act_ = new QAction(tr("Open Wizard"), this); + start_wizard_act_->setIcon(QIcon(":/icons/wizard.png")); start_wizard_act_->setToolTip(tr("Open the wizard")); connect(start_wizard_act_, &QAction::triggered, this, &MainWindow::slot_start_wizard); @@ -492,10 +506,10 @@ void MainWindow::create_actions() { connect(show_key_details_act_, &QAction::triggered, this, &MainWindow::slot_show_key_details); - add_key_2_favourtie_act_ = new QAction(tr("Add To Favourite"), this); - add_key_2_favourtie_act_->setToolTip(tr("Add this key to Favourite Table")); - add_key_2_favourtie_act_->setData(QVariant("add_key_2_favourite_action")); - connect(add_key_2_favourtie_act_, &QAction::triggered, this, + add_key_2_favourite_act_ = new QAction(tr("Add To Favourite"), this); + add_key_2_favourite_act_->setToolTip(tr("Add this key to Favourite Table")); + add_key_2_favourite_act_->setData(QVariant("add_key_2_favourite_action")); + connect(add_key_2_favourite_act_, &QAction::triggered, this, &MainWindow::slot_add_key_2_favourite); remove_key_from_favourtie_act_ = @@ -587,13 +601,13 @@ void MainWindow::create_menus() { import_key_menu_->addAction(import_key_from_key_server_act_); key_menu_->addAction(open_key_management_act_); - gpg_menu_ = menuBar()->addMenu(tr("GnuPG")); - gpg_menu_->addAction(clean_gpg_password_cache_act_); - gpg_menu_->addSeparator(); - gpg_menu_->addAction(reload_components_act_); - gpg_menu_->addAction(restart_components_act_); - gpg_menu_->addSeparator(); - gpg_menu_->addAction(gnupg_controller_open_act_); + advance_menu_ = menuBar()->addMenu(tr("Advance")); + advance_menu_->addAction(clean_gpg_password_cache_act_); + advance_menu_->addAction(reload_components_act_); + advance_menu_->addAction(restart_components_act_); + advance_menu_->addSeparator(); + advance_menu_->addAction(gnupg_controller_open_act_); + advance_menu_->addAction(module_controller_open_act_); steganography_menu_ = menuBar()->addMenu(tr("Steganography")); steganography_menu_->addAction(cut_pgp_header_act_); @@ -604,9 +618,17 @@ void MainWindow::create_menus() { help_menu_ = menuBar()->addMenu(tr("Help")); help_menu_->addAction(start_wizard_act_); help_menu_->addSeparator(); - help_menu_->addAction(check_update_act_); - help_menu_->addAction(gnupg_act_); + + if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { + help_menu_->addAction(gnupg_act_); + } + help_menu_->addAction(translate_act_); + + if (Module::IsModuleActivate(kVersionCheckingModuleID)) { + help_menu_->addAction(check_update_act_); + } + help_menu_->addAction(about_act_); } diff --git a/src/ui/struct/settings/AppearanceSO.h b/src/ui/struct/settings_object/AppearanceSO.h index 25262f22..25262f22 100644 --- a/src/ui/struct/settings/AppearanceSO.h +++ b/src/ui/struct/settings_object/AppearanceSO.h diff --git a/src/ui/struct/settings/KeyServerSO.h b/src/ui/struct/settings_object/KeyServerSO.h index 3c9320d2..3c9320d2 100644 --- a/src/ui/struct/settings/KeyServerSO.h +++ b/src/ui/struct/settings_object/KeyServerSO.h diff --git a/src/ui/struct/settings/WindowStateSO.h b/src/ui/struct/settings_object/WindowStateSO.h index 3fa56f3c..3fa56f3c 100644 --- a/src/ui/struct/settings/WindowStateSO.h +++ b/src/ui/struct/settings_object/WindowStateSO.h diff --git a/src/ui/thread/KeyServerImportTask.cpp b/src/ui/thread/KeyServerImportTask.cpp index 63cabbcd..8bcb2eab 100644 --- a/src/ui/thread/KeyServerImportTask.cpp +++ b/src/ui/thread/KeyServerImportTask.cpp @@ -29,8 +29,9 @@ #include "ui/thread/KeyServerImportTask.h" #include "core/function/gpg/GpgKeyImportExporter.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/KeyServerSO.h" +#include "core/model/SettingsObject.h" +#include "core/utils/BuildInfoUtils.h" +#include "ui/struct/settings_object/KeyServerSO.h" GpgFrontend::UI::KeyServerImportTask::KeyServerImportTask( QString keyserver_url, std::vector<QString> keyids) @@ -54,7 +55,11 @@ auto GpgFrontend::UI::KeyServerImportTask::Run() -> int { QUrl const req_url(keyserver_url.scheme() + "://" + keyserver_url.host() + "/pks/lookup?op=get&search=0x" + key_id + "&options=mr"); - reply_ = manager_->get(QNetworkRequest(req_url)); + auto request = QNetworkRequest(req_url); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); + + reply_ = manager_->get(request); connect(reply_, &QNetworkReply::finished, this, &KeyServerImportTask::dealing_reply_from_server); } diff --git a/src/ui/thread/KeyServerSearchTask.cpp b/src/ui/thread/KeyServerSearchTask.cpp index 2f05b774..828ce5ac 100644 --- a/src/ui/thread/KeyServerSearchTask.cpp +++ b/src/ui/thread/KeyServerSearchTask.cpp @@ -28,6 +28,8 @@ #include "ui/thread/KeyServerSearchTask.h" +#include "core/utils/BuildInfoUtils.h" + GpgFrontend::UI::KeyServerSearchTask::KeyServerSearchTask(QString keyserver_url, QString search_string) : Task("key_server_search_task"), @@ -42,7 +44,11 @@ auto GpgFrontend::UI::KeyServerSearchTask::Run() -> int { "/pks/lookup?search=" + search_string_ + "&op=index&options=mr"; - reply_ = manager_->get(QNetworkRequest(url_from_remote)); + auto request = QNetworkRequest(url_from_remote); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); + + reply_ = manager_->get(request); connect(reply_, &QNetworkReply::finished, this, &KeyServerSearchTask::dealing_reply_from_server); diff --git a/src/ui/thread/ListedKeyServerTestTask.cpp b/src/ui/thread/ListedKeyServerTestTask.cpp index f50a66ab..5f7e2dca 100644 --- a/src/ui/thread/ListedKeyServerTestTask.cpp +++ b/src/ui/thread/ListedKeyServerTestTask.cpp @@ -29,7 +29,8 @@ #include "ListedKeyServerTestTask.h" #include <QtNetwork> -#include <vector> + +#include "core/utils/BuildInfoUtils.h" GpgFrontend::UI::ListedKeyServerTestTask::ListedKeyServerTestTask( QStringList urls, int timeout, QWidget* /*parent*/) @@ -49,7 +50,11 @@ auto GpgFrontend::UI::ListedKeyServerTestTask::Run() -> int { auto key_url = QUrl{url}; GF_UI_LOG_DEBUG("key server request: {}", key_url.host()); - auto* network_reply = network_manager_->get(QNetworkRequest{key_url}); + auto request = QNetworkRequest(key_url); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); + + auto* network_reply = network_manager_->get(request); auto* timer = new QTimer(this); connect(network_reply, &QNetworkReply::finished, this, diff --git a/src/ui/thread/ProxyConnectionTestTask.cpp b/src/ui/thread/ProxyConnectionTestTask.cpp index b681ca6d..c1d2f3e6 100644 --- a/src/ui/thread/ProxyConnectionTestTask.cpp +++ b/src/ui/thread/ProxyConnectionTestTask.cpp @@ -30,6 +30,8 @@ #include <QtNetwork> +#include "core/utils/BuildInfoUtils.h" + GpgFrontend::UI::ProxyConnectionTestTask::ProxyConnectionTestTask(QString url, int timeout) : Task("proxy_connection_test_task"), @@ -40,7 +42,11 @@ GpgFrontend::UI::ProxyConnectionTestTask::ProxyConnectionTestTask(QString url, } auto GpgFrontend::UI::ProxyConnectionTestTask::Run() -> int { - auto* network_reply = network_manager_->get(QNetworkRequest{url_}); + auto request = QNetworkRequest(url_); + request.setHeader(QNetworkRequest::UserAgentHeader, + GetHttpRequestUserAgent()); + + auto* network_reply = network_manager_->get(request); auto* timer = new QTimer(this); connect(network_reply, &QNetworkReply::finished, this, diff --git a/src/ui/widgets/FileTreeView.cpp b/src/ui/widgets/FileTreeView.cpp index 7a725e10..de22ec83 100644 --- a/src/ui/widgets/FileTreeView.cpp +++ b/src/ui/widgets/FileTreeView.cpp @@ -54,6 +54,10 @@ FileTreeView::FileTreeView(QWidget* parent, const QString& target_path) &FileTreeView::slot_show_custom_context_menu); connect(this, &QTreeView::doubleClicked, this, &FileTreeView::slot_file_tree_view_item_double_clicked); + connect(dir_model_, &QFileSystemModel::layoutChanged, this, + &FileTreeView::slot_adjust_column_widths); + connect(dir_model_, &QFileSystemModel::dataChanged, this, + &FileTreeView::slot_adjust_column_widths); } void FileTreeView::selectionChanged(const QItemSelection& selected, @@ -82,9 +86,7 @@ void FileTreeView::SlotGoPath(const QString& target_path) { GF_UI_LOG_DEBUG("file tree view set target path: {}", current_path_); this->setRootIndex(dir_model_->index(file_info.filePath())); dir_model_->setRootPath(file_info.filePath()); - for (int i = 1; i < dir_model_->columnCount(); ++i) { - this->resizeColumnToContents(i); - } + slot_adjust_column_widths(); } else { QMessageBox::critical( this, tr("Error"), @@ -413,12 +415,21 @@ void FileTreeView::slot_compress_files() {} void FileTreeView::paintEvent(QPaintEvent* event) { QTreeView::paintEvent(event); - for (int i = 1; i < dir_model_->columnCount(); ++i) { - this->resizeColumnToContents(i); + + if (!initial_resize_done_) { + slot_adjust_column_widths(); + initial_resize_done_ = true; } } void FileTreeView::mousePressEvent(QMouseEvent* event) { QTreeView::mousePressEvent(event); } + +void FileTreeView::slot_adjust_column_widths() { + for (int i = 1; i < dir_model_->columnCount(); ++i) { + this->resizeColumnToContents(i); + } +} + } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/FileTreeView.h b/src/ui/widgets/FileTreeView.h index cd3b1cb8..67ce49ef 100644 --- a/src/ui/widgets/FileTreeView.h +++ b/src/ui/widgets/FileTreeView.h @@ -147,7 +147,7 @@ class FileTreeView : public QTreeView { * @brief * */ - auto SlotDeleteSelectedItem() -> void; + void SlotDeleteSelectedItem(); /** * @brief @@ -219,6 +219,12 @@ class FileTreeView : public QTreeView { */ void slot_create_popup_menu(); + /** + * @brief + * + */ + void slot_adjust_column_widths(); + private: QFileSystemModel* dir_model_; ///< QString current_path_; ///< @@ -233,5 +239,7 @@ class FileTreeView : public QTreeView { QAction* action_create_empty_file_; QAction* action_make_directory_; QAction* action_compress_files_; + + bool initial_resize_done_ = false; }; } // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/GRTTreeView.cpp b/src/ui/widgets/GRTTreeView.cpp new file mode 100644 index 00000000..09d7dcf0 --- /dev/null +++ b/src/ui/widgets/GRTTreeView.cpp @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GRTTreeView.h" + +#include "core/module/GlobalRegisterTableTreeModel.h" +#include "core/module/ModuleManager.h" + +namespace GpgFrontend::UI { + +GRTTreeView::GRTTreeView(QWidget* parent) : QTreeView(parent) { + setModel(new Module::GlobalRegisterTableTreeModel( + Module::ModuleManager::GetInstance().GRT())); + + connect(model(), &QFileSystemModel::layoutChanged, this, + &GRTTreeView::slot_adjust_column_widths); + connect(model(), &QFileSystemModel::dataChanged, this, + &GRTTreeView::slot_adjust_column_widths); + connect(this, &GRTTreeView::expanded, this, + &GRTTreeView::slot_adjust_column_widths); + connect(this, &GRTTreeView::collapsed, this, + &GRTTreeView::slot_adjust_column_widths); +} + +GRTTreeView::~GRTTreeView() = default; + +void GRTTreeView::paintEvent(QPaintEvent* event) { + QTreeView::paintEvent(event); + + if (!initial_resize_done_) { + slot_adjust_column_widths(); + initial_resize_done_ = true; + } +} + +void GRTTreeView::slot_adjust_column_widths() { + for (int i = 0; i < model()->columnCount(); ++i) { + this->resizeColumnToContents(i); + } +} +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/GRTTreeView.h b/src/ui/widgets/GRTTreeView.h new file mode 100644 index 00000000..6f3f83c8 --- /dev/null +++ b/src/ui/widgets/GRTTreeView.h @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +namespace GpgFrontend::UI { + +class GRTTreeView : public QTreeView { + Q_OBJECT + public: + /** + * @brief Construct a new GRTTreeView object + * + * @param parent + */ + explicit GRTTreeView(QWidget* parent); + + /** + * @brief Destroy the GRTTreeView object + * + */ + virtual ~GRTTreeView() override; + + protected: + /** + * @brief + * + * @param event + */ + void paintEvent(QPaintEvent* event) override; + + private slots: + + /** + * @brief + * + */ + void slot_adjust_column_widths(); + + private: + bool initial_resize_done_ = false; +}; + +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp index d1a006c5..425e6ccd 100644 --- a/src/ui/widgets/InfoBoardWidget.cpp +++ b/src/ui/widgets/InfoBoardWidget.cpp @@ -29,9 +29,9 @@ #include "ui/widgets/InfoBoardWidget.h" #include "core/GpgModel.h" +#include "core/model/SettingsObject.h" #include "ui/UISignalStation.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/AppearanceSO.h" +#include "ui/struct/settings_object/AppearanceSO.h" #include "ui_InfoBoard.h" namespace GpgFrontend::UI { diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index 48c99269..be79a6fd 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -231,7 +231,7 @@ auto KeyList::GetAllPrivateKeys() -> KeyIdArgsListPtr { return ret; } -auto KeyList::GetPrivateChecked() -> KeyIdArgsListPtr { +auto KeyList::GetCheckedPrivateKey() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; @@ -242,7 +242,27 @@ auto KeyList::GetPrivateChecked() -> KeyIdArgsListPtr { for (int i = 0; i < key_list->rowCount(); i++) { if ((key_list->item(i, 0)->checkState() == Qt::Checked) && - ((key_list->item(i, 1)) != nullptr)) { + ((key_list->item(i, 1)) != nullptr) && + buffered_keys[i].IsPrivateKey()) { + ret->push_back(buffered_keys[i].GetId()); + } + } + return ret; +} + +auto KeyList::GetCheckedPublicKey() -> KeyIdArgsListPtr { + auto ret = std::make_unique<KeyIdArgsList>(); + if (ui_->keyGroupTab->size().isEmpty()) return ret; + + auto* key_list = + qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); + const auto& buffered_keys = + m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + + for (int i = 0; i < key_list->rowCount(); i++) { + if ((key_list->item(i, 0)->checkState() == Qt::Checked) && + ((key_list->item(i, 1)) != nullptr) && + !buffered_keys[i].IsPrivateKey()) { ret->push_back(buffered_keys[i].GetId()); } } @@ -458,14 +478,28 @@ void KeyList::slot_refresh_ui() { } void KeyList::slot_sync_with_key_server() { + auto checked_public_keys = GetCheckedPublicKey(); + KeyIdArgsList key_ids; - { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); - for (const auto& key : *buffered_keys_list_) { - if (!(key.IsPrivateKey() && key.IsHasMasterKey())) { - key_ids.push_back(key.GetId()); + if (checked_public_keys->empty()) { + QMessageBox::StandardButton const reply = QMessageBox::question( + this, QCoreApplication::tr("Sync All Public Key"), + QCoreApplication::tr("You have not checked any public keys that you " + "want to synchronize, do you want to synchronize " + "all local public keys from the key server?"), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::No) return; + { + std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); + for (const auto& key : *buffered_keys_list_) { + if (!(key.IsPrivateKey() && key.IsHasMasterKey())) { + key_ids.push_back(key.GetId()); + } } } + } else { + key_ids = *checked_public_keys; } if (key_ids.empty()) return; diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h index 25180496..1761fb23 100644 --- a/src/ui/widgets/KeyList.h +++ b/src/ui/widgets/KeyList.h @@ -188,7 +188,7 @@ class KeyList : public QWidget { const QString& name, const QString& id, KeyListRow::KeyType selectType = KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::InfoType infoType = KeyListColumn::ALL, - const KeyTable::KeyTableFilter filter = + KeyTable::KeyTableFilter filter = [](const GpgKey&, const KeyTable&) -> bool { return true; }); /** @@ -225,7 +225,7 @@ class KeyList : public QWidget { * * @return KeyIdArgsListPtr */ - KeyIdArgsListPtr GetChecked(); + auto GetChecked() -> KeyIdArgsListPtr; /** * @brief Get the Checked object @@ -233,21 +233,28 @@ class KeyList : public QWidget { * @param key_table * @return KeyIdArgsListPtr */ - static KeyIdArgsListPtr GetChecked(const KeyTable& key_table); + static auto GetChecked(const KeyTable& key_table) -> KeyIdArgsListPtr; /** * @brief Get the Private Checked object * * @return KeyIdArgsListPtr */ - KeyIdArgsListPtr GetPrivateChecked(); + auto GetCheckedPrivateKey() -> KeyIdArgsListPtr; + + /** + * @brief + * + * @return KeyIdArgsListPtr + */ + auto GetCheckedPublicKey() -> KeyIdArgsListPtr; /** * @brief Get the All Private Keys object * * @return KeyIdArgsListPtr */ - KeyIdArgsListPtr GetAllPrivateKeys(); + auto GetAllPrivateKeys() -> KeyIdArgsListPtr; /** * @brief Set the Checked object @@ -270,14 +277,14 @@ class KeyList : public QWidget { * * @return KeyIdArgsListPtr */ - KeyIdArgsListPtr GetSelected(); + auto GetSelected() -> KeyIdArgsListPtr; /** * @brief Get the Selected Key object * * @return QString */ - QString GetSelectedKey(); + auto GetSelectedKey() -> QString; /** * @brief @@ -285,7 +292,7 @@ class KeyList : public QWidget { * @return true * @return false */ - [[maybe_unused]] bool ContainsPrivateKeys(); + [[maybe_unused]] auto ContainsPrivateKeys() -> bool; signals: /** diff --git a/src/ui/widgets/ModuleListView.cpp b/src/ui/widgets/ModuleListView.cpp new file mode 100644 index 00000000..ced602fb --- /dev/null +++ b/src/ui/widgets/ModuleListView.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "ModuleListView.h" + +#include "core/module/ModuleManager.h" + +namespace GpgFrontend::UI { + +ModuleListView::ModuleListView(QWidget *parent) + : QListView(parent), model_(new QStandardItemModel(this)) { + setModel(model_); + setEditTriggers(QAbstractItemView::NoEditTriggers); + + load_module_informations(); +} + +void ModuleListView::currentChanged(const QModelIndex ¤t, + const QModelIndex &previous) { + QListView::currentChanged(current, previous); + auto *item = model_->itemFromIndex(current); + if (item != nullptr) { + emit this->SignalSelectModule(item->data(Qt::UserRole + 1).toString()); + } +} + +void ModuleListView::load_module_informations() { + auto &module_manager = Module::ModuleManager::GetInstance(); + auto module_ids = module_manager.ListAllRegisteredModuleID(); + + model_->clear(); + for (const auto &module_id : module_ids) { + auto module = module_manager.SearchModule(module_id); + auto integrated_module = module_manager.IsIntegratedModule(module_id); + auto meta_data = module->GetModuleMetaData(); + + auto *item = new QStandardItem((integrated_module ? "*" : "") + + meta_data.value("Name", module_id)); + + item->setData(module_id, Qt::UserRole + 1); + model_->appendRow(item); + } +} + +auto ModuleListView::GetCurrentModuleID() -> Module::ModuleIdentifier { + auto *item = model_->itemFromIndex(currentIndex()); + return item != nullptr ? item->data(Qt::UserRole + 1).toString() : ""; +} +}; // namespace GpgFrontend::UI diff --git a/src/ui/widgets/ModuleListView.h b/src/ui/widgets/ModuleListView.h new file mode 100644 index 00000000..0b294bbf --- /dev/null +++ b/src/ui/widgets/ModuleListView.h @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/module/Module.h" + +namespace GpgFrontend::UI { +class ModuleListView : public QListView { + Q_OBJECT + public: + explicit ModuleListView(QWidget *parent); + + auto GetCurrentModuleID() -> Module::ModuleIdentifier; + + signals: + void SignalSelectModule(Module::ModuleIdentifier); + + protected: + void currentChanged(const QModelIndex ¤t, + const QModelIndex &previous) override; + + private: + QStandardItemModel *model_; + + void load_module_informations(); +}; +}; // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/PlainTextEditorPage.cpp b/src/ui/widgets/PlainTextEditorPage.cpp index 8f4890cc..874bbf3b 100644 --- a/src/ui/widgets/PlainTextEditorPage.cpp +++ b/src/ui/widgets/PlainTextEditorPage.cpp @@ -28,10 +28,10 @@ #include "PlainTextEditorPage.h" +#include "core/model/SettingsObject.h" #include "core/thread/FileReadTask.h" #include "core/thread/TaskRunnerGetter.h" -#include "ui/struct/SettingsObject.h" -#include "ui/struct/settings/AppearanceSO.h" +#include "ui/struct/settings_object/AppearanceSO.h" #include "ui_PlainTextEditor.h" namespace GpgFrontend::UI { diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp index 1373c5d9..a0dba5f5 100644 --- a/src/ui/widgets/TextEdit.cpp +++ b/src/ui/widgets/TextEdit.cpp @@ -34,8 +34,8 @@ #include "core/GpgModel.h" #include "core/function/GlobalSettingStation.h" +#include "core/model/CacheObject.h" #include "ui/UISignalStation.h" -#include "ui/struct/CacheObject.h" namespace GpgFrontend::UI { @@ -261,7 +261,7 @@ void TextEdit::slot_remove_tab(int index) { * * If it returns false, the close event should be aborted. */ -bool TextEdit::maybe_save_current_tab(bool askToSave) { +auto TextEdit::maybe_save_current_tab(bool askToSave) -> bool { PlainTextEditorPage* page = SlotCurPageTextEdit(); // if this page is no textedit, there should be nothing to save if (page == nullptr) { @@ -304,8 +304,8 @@ bool TextEdit::maybe_save_current_tab(bool askToSave) { } auto TextEdit::MaybeSaveAnyTab() -> bool { - // get a list of all unsaved documents and their tabids - QHash<int, QString> unsaved_docs = this->UnsavedDocuments(); + // get a list of all unsaved documents and their tab ids + QHash<int, QString> const unsaved_docs = this->UnsavedDocuments(); /* * no unsaved documents, so app can be closed @@ -318,7 +318,7 @@ auto TextEdit::MaybeSaveAnyTab() -> bool { * and show normal unsaved doc dialog */ if (unsaved_docs.size() == 1) { - int modified_tab = unsaved_docs.keys().at(0); + int const modified_tab = unsaved_docs.keys().at(0); tab_widget_->setCurrentIndex(modified_tab); return maybe_save_current_tab(true); } |