aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2024-12-01 00:21:46 +0000
committersaturneric <[email protected]>2024-12-01 00:21:46 +0000
commiteeec34f66fac8ecb350cd8d683a5dd167c91e706 (patch)
tree61da717af5370e37963da1e21f9daae0dc426b00
parentfix: solve link errors on windows (diff)
parentfeat: improve windows release structure at nightly build (diff)
downloadGpgFrontend-eeec34f66fac8ecb350cd8d683a5dd167c91e706.tar.gz
GpgFrontend-eeec34f66fac8ecb350cd8d683a5dd167c91e706.zip
Merge branch 'dev/2.1.5/mingw' into develop
-rw-r--r--.github/workflows/testing-nightly.yml79
-rw-r--r--gpgfrontend.qrc11
m---------modules0
-rw-r--r--resource/lfs/icons/compress.pngbin0 -> 3906 bytes
-rw-r--r--resource/lfs/icons/decrypted.pngbin3620 -> 0 bytes
-rw-r--r--resource/lfs/icons/decrypted_verified.pngbin3935 -> 0 bytes
-rw-r--r--resource/lfs/icons/email.pngbin4582 -> 5517 bytes
-rw-r--r--resource/lfs/icons/encrypted.pngbin3288 -> 0 bytes
-rw-r--r--resource/lfs/icons/encrypted_signed.pngbin2837 -> 0 bytes
-rw-r--r--resource/lfs/icons/expand.pngbin0 -> 3589 bytes
-rw-r--r--resource/lfs/icons/export-email.pngbin0 -> 6148 bytes
-rw-r--r--resource/lfs/icons/file-browser.pngbin3652 -> 0 bytes
-rw-r--r--resource/lfs/icons/file-operator.pngbin0 -> 6401 bytes
-rw-r--r--resource/lfs/icons/file.pngbin4488 -> 2569 bytes
-rw-r--r--resource/lfs/icons/lock.pngbin0 -> 4711 bytes
-rw-r--r--resource/lfs/icons/misc_doc.pngbin1482 -> 2639 bytes
-rw-r--r--resource/lfs/icons/unlock.pngbin0 -> 4684 bytes
-rw-r--r--src/CMakeLists.txt66
-rw-r--r--src/cmd.cpp2
-rw-r--r--src/core/CMakeLists.txt7
-rw-r--r--src/core/GpgCoreInit.cpp11
-rw-r--r--src/core/function/CacheManager.cpp39
-rw-r--r--src/core/function/GlobalSettingStation.cpp80
-rw-r--r--src/core/function/gpg/GpgAdvancedOperator.cpp23
-rw-r--r--src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp3
-rw-r--r--src/core/model/GpgGenKeyInfo.cpp8
-rw-r--r--src/core/model/GpgSignResult.cpp6
-rw-r--r--src/core/model/GpgSignResult.h2
-rw-r--r--src/core/module/ModuleInit.cpp4
-rw-r--r--src/sdk/CMakeLists.txt7
-rw-r--r--src/sdk/GFSDKBasic.cpp2
-rw-r--r--src/sdk/GFSDKExtra.cpp2
-rw-r--r--src/sdk/GFSDKGpg.cpp208
-rw-r--r--src/sdk/GFSDKGpg.h106
-rw-r--r--src/sdk/GFSDKModule.cpp2
-rw-r--r--src/sdk/GFSDKUI.cpp78
-rw-r--r--src/sdk/GFSDKUI.h19
-rw-r--r--src/sdk/private/GFSDKPrivat.cpp (renamed from src/sdk/private/CommonUtils.cpp)37
-rw-r--r--src/sdk/private/GFSDKPrivat.h (renamed from src/sdk/private/CommonUtils.h)29
-rw-r--r--src/test/CMakeLists.txt7
-rw-r--r--src/ui/CMakeLists.txt7
-rw-r--r--src/ui/GpgFrontendUIInit.cpp2
-rw-r--r--src/ui/UIModuleManager.cpp25
-rw-r--r--src/ui/UIModuleManager.h38
-rw-r--r--src/ui/UserInterfaceUtils.cpp14
-rw-r--r--src/ui/UserInterfaceUtils.h9
-rw-r--r--src/ui/dialog/SignersPicker.cpp10
-rw-r--r--src/ui/dialog/SignersPicker.h6
-rw-r--r--src/ui/dialog/controller/GnuPGControllerDialog.cpp18
-rw-r--r--src/ui/dialog/controller/ModuleControllerDialog.cpp2
-rw-r--r--src/ui/main_window/GeneralMainWindow.cpp16
-rw-r--r--src/ui/main_window/GeneralMainWindow.h17
-rw-r--r--src/ui/main_window/MainWindow.cpp4
-rw-r--r--src/ui/main_window/MainWindow.h52
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp601
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp74
-rw-r--r--src/ui/main_window/MainWindowUI.cpp72
-rw-r--r--src/ui/widgets/EMailEditorPage.cpp43
-rw-r--r--src/ui/widgets/EMailEditorPage.h46
-rw-r--r--src/ui/widgets/FilePage.cpp4
-rw-r--r--src/ui/widgets/KeyList.cpp11
-rw-r--r--src/ui/widgets/KeyList.h7
-rw-r--r--src/ui/widgets/ModuleListView.cpp4
-rw-r--r--src/ui/widgets/ModuleListView.h2
-rw-r--r--src/ui/widgets/PlainTextEditorPage.h4
-rw-r--r--src/ui/widgets/TextEdit.cpp91
-rw-r--r--src/ui/widgets/TextEdit.h36
-rw-r--r--src/ui/widgets/TextEditTabWidget.cpp69
-rw-r--r--src/ui/widgets/TextEditTabWidget.h25
m---------third_party/qttranslations0
-rw-r--r--ui/EmailListEditor.ui70
-rw-r--r--ui/ModuleControllerDialog.ui2
-rw-r--r--ui/PlainTextEditor.ui8
-rw-r--r--ui/SendMailDialog.ui469
74 files changed, 1648 insertions, 1048 deletions
diff --git a/.github/workflows/testing-nightly.yml b/.github/workflows/testing-nightly.yml
index 5417c466..ed763293 100644
--- a/.github/workflows/testing-nightly.yml
+++ b/.github/workflows/testing-nightly.yml
@@ -31,6 +31,7 @@ on:
env:
BUILD_TYPE: Release
+ GNUPG_VERSION: "2.4.7"
jobs:
build:
@@ -164,16 +165,6 @@ jobs:
cd ${{github.workspace}}
if: matrix.os == 'ubuntu-20.04'
- - name: Build GpgME (Windows)
- shell: msys2 {0}
- run: |
- git clone --depth 1 --branch fix/1.18.0 https://git.bktus.com/GpgFrontend/gpgme.git ${{github.workspace}}/third_party/gpgme
- cd ${{github.workspace}}/third_party/gpgme
- ./autogen.sh
- ./configure --enable-maintainer-mode --enable-languages=cpp --disable-gpg-test && make -j4
- make install
- if: matrix.os == 'windows-2019'
-
- name: Build googletest (Linux)
run: |
git clone --depth 1 --branch v1.15.0 https://github.com/google/googletest.git ${{github.workspace}}/third_party/googletest
@@ -194,7 +185,7 @@ jobs:
- name: Build & Install Full SDK (Windows)
shell: msys2 {0}
run: |
- cygpath -u ${{github.workspace}}
+ cd $(cygpath -u "${{github.workspace}}")
mkdir build-full-sdk && cd build-full-sdk
cmake -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_TYPE_FULL_SDK=ON -DCMAKE_INSTALL_PREFIX=$MSYSTEM_PREFIX ..
cmake --build . --config ${{env.BUILD_TYPE}} -- -j 4
@@ -211,7 +202,7 @@ jobs:
- name: Build Integrated Modules (Windows)
shell: msys2 {0}
run: |
- cygpath -u ${{github.workspace}}
+ cd $(cygpath -u "${{github.workspace}}")
cd modules
mkdir build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_TYPE_STABLE=ON -DCMAKE_INSTALL_PREFIX=./artifacts ..
@@ -252,10 +243,10 @@ jobs:
ditto -c -k --keepParent ${{github.workspace}}/build/package/GpgFrontend.app ${{github.workspace}}/build/GpgFrontend.app.zip
hdiutil create ${{github.workspace}}/build/tmp.dmg -ov \
-volname "GpgFrontend" -fs HFS+ -srcfolder ${{github.workspace}}/build/package/
- mkdir ${{github.workspace}}/build/final-artifact
- create-dmg --codesign "${{secrets.GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}}" --volicon "${{github.workspace}}/resource/lfs/icns/GpgFrontend.icns" --volname GpgFrontend --app-drop-link 600 185 --window-size 800 400 ${{github.workspace}}/build/final-artifact/GpgFrontend.dmg ${{github.workspace}}/build/package/GpgFrontend.app
- mv ${{github.workspace}}/build/final-artifact/GpgFrontend.dmg \
- ${{github.workspace}}/build/final-artifact/GpgFrontend-${{env.sha_short}}.dmg
+ mkdir ${{github.workspace}}/build/upload-artifact
+ create-dmg --codesign "${{secrets.GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}}" --volicon "${{github.workspace}}/resource/lfs/icns/GpgFrontend.icns" --volname GpgFrontend --app-drop-link 600 185 --window-size 800 400 ${{github.workspace}}/build/upload-artifact/GpgFrontend.dmg ${{github.workspace}}/build/package/GpgFrontend.app
+ mv ${{github.workspace}}/build/upload-artifact/GpgFrontend.dmg \
+ ${{github.workspace}}/build/upload-artifact/GpgFrontend-${{env.sha_short}}.dmg
mv ${{github.workspace}}/build/GpgFrontend.app.zip \
${{github.workspace}}/build/GpgFrontend-${{env.sha_short}}.zip
if: matrix.os == 'macos-12'
@@ -281,8 +272,8 @@ jobs:
- name: Copy Modules & Package App Image (Linux)
run: |
cmake -E copy_directory ${{github.workspace}}/modules/build/artifacts/modules ${{github.workspace}}/build/artifacts/AppDir/usr/modules
- mkdir ${{github.workspace}}/build/final-artifact
- cd ${{github.workspace}}/build/final-artifact
+ mkdir ${{github.workspace}}/build/upload-artifact
+ cd ${{github.workspace}}/build/upload-artifact
wget -c -nv https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
chmod u+x linuxdeployqt-continuous-x86_64.AppImage
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
@@ -294,7 +285,7 @@ jobs:
- name: Configure CMake & Build Application (Windows)
shell: msys2 {0}
run: |
- cygpath -u ${{github.workspace}}
+ cd $(cygpath -u "${{github.workspace}}")
mkdir build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_TYPE_ONLY_APPLICATION=ON ..
cmake --build . --config ${{env.BUILD_TYPE}} -- -j 4
@@ -306,38 +297,74 @@ jobs:
echo "BUILD_TYPE_LOWER=$("${{env.BUILD_TYPE}}".ToLower())" >> $env:GITHUB_ENV
if: matrix.os == 'windows-2019'
+ - name: Download GnuPG Binary Release (Windows)
+ shell: msys2 {0}
+ run: |
+ export URL="https://ftp.bktus.com/GnuPG/${{env.GNUPG_VERSION}}"
+ export FILE="gnupg.zip"
+ export CHECKSUM_FILE="SHA256SUMS.txt"
+
+ cd $(cygpath -u "${{github.workspace}}")
+
+ mkdir -p build/downloads
+ curl -o build/downloads/$FILE $URL/$FILE
+ curl -o build/downloads/$CHECKSUM_FILE $URL/$CHECKSUM_FILE
+
+ CHECKSUM=$(grep "$FILE" build/downloads/$CHECKSUM_FILE | awk '{print $1}')
+ ACTUAL_CHECKSUM=$(sha256sum build/downloads/$FILE | awk '{print $1}')
+ echo "Expected Checksum: $CHECKSUM"
+ echo "Actual Checksum: $ACTUAL_CHECKSUM"
+ if [ "$CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
+ echo "Checksum verification failed!" >&2
+ exit 1
+ fi
+
+ mkdir -p build/artifacts
+ unzip build/downloads/$FILE -d build/artifacts/
+ ls -l build/artifacts/
+ if: matrix.os == 'windows-2019'
+
- name: Copy Modules & Package (Windows)
shell: msys2 {0}
run: |
- cygpath -u ${{github.workspace}}
+ cd $(cygpath -u "${{github.workspace}}")
+ cp PrivacyPolicy.md build/artifacts/
+ cp README.md build/artifacts/
+ cp SECURITY.md build/artifacts/
+ cp TRANSLATORS build/artifacts/
+ cp COPYING build/artifacts/
+ cp gpgfrontend.ico build/artifacts/bin/GpgFrontend.ico
+ touch build/artifacts/bin/PORTABLE.txt
mkdir -p build/artifacts/modules
cp -r modules/build/artifacts/bin/* build/artifacts/modules
cd build
- windeployqt-qt6 --no-translations --force ./artifacts/GpgFrontend.exe
- mkdir final-artifact
+ windeployqt-qt6 --no-translations --force ./artifacts/bin/libgpgfrontend_core.dll
+ windeployqt-qt6 --no-translations --force ./artifacts/bin/libgpgfrontend_ui.dll
+ windeployqt-qt6 --no-translations --force ./artifacts/bin/GpgFrontend.exe
+ mkdir upload-artifact
cd artifacts
- zip -r ../final-artifact/GpgFrontend-${{env.SHORT_SHA}}-x86_64.zip *
+ zip -r ../upload-artifact/GpgFrontend-${{env.SHORT_SHA}}-x86_64.zip *
if: matrix.os == 'windows-2019'
- name: Upload Artifact (Linux)
uses: actions/upload-artifact@master
with:
name: gpgfrontend-${{matrix.os}}-${{env.BUILD_TYPE_LOWER}}-${{env.SHORT_SHA}}
- path: ${{github.workspace}}/build/final-artifact/Gpg_Frontend*.AppImage*
+ path: ${{github.workspace}}/build/upload-artifact/Gpg_Frontend*.AppImage*
if: matrix.os == 'ubuntu-20.04'
- name: Upload Artifact (macOS)
uses: actions/upload-artifact@master
with:
name: gpgfrontend-${{matrix.os}}-${{env.BUILD_TYPE_LOWER}}-${{env.SHORT_SHA}}
- path: ${{github.workspace}}/build/final-artifact/*
+ path: ${{github.workspace}}/build/upload-artifact/*
if: matrix.os == 'macos-12'
- name: Upload Artifact (Windows)
uses: actions/upload-artifact@master
with:
name: gpgfrontend-${{matrix.os}}-${{env.BUILD_TYPE_LOWER}}-${{env.SHORT_SHA}}
- path: ${{github.workspace}}/build/final-artifact/*
+ path: ${{github.workspace}}/build/upload-artifact/*
if: matrix.os == 'windows-2019'
release:
needs: build
diff --git a/gpgfrontend.qrc b/gpgfrontend.qrc
index 4e904366..dea3c3f6 100644
--- a/gpgfrontend.qrc
+++ b/gpgfrontend.qrc
@@ -18,18 +18,18 @@
<file alias="button_paste.png">resource/lfs/icons/button_paste.png</file>
<file alias="button_delete.png">resource/lfs/icons/button_delete.png</file>
<file alias="configure.png">resource/lfs/icons/configure.png</file>
- <file alias="decrypted.png">resource/lfs/icons/decrypted.png</file>
<file alias="drafts.png">resource/lfs/icons/drafts.png</file>
<file alias="edit.png">resource/lfs/icons/edit.png</file>
<file alias="email.png">resource/lfs/icons/email.png</file>
- <file alias="encrypted.png">resource/lfs/icons/encrypted.png</file>
- <file alias="encrypted_signed.png">resource/lfs/icons/encrypted_signed.png</file>
- <file alias="decrypted_verified.png">resource/lfs/icons/decrypted_verified.png</file>
+ <file alias="lock.png">resource/lfs/icons/lock.png</file>
+ <file alias="unlock.png">resource/lfs/icons/unlock.png</file>
+ <file alias="expand.png">resource/lfs/icons/expand.png</file>
+ <file alias="compress.png">resource/lfs/icons/compress.png</file>
<file alias="exit.png">resource/lfs/icons/exit.png</file>
<file alias="export_key_to_file.png">resource/lfs/icons/export_key_to_file.png</file>
<file alias="file.png">resource/lfs/icons/file.png</file>
<file alias="fileencryption.png">resource/lfs/icons/fileencrytion.png</file>
- <file alias="file-browser.png">resource/lfs/icons/file-browser.png</file>
+ <file alias="file-operator.png">resource/lfs/icons/file-operator.png</file>
<file alias="fileopen.png">resource/lfs/icons/fileopen.png</file>
<file alias="fileprint.png">resource/lfs/icons/fileprint.png</file>
<file alias="filesave.png">resource/lfs/icons/filesave.png</file>
@@ -105,6 +105,7 @@
<file alias="publish.png">resource/lfs/icons/publish.png</file>
<file alias="email-check.png">resource/lfs/icons/email-check.png</file>
<file alias="email-open.png">resource/lfs/icons/email-open.png</file>
+ <file alias="export-email.png">resource/lfs/icons/export-email.png</file>
</qresource>
<qresource prefix="/test/key">
<file alias="pv1.key">resource/lfs/test/data/pv1.key</file>
diff --git a/modules b/modules
-Subproject d52d7d683f058f116c832624b2ec8a977017aae
+Subproject 419ab0972fff50187956e3b4139f786be877995
diff --git a/resource/lfs/icons/compress.png b/resource/lfs/icons/compress.png
new file mode 100644
index 00000000..38066f29
--- /dev/null
+++ b/resource/lfs/icons/compress.png
Binary files differ
diff --git a/resource/lfs/icons/decrypted.png b/resource/lfs/icons/decrypted.png
deleted file mode 100644
index 9fe6970a..00000000
--- a/resource/lfs/icons/decrypted.png
+++ /dev/null
Binary files differ
diff --git a/resource/lfs/icons/decrypted_verified.png b/resource/lfs/icons/decrypted_verified.png
deleted file mode 100644
index 5e45f625..00000000
--- a/resource/lfs/icons/decrypted_verified.png
+++ /dev/null
Binary files differ
diff --git a/resource/lfs/icons/email.png b/resource/lfs/icons/email.png
index f0517848..58c55528 100644
--- a/resource/lfs/icons/email.png
+++ b/resource/lfs/icons/email.png
Binary files differ
diff --git a/resource/lfs/icons/encrypted.png b/resource/lfs/icons/encrypted.png
deleted file mode 100644
index 45bbf696..00000000
--- a/resource/lfs/icons/encrypted.png
+++ /dev/null
Binary files differ
diff --git a/resource/lfs/icons/encrypted_signed.png b/resource/lfs/icons/encrypted_signed.png
deleted file mode 100644
index ffb57196..00000000
--- a/resource/lfs/icons/encrypted_signed.png
+++ /dev/null
Binary files differ
diff --git a/resource/lfs/icons/expand.png b/resource/lfs/icons/expand.png
new file mode 100644
index 00000000..04e8b33c
--- /dev/null
+++ b/resource/lfs/icons/expand.png
Binary files differ
diff --git a/resource/lfs/icons/export-email.png b/resource/lfs/icons/export-email.png
new file mode 100644
index 00000000..fcf87bbe
--- /dev/null
+++ b/resource/lfs/icons/export-email.png
Binary files differ
diff --git a/resource/lfs/icons/file-browser.png b/resource/lfs/icons/file-browser.png
deleted file mode 100644
index 29dba7e1..00000000
--- a/resource/lfs/icons/file-browser.png
+++ /dev/null
Binary files differ
diff --git a/resource/lfs/icons/file-operator.png b/resource/lfs/icons/file-operator.png
new file mode 100644
index 00000000..cab57a98
--- /dev/null
+++ b/resource/lfs/icons/file-operator.png
Binary files differ
diff --git a/resource/lfs/icons/file.png b/resource/lfs/icons/file.png
index d8562029..818f87af 100644
--- a/resource/lfs/icons/file.png
+++ b/resource/lfs/icons/file.png
Binary files differ
diff --git a/resource/lfs/icons/lock.png b/resource/lfs/icons/lock.png
new file mode 100644
index 00000000..76dd66c4
--- /dev/null
+++ b/resource/lfs/icons/lock.png
Binary files differ
diff --git a/resource/lfs/icons/misc_doc.png b/resource/lfs/icons/misc_doc.png
index 57878ba3..25d2eb55 100644
--- a/resource/lfs/icons/misc_doc.png
+++ b/resource/lfs/icons/misc_doc.png
Binary files differ
diff --git a/resource/lfs/icons/unlock.png b/resource/lfs/icons/unlock.png
new file mode 100644
index 00000000..228c8f7c
--- /dev/null
+++ b/resource/lfs/icons/unlock.png
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ba92ef27..0c9171e5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,13 +65,13 @@ 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 Binary Output Path
+if(XCODE_BUILD)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE})
+elseif(MINGW)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts/bin)
+else()
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts)
endif()
# Print modules
@@ -105,11 +105,14 @@ if(BUILD_APPLICATION)
set_property(SOURCE gpgfrontend.rc APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/gpgfrontend.ico)
endif()
+# Set Resource Output Path
if(BUILD_APPLICATION)
- # Set Resource Output Path
if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
if(APPLE)
set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Resources)
+ 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)
set(BUILD_APP_IMAGE 1)
else()
@@ -120,16 +123,6 @@ if(BUILD_APPLICATION)
endif()
endif()
-if(BUILD_APPLICATION)
- if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
- if(APPLE)
- set(GPGFRONTEND_MACOS_ICON ${CMAKE_SOURCE_DIR}/gpgfrontend.icns)
- set_source_files_properties(${GPGFRONTEND_MACOS_ICON} PROPERTIES
- MACOSX_PACKAGE_LOCATION "Resources")
- endif()
- endif()
-endif()
-
if(BUILD_APPLICATION AND MINGW)
message(STATUS "Copying Dependent DLL For Windows Runtime Env")
@@ -249,35 +242,19 @@ if(BUILD_APPLICATION AND MINGW)
file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libxml2-*.dll")
list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
- # /mingw64/libexec
- execute_process(
- COMMAND cygpath -m /mingw64/libexec
- OUTPUT_VARIABLE MSYS64_LIBEXEC_PATH
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- # gpgme-w32spawn.exe
- unset(_libExEPath)
- file(GLOB _libExEPath "${MSYS64_LIBEXEC_PATH}/gpgme-*.exe")
- list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath})
+ unset(_libDllPath)
+ file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libarchive*.dll")
+ list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
- unset(_libExEPath)
- file(GLOB _libExEPath "${MSYS64_BIN_PATH}/gpgme-*.exe")
- list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath})
+ unset(_libDllPath)
+ file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgtest*.dll")
+ list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
# add gpgfrontend libraries
if(STABLE_BUILD_ONLY_APPLICATION)
unset(_libDllPath)
file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgpgfrontend_*.dll")
list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
-
- unset(_libDllPath)
- file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libarchive*.dll")
- list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
-
- unset(_libDllPath)
- file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgtest*.dll")
- list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath})
endif()
# dll with only name
@@ -403,17 +380,6 @@ if(BUILD_APPLICATION)
else()
# if the status is debug
add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES})
-
- if(MINGW)
- # include qt dependencies
- if(NOT Qt6_DIR)
- add_custom_command(TARGET ${AppName} POST_BUILD
- COMMAND windeployqt --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe)
- else()
- add_custom_command(TARGET ${AppName} POST_BUILD
- COMMAND windeployqt-qt6.exe --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe)
- endif()
- endif()
endif()
# Make app build with resources
diff --git a/src/cmd.cpp b/src/cmd.cpp
index 2f972329..d56f1c8a 100644
--- a/src/cmd.cpp
+++ b/src/cmd.cpp
@@ -72,7 +72,7 @@ auto PrintVersion() -> int {
auto PrintEnvInfo() -> int {
QTextStream stream(stdout);
stream << GetProjectName() << " " << GetProjectVersion() << " "
- << "Environemnt Informations:" << '\n';
+ << "Environemnt Information:" << '\n';
stream << '\n';
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 90409e22..3ce199e5 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -92,13 +92,6 @@ target_precompile_headers(gpgfrontend_core
# using std c++ 17
target_compile_features(gpgfrontend_core PUBLIC cxx_std_17)
-if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
- # lib output path
- set_target_properties(gpgfrontend_core PROPERTIES
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib)
-endif()
-
# link for different platforms
if(MINGW)
message(STATUS "Link GPG Static Library For MINGW")
diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp
index e761b857..34ac866b 100644
--- a/src/core/GpgCoreInit.cpp
+++ b/src/core/GpgCoreInit.cpp
@@ -124,6 +124,17 @@ auto InitGpgME() -> bool {
return false;
}
+#if defined(_WIN32) || defined(WIN32)
+ auto w32spawn_dir =
+ GlobalSettingStation::GetInstance().GetAppDir() + "/../gnupg/bin";
+ if (gpgme_set_global_flag("w32-inst-dir",
+ w32spawn_dir.toUtf8().constData()) != 0) {
+ LOG_E() << "gpgme_set_global_flag() with argument 'w32spawn_dir' failed, "
+ "abort...";
+ return false;
+ }
+#endif
+
if (CheckGpgError(
gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr))) !=
GPG_ERR_NO_ERROR) {
diff --git a/src/core/function/CacheManager.cpp b/src/core/function/CacheManager.cpp
index d54d0fac..5670819b 100644
--- a/src/core/function/CacheManager.cpp
+++ b/src/core/function/CacheManager.cpp
@@ -110,6 +110,7 @@ class CacheManager::Impl : public QObject {
key_storage_.push_back(key);
}
+ durable_cache_modified_ = true;
if (flush) slot_flush_cache_storage();
}
@@ -118,6 +119,7 @@ class CacheManager::Impl : public QObject {
if (!durable_cache_storage_.exists(key)) {
durable_cache_storage_.insert(key, load_cache_storage(key, {}));
+ durable_cache_modified_ = true;
}
auto cache = durable_cache_storage_.get(key);
@@ -131,6 +133,7 @@ class CacheManager::Impl : public QObject {
if (!durable_cache_storage_.exists(key)) {
durable_cache_storage_.insert(
key, load_cache_storage(key, std::move(default_value)));
+ durable_cache_modified_ = true;
}
auto cache = durable_cache_storage_.get(key);
@@ -140,6 +143,7 @@ class CacheManager::Impl : public QObject {
auto ResetDurableCache(const QString& key) -> bool {
auto data_object_key = get_data_object_key(key);
+ durable_cache_modified_ = true;
return durable_cache_storage_.remove(key);
}
@@ -188,7 +192,9 @@ class CacheManager::Impl : public QObject {
*
*/
void slot_flush_cache_storage() {
- FLOG_D("write cache to file system...");
+ if (!durable_cache_modified_) return;
+
+ FLOG_D("update durable cache to disk...");
for (const auto& cache : durable_cache_storage_.mirror()) {
auto key = get_data_object_key(cache.first);
@@ -197,23 +203,11 @@ class CacheManager::Impl : public QObject {
}
GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(
drk_key_, QJsonDocument(key_storage_));
+
+ durable_cache_modified_ = false;
}
private:
- struct CacheObject {
- QString value;
- qint64 ttl;
-
- CacheObject(QString value, qint64 ttl)
- : value(std::move(value)), ttl(ttl) {}
- };
-
- QCache<QString, CacheObject> runtime_cache_storage_;
- ThreadSafeMap<QString, QJsonDocument> durable_cache_storage_;
- QJsonArray key_storage_;
- QTimer* flush_timer_;
- const QString drk_key_ = "__cache_manage_data_register_key_list";
-
/**
* @brief Get the data object key object
*
@@ -273,6 +267,21 @@ class CacheManager::Impl : public QObject {
* @param key
*/
void register_cache_key(const QString& key) {}
+
+ struct CacheObject {
+ QString value;
+ qint64 ttl;
+
+ CacheObject(QString value, qint64 ttl)
+ : value(std::move(value)), ttl(ttl) {}
+ };
+
+ QCache<QString, CacheObject> runtime_cache_storage_;
+ ThreadSafeMap<QString, QJsonDocument> durable_cache_storage_;
+ QJsonArray key_storage_;
+ QTimer* flush_timer_;
+ const QString drk_key_ = "__cache_manage_data_register_key_list";
+ std::atomic<bool> durable_cache_modified_{};
};
CacheManager::CacheManager(int channel)
diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp
index 42aced01..367437da 100644
--- a/src/core/function/GlobalSettingStation.cpp
+++ b/src/core/function/GlobalSettingStation.cpp
@@ -40,22 +40,23 @@ class GlobalSettingStation::Impl {
*
*/
explicit Impl() noexcept {
- LOG_I() << "app path: " << GetAppDir();
+ LOG_I() << "app path: " << app_path_;
LOG_I() << "app working path: " << working_path_;
auto portable_file_path = working_path_ + "/PORTABLE.txt";
if (QFileInfo(portable_file_path).exists()) {
Module::UpsertRTValue("core", "env.state.portable", 1);
+ LOG_I() << "GpgFrontend runs in the portable mode now";
- app_data_path_ = working_path_;
- app_log_path_ = app_data_path_ + "/logs";
- app_data_objs_path_ = app_data_path_ + "/data_objs";
+ app_data_path_ = app_path_ + "/../";
+ app_config_path_ = app_data_path_ + "/config";
portable_mode_ = true;
}
LOG_I() << "app data path: " << app_data_path_;
- LOG_I() << "app log path: " << app_log_path_;
+ LOG_I() << "app log path: " << app_log_path();
+ LOG_I() << "app modules path: " << app_modules_path();
#if defined(_WIN32) || defined(WIN32)
LOG_I() << "app config path: " << app_config_path_;
@@ -63,36 +64,35 @@ class GlobalSettingStation::Impl {
#endif
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(".");
+ if (!QDir(app_log_path()).exists()) QDir(app_log_path()).mkpath(".");
+ if (!QDir(app_modules_path()).exists()) {
+ QDir(app_modules_path()).mkpath(".");
+ }
}
[[nodiscard]] auto GetSettings() -> QSettings {
- if (!portable_mode_) {
#if defined(_WIN32) || defined(WIN32)
- return QSettings(app_config_target_path_, QSettings::IniFormat);
+ return QSettings(app_config_file_path(), QSettings::IniFormat);
#else
- return QSettings();
+ return QSettings();
#endif
- }
- return {app_portable_config_path_, QSettings::IniFormat};
}
[[nodiscard]] auto GetLogFilesSize() const -> QString {
- return GetHumanFriendlyFileSize(GetFileSizeByPath(app_log_path_, "*.log"));
+ return GetHumanFriendlyFileSize(GetFileSizeByPath(app_log_path(), "*.log"));
}
[[nodiscard]] auto GetDataObjectsFilesSize() const -> QString {
return GetHumanFriendlyFileSize(
- GetFileSizeByPath(app_data_objs_path_, "*"));
+ GetFileSizeByPath(app_data_objs_path(), "*"));
}
void ClearAllLogFiles() const {
- DeleteAllFilesByPattern(app_log_path_, "*.log");
+ DeleteAllFilesByPattern(app_log_path(), "*.log");
}
void ClearAllDataObjects() const {
- DeleteAllFilesByPattern(app_data_objs_path_, "*");
+ DeleteAllFilesByPattern(app_data_objs_path(), "*");
}
/**
@@ -100,9 +100,7 @@ class GlobalSettingStation::Impl {
*
* @return QString
*/
- [[nodiscard]] auto GetAppDir() const -> QString {
- return QCoreApplication::applicationDirPath();
- }
+ [[nodiscard]] auto GetAppDir() const -> QString { return app_path_; }
/**
* @brief Get the App Data Path object
@@ -118,7 +116,7 @@ class GlobalSettingStation::Impl {
*
* @return QString
*/
- [[nodiscard]] auto GetLogDir() const -> QString { return app_log_path_; }
+ [[nodiscard]] auto GetLogDir() const -> QString { return app_log_path(); }
/**
* @brief Get the Modules Dir object
@@ -126,35 +124,33 @@ class GlobalSettingStation::Impl {
* @return QString
*/
[[nodiscard]] auto GetModulesDir() const -> QString {
- return GetAppDataPath() + "/mods";
+ return app_modules_path();
}
private:
- QString working_path_ = QDir::currentPath();
-
- QString app_data_path_ = QString{QStandardPaths::writableLocation(
- QStandardPaths::AppLocalDataLocation)}; ///< Program Data Location
-
- QString app_config_path_ = QString{
- QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)};
-
- QString app_log_path_ = app_data_path_ + "/logs"; ///< Program Data Location
+ [[nodiscard]] auto app_config_file_path() const -> QString {
+ return app_config_path_ + "/config.ini";
+ }
- QString app_data_objs_path_ =
- app_data_path_ + "/data_objs"; ///< Object storage path
+ [[nodiscard]] auto app_data_objs_path() const -> QString {
+ return app_data_path_ + "/data_objs";
+ }
- QString app_config_target_path_ =
- app_config_path_ + "/config.ini"; ///< take effect only in portable mode
+ [[nodiscard]] auto app_log_path() const -> QString {
+ return app_data_path_ + "/logs";
+ }
- bool portable_mode_ = false; ///<
- QString app_portable_config_path_ =
- working_path_ + "/config.ini"; ///< take effect only in portable mode
+ [[nodiscard]] auto app_modules_path() const -> QString {
+ return app_data_path_ + "/mods";
+ }
- /**
- * @brief
- *
- */
- void init_app_secure_key() {}
+ bool portable_mode_ = false;
+ const QString app_path_ = QCoreApplication::applicationDirPath();
+ QString working_path_ = QDir::currentPath();
+ QString app_data_path_ = QString{
+ QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)};
+ QString app_config_path_ = QString{
+ QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)};
};
GlobalSettingStation::GlobalSettingStation(int channel) noexcept
diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp
index a742b60a..4a373f0a 100644
--- a/src/core/function/gpg/GpgAdvancedOperator.cpp
+++ b/src/core/function/gpg/GpgAdvancedOperator.cpp
@@ -120,20 +120,23 @@ void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents() {
FLOG_D("gpgconf --kill --all execute result: %d", success);
if (!success) {
- FLOG_W("restart all component after core initilized failed");
+ FLOG_W("restart all component after core initalized failed");
Module::UpsertRTValue(
"core", "gpg_advanced_operator.restart_gpg_components", false);
return;
}
- // StartGpgAgent([](int err, DataObjectPtr) {
- // if (err >= 0) {
- // Module::UpsertRTValue(
- // "core", "gpg_advanced_operator.restart_gpg_components",
- // true);
- // return;
- // }
- // });
+#if defined(__APPLE__) && defined(__MACH__)
+ FLOG_I("getting gpg-agent to start automatically on macOS");
+#else
+ StartGpgAgent([](int err, DataObjectPtr) {
+ if (err >= 0) {
+ Module::UpsertRTValue(
+ "core", "gpg_advanced_operator.restart_gpg_components", true);
+ return;
+ }
+ });
+#endif
}});
}
@@ -176,7 +179,7 @@ void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) {
GpgFrontend::GpgCommandExecutor::ExecuteSync(
{gpg_agent_path, QStringList{"--homedir", home_path, "--daemon"},
[=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpgconf daemon exit code: %d", exit_code);
+ FLOG_D("gpg-agent daemon exit code: %d", exit_code);
cb(exit_code >= 0 ? 0 : -1, TransferParams());
}});
}
diff --git a/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp b/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp
index e569dc3f..6e948705 100644
--- a/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp
+++ b/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp
@@ -80,9 +80,6 @@ void GpgFrontend::GpgDecryptResultAnalyse::doAnalyse() {
<< Qt::endl;
}
- stream_ << "- " << tr("German Encryption Standards") << ": "
- << (result->is_de_vs == 0 ? tr("false") : tr("true")) << Qt::endl;
-
stream_ << Qt::endl << Qt::endl;
auto *recipient = result->recipients;
diff --git a/src/core/model/GpgGenKeyInfo.cpp b/src/core/model/GpgGenKeyInfo.cpp
index 1514c3bc..1aaa4cea 100644
--- a/src/core/model/GpgGenKeyInfo.cpp
+++ b/src/core/model/GpgGenKeyInfo.cpp
@@ -232,7 +232,7 @@ auto GenKeyInfo::GetSupportedKeyAlgo()
k_support_key_algo = {
{"RSA", "RSA", ""},
{"DSA", "DSA", ""},
- {"ECDSA (ED25519)", "ED25519", ""},
+ {"EdDSA (ED25519)", "ED25519", ""},
{"ECDSA (NIST P-256)", "NISTP256", ""},
{"ECDSA (NIST P-384)", "NISTP384", ""},
{"ECDSA (NIST P-521)", "NISTP521", ""},
@@ -242,7 +242,7 @@ auto GenKeyInfo::GetSupportedKeyAlgo()
{"RSA", "RSA", ""},
{"DSA", "DSA", ""},
{"EdDSA (ED448)", "ED448", ""},
- {"ECDSA (ED25519)", "ED25519", ""},
+ {"EdDSA (ED25519)", "ED25519", ""},
{"ECDSA (SECP256K1)", "SECP256K1", ""},
{"ECDSA (NIST P-256)", "NISTP256", ""},
{"ECDSA (NIST P-384)", "NISTP384", ""},
@@ -278,7 +278,7 @@ auto GenKeyInfo::GetSupportedSubkeyAlgo()
{"RSA", "", "RSA"},
{"DSA", "", "DSA"},
{"ELG-E", "", "ELG"},
- {"ECDSA (ED25519)", "", "ED25519"},
+ {"EdDSA (ED25519)", "", "ED25519"},
{"ECDH (CV25519)", "", "CV25519"},
{"ECDH (NIST P-256)", "", "NISTP256"},
{"ECDH (NIST P-384)", "", "NISTP384"},
@@ -289,7 +289,7 @@ auto GenKeyInfo::GetSupportedSubkeyAlgo()
{"RSA", "", "RSA"},
{"DSA", "", "DSA"},
{"ELG-E", "", "ELG"},
- {"ECDSA (ED25519)", "", "ED25519"},
+ {"EdDSA (ED25519)", "", "ED25519"},
{"ECDH (CV25519)", "", "CV25519"},
{"ECDH (SECP256K1)", "", "SECP256K1"},
{"EdDSA (ED448)", "", "ED448"},
diff --git a/src/core/model/GpgSignResult.cpp b/src/core/model/GpgSignResult.cpp
index 1819c22b..59c402dd 100644
--- a/src/core/model/GpgSignResult.cpp
+++ b/src/core/model/GpgSignResult.cpp
@@ -27,7 +27,6 @@
*/
#include "GpgSignResult.h"
-
namespace GpgFrontend {
GpgSignResult::GpgSignResult(gpgme_sign_result_t r)
: result_ref_(std::shared_ptr<struct _gpgme_op_sign_result>(
@@ -62,4 +61,9 @@ auto GpgSignResult::InvalidSigners()
}
return result;
}
+
+auto GpgSignResult::HashAlgo() -> QString {
+ if (result_ref_->signatures == nullptr) return {};
+ return gpgme_hash_algo_name(result_ref_->signatures->hash_algo);
+}
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/model/GpgSignResult.h b/src/core/model/GpgSignResult.h
index a7356c65..3881c86f 100644
--- a/src/core/model/GpgSignResult.h
+++ b/src/core/model/GpgSignResult.h
@@ -39,6 +39,8 @@ class GPGFRONTEND_CORE_EXPORT GpgSignResult {
auto GetRaw() -> gpgme_sign_result_t;
+ auto HashAlgo() -> QString;
+
auto InvalidSigners() -> std::vector<std::tuple<QString, GpgError>>;
explicit GpgSignResult(gpgme_sign_result_t);
diff --git a/src/core/module/ModuleInit.cpp b/src/core/module/ModuleInit.cpp
index 972e7025..175d35ad 100644
--- a/src/core/module/ModuleInit.cpp
+++ b/src/core/module/ModuleInit.cpp
@@ -49,8 +49,8 @@ auto SearchModuleFromPath(const QString& mods_path,
}
auto LoadIntegratedMods() -> QMap<QString, bool> {
- const auto exec_binary_path = QCoreApplication::applicationDirPath();
- QString mods_path = exec_binary_path + "/modules";
+ const auto exec_binary_path = GlobalSettingStation::GetInstance().GetAppDir();
+ QString mods_path = exec_binary_path + "/../modules";
#ifdef NDEBUG
diff --git a/src/sdk/CMakeLists.txt b/src/sdk/CMakeLists.txt
index 2e754584..de6d24a7 100644
--- a/src/sdk/CMakeLists.txt
+++ b/src/sdk/CMakeLists.txt
@@ -45,13 +45,6 @@ target_link_libraries(gpgfrontend_module_sdk PRIVATE gpgfrontend_core gpgfronten
file(GLOB _headerPath "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
set_target_properties(gpgfrontend_module_sdk PROPERTIES PUBLIC_HEADER "${_headerPath}")
-if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
- # lib output path
- set_target_properties(gpgfrontend_module_sdk PROPERTIES
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib)
-endif()
-
if(XCODE_BUILD)
set_target_properties(gpgfrontend_module_sdk
PROPERTIES
diff --git a/src/sdk/GFSDKBasic.cpp b/src/sdk/GFSDKBasic.cpp
index ed734bbe..1c7816d2 100644
--- a/src/sdk/GFSDKBasic.cpp
+++ b/src/sdk/GFSDKBasic.cpp
@@ -32,7 +32,7 @@
#include "core/function/SecureMemoryAllocator.h"
#include "core/function/gpg/GpgCommandExecutor.h"
#include "core/utils/BuildInfoUtils.h"
-#include "sdk/private/CommonUtils.h"
+#include "private/GFSDKPrivat.h"
#include "ui/UIModuleManager.h"
auto GFAllocateMemory(uint32_t size) -> void* {
diff --git a/src/sdk/GFSDKExtra.cpp b/src/sdk/GFSDKExtra.cpp
index 6a95a8f9..1c755389 100644
--- a/src/sdk/GFSDKExtra.cpp
+++ b/src/sdk/GFSDKExtra.cpp
@@ -31,7 +31,7 @@
#include <core/utils/BuildInfoUtils.h>
#include <core/utils/CommonUtils.h>
-#include "sdk/private/CommonUtils.h"
+#include "private/GFSDKPrivat.h"
auto GFCompareSoftwareVersion(const char *current_version,
const char *latest_version) -> int {
diff --git a/src/sdk/GFSDKGpg.cpp b/src/sdk/GFSDKGpg.cpp
index 88162ffa..52ea0520 100644
--- a/src/sdk/GFSDKGpg.cpp
+++ b/src/sdk/GFSDKGpg.cpp
@@ -24,4 +24,210 @@
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
- */ \ No newline at end of file
+ */
+
+#include "GFSDKGpg.h"
+
+#include "GFSDKBasic.h"
+#include "core/function/gpg/GpgBasicOperator.h"
+#include "core/function/gpg/GpgKeyGetter.h"
+#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "core/model/DataObject.h"
+#include "core/model/GpgDecryptResult.h"
+#include "core/model/GpgEncryptResult.h"
+#include "core/model/GpgSignResult.h"
+#include "core/model/GpgVerifyResult.h"
+#include "core/typedef/GpgTypedef.h"
+#include "core/utils/GpgUtils.h"
+#include "ui/UIModuleManager.h"
+
+//
+#include "private/GFSDKPrivat.h"
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgSignData(int channel, char** key_ids,
+ int key_ids_size, char* data,
+ int sign_mode, int ascii,
+ GFGpgSignResult** ps) -> int {
+ auto singer_ids = CharArrayToQList(key_ids, key_ids_size);
+
+ GpgFrontend::KeyArgsList signer_keys;
+ for (const auto& signer_id : singer_ids) {
+ auto key =
+ GpgFrontend::GpgKeyGetter::GetInstance(channel).GetKey(signer_id);
+ if (key.IsGood()) signer_keys.push_back(key);
+ }
+
+ if (signer_keys.empty()) return -1;
+
+ auto in_buffer = GpgFrontend::GFBuffer(GFUnStrDup(data).toUtf8());
+
+ auto gpg_sign_mode =
+ sign_mode == 0 ? GPGME_SIG_MODE_NORMAL : GPGME_SIG_MODE_DETACH;
+
+ auto [err, data_object] =
+ GpgFrontend::GpgBasicOperator::GetInstance(channel).SignSync(
+ signer_keys, in_buffer, gpg_sign_mode, ascii != 0);
+
+ *ps =
+ static_cast<GFGpgSignResult*>(GFAllocateMemory(sizeof(GFGpgSignResult)));
+ auto* s = *ps;
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return -1;
+ }
+
+ auto result =
+ GpgFrontend::ExtractParams<GpgFrontend::GpgSignResult>(data_object, 0);
+ auto out_buffer =
+ GpgFrontend::ExtractParams<GpgFrontend::GFBuffer>(data_object, 1);
+
+ auto capsule_id =
+ GpgFrontend::UI::UIModuleManager::GetInstance().MakeCapsule(result);
+
+ s->signature = GFStrDup(out_buffer.ConvertToQByteArray());
+ s->hash_algo = GFStrDup(result.HashAlgo());
+ s->capsule_id = GFStrDup(capsule_id);
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return 0;
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgPublicKey(int channel, char* key_id,
+ int ascii) -> char* {
+ auto key = GpgFrontend::GpgKeyGetter::GetInstance(channel).GetKey(
+ GFUnStrDup(key_id));
+
+ if (!key.IsGood()) return nullptr;
+
+ auto [err, buffer] =
+ GpgFrontend::GpgKeyImportExporter::GetInstance(channel).ExportKey(
+ key, false, ascii != 0, true);
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) return nullptr;
+
+ return GFStrDup(buffer.ConvertToQByteArray());
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgKeyPrimaryUID(int channel, char* key_id,
+ GFGpgKeyUID** ps) -> int {
+ auto key = GpgFrontend::GpgKeyGetter::GetInstance(channel).GetKey(
+ GFUnStrDup(key_id));
+
+ if (!key.IsGood()) return -1;
+
+ auto uids = key.GetUIDs();
+ auto& primary_uid = uids->front();
+
+ *ps = static_cast<GFGpgKeyUID*>(GFAllocateMemory(sizeof(GFGpgKeyUID)));
+
+ auto* s = *ps;
+ s->name = GFStrDup(primary_uid.GetName());
+ s->email = GFStrDup(primary_uid.GetEmail());
+ s->comment = GFStrDup(primary_uid.GetComment());
+ return 0;
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFGpgEncryptData(int channel, char** key_ids, int key_ids_size, char* data,
+ int ascii, GFGpgEncryptionResult** ps) -> int {
+ auto encrypt_key_ids = CharArrayToQList(key_ids, key_ids_size);
+
+ GpgFrontend::KeyArgsList encrypt_keys;
+ for (const auto& encrypt_key_id : encrypt_key_ids) {
+ auto key =
+ GpgFrontend::GpgKeyGetter::GetInstance(channel).GetKey(encrypt_key_id);
+ if (key.IsGood()) encrypt_keys.push_back(key);
+ }
+
+ if (encrypt_keys.empty()) return -1;
+
+ auto in_buffer = GpgFrontend::GFBuffer(GFUnStrDup(data).toUtf8());
+
+ auto [err, data_object] =
+ GpgFrontend::GpgBasicOperator::GetInstance(channel).EncryptSync(
+ encrypt_keys, in_buffer, ascii != 0);
+
+ *ps = static_cast<GFGpgEncryptionResult*>(
+ GFAllocateMemory(sizeof(GFGpgEncryptionResult)));
+ auto* s = *ps;
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return -1;
+ }
+
+ auto result =
+ GpgFrontend::ExtractParams<GpgFrontend::GpgEncryptResult>(data_object, 0);
+ auto out_buffer =
+ GpgFrontend::ExtractParams<GpgFrontend::GFBuffer>(data_object, 1);
+
+ auto capsule_id =
+ GpgFrontend::UI::UIModuleManager::GetInstance().MakeCapsule(result);
+
+ s->encrypted_data = GFStrDup(out_buffer.ConvertToQByteArray());
+ s->capsule_id = GFStrDup(capsule_id);
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return 0;
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFGpgDecryptData(int channel, char* data, GFGpgDecryptResult** ps) -> int {
+ auto in_buffer = GpgFrontend::GFBuffer(GFUnStrDup(data).toUtf8());
+
+ auto [err, data_object] =
+ GpgFrontend::GpgBasicOperator::GetInstance(channel).DecryptSync(
+ in_buffer);
+
+ *ps = static_cast<GFGpgDecryptResult*>(
+ GFAllocateMemory(sizeof(GFGpgDecryptResult)));
+ auto* s = *ps;
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return -1;
+ }
+
+ auto result =
+ GpgFrontend::ExtractParams<GpgFrontend::GpgDecryptResult>(data_object, 0);
+ auto out_buffer =
+ GpgFrontend::ExtractParams<GpgFrontend::GFBuffer>(data_object, 1);
+
+ auto capsule_id =
+ GpgFrontend::UI::UIModuleManager::GetInstance().MakeCapsule(result);
+
+ s->decrypted_data = GFStrDup(out_buffer.ConvertToQByteArray());
+ s->capsule_id = GFStrDup(capsule_id);
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return 0;
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgVerifyData(
+ int channel, char* data, char* signature, GFGpgVerifyResult** ps) -> int {
+ auto in_buffer = GpgFrontend::GFBuffer(GFUnStrDup(data).toUtf8());
+ auto sig_buffer = GpgFrontend::GFBuffer(GFUnStrDup(signature).toUtf8());
+
+ auto [err, data_object] =
+ GpgFrontend::GpgBasicOperator::GetInstance(channel).VerifySync(
+ in_buffer, sig_buffer);
+
+ *ps = static_cast<GFGpgVerifyResult*>(
+ GFAllocateMemory(sizeof(GFGpgVerifyResult)));
+ auto* s = *ps;
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return -1;
+ }
+
+ if (GpgFrontend::CheckGpgError(err) != GPG_ERR_NO_ERROR) return -1;
+
+ auto result =
+ GpgFrontend::ExtractParams<GpgFrontend::GpgVerifyResult>(data_object, 0);
+
+ auto capsule_id =
+ GpgFrontend::UI::UIModuleManager::GetInstance().MakeCapsule(result);
+
+ s->capsule_id = GFStrDup(capsule_id);
+ s->error_string = GFStrDup(GpgFrontend::DescribeGpgErrCode(err).second);
+ return 0;
+}
diff --git a/src/sdk/GFSDKGpg.h b/src/sdk/GFSDKGpg.h
index 1bbf5914..8977a975 100644
--- a/src/sdk/GFSDKGpg.h
+++ b/src/sdk/GFSDKGpg.h
@@ -28,4 +28,108 @@
#pragma once
-extern "C" {} \ No newline at end of file
+#include "GFSDKExport.h"
+
+extern "C" {
+
+struct GFGpgSignResult {
+ char* signature;
+ char* hash_algo;
+ char* capsule_id;
+ char* error_string;
+};
+
+struct GFGpgEncryptionResult {
+ char* encrypted_data;
+ char* capsule_id;
+ char* error_string;
+};
+
+struct GFGpgDecryptResult {
+ char* decrypted_data;
+ char* capsule_id;
+ char* error_string;
+};
+
+struct GFGpgVerifyResult {
+ char* capsule_id;
+ char* error_string;
+};
+
+struct GFGpgKeyUID {
+ char* name;
+ char* email;
+ char* comment;
+};
+
+/**
+ * @brief
+ *
+ * @param key_id
+ * @param data
+ * @param mode
+ * @return const char*
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgSignData(int channel, char** key_ids,
+ int key_ids_size, char* data,
+ int sign_mode, int ascii,
+ GFGpgSignResult**) -> int;
+
+/**
+ * @brief
+ *
+ * @param channel
+ * @param key_ids
+ * @param key_ids_size
+ * @param data
+ * @param ascii
+ * @return int
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFGpgEncryptData(int channel, char** key_ids, int key_ids_size, char* data,
+ int ascii, GFGpgEncryptionResult**) -> int;
+
+/**
+ * @brief
+ *
+ * @param key_id
+ * @param data
+ * @param mode
+ * @return const char*
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFGpgDecryptData(int channel, char* data, GFGpgDecryptResult**) -> int;
+
+/**
+ * @brief
+ *
+ * @param key_id
+ * @param data
+ * @param mode
+ * @return const char*
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgVerifyData(int channel, char* data,
+ char* signature,
+ GFGpgVerifyResult**) -> int;
+
+/**
+ * @brief
+ *
+ * @param key_id
+ * @param data
+ * @param mode
+ * @return const char*
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgPublicKey(int channel, char* key_id,
+ int ascii) -> char*;
+
+/**
+ * @brief
+ *
+ * @param channel
+ * @param key_id
+ * @return GpgKeyUID
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFGpgKeyPrimaryUID(int channel, char* key_id,
+ GFGpgKeyUID**) -> int;
+} \ No newline at end of file
diff --git a/src/sdk/GFSDKModule.cpp b/src/sdk/GFSDKModule.cpp
index 5435b0a1..e76847d2 100644
--- a/src/sdk/GFSDKModule.cpp
+++ b/src/sdk/GFSDKModule.cpp
@@ -29,9 +29,9 @@
#include "GFSDKModule.h"
#include <core/module/ModuleManager.h>
-#include <sdk/private/CommonUtils.h>
#include "GFSDKBasic.h"
+#include "private/GFSDKPrivat.h"
void GFModuleListenEvent(const char *module_id, const char *event_id) {
return GpgFrontend::Module::ModuleManager::GetInstance().ListenEvent(
diff --git a/src/sdk/GFSDKUI.cpp b/src/sdk/GFSDKUI.cpp
index 54716209..cc08705c 100644
--- a/src/sdk/GFSDKUI.cpp
+++ b/src/sdk/GFSDKUI.cpp
@@ -31,9 +31,10 @@
#include <core/utils/CommonUtils.h>
#include <QMap>
+#include <QObject>
#include <QString>
-#include "sdk/private/CommonUtils.h"
+#include "private/GFSDKPrivat.h"
#include "ui/UIModuleManager.h"
auto MetaDataArrayToQMap(MetaData** meta_data_array,
@@ -53,7 +54,7 @@ auto MetaDataArrayToQMap(MetaData** meta_data_array,
}
auto GFUIMountEntry(const char* id, MetaData** meta_data_array,
- int meta_data_array_size, EntryFactory factory) -> int {
+ int meta_data_array_size, QObjectFactory factory) -> int {
if (id == nullptr || factory == nullptr) return -1;
auto meta_data = MetaDataArrayToQMap(meta_data_array, meta_data_array_size);
@@ -69,3 +70,76 @@ auto GFUIMountEntry(const char* id, MetaData** meta_data_array,
return 0;
}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIMainWindowPtr() -> void* {
+ return GpgFrontend::UI::UIModuleManager::GetInstance().GetQObject(
+ "main_window");
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFUIShowDialog(void* dialog_raw_ptr, void* parent_raw_ptr) -> bool {
+ if (dialog_raw_ptr == nullptr) {
+ LOG_E() << "dialog raw ptr is nullptr";
+ return false;
+ }
+
+ auto* q_obj = static_cast<QObject*>(dialog_raw_ptr);
+ QPointer<QDialog> dialog = qobject_cast<QDialog*>(q_obj);
+
+ if (dialog == nullptr) {
+ LOG_E() << "convert dialog raw ptr to qdialog failed";
+ return false;
+ }
+
+ QPointer<QWidget> parent = nullptr;
+ if (parent_raw_ptr != nullptr) {
+ auto* qp_obj = static_cast<QObject*>(parent_raw_ptr);
+ parent = qobject_cast<QWidget*>(qp_obj);
+
+ if (parent == nullptr) {
+ LOG_E() << "convert parent raw ptr to qwidget failed";
+ return false;
+ }
+ }
+
+ auto* main_thread = QApplication::instance()->thread();
+
+ LOG_D() << "before entering into main thread, current thread id:"
+ << QThread::currentThreadId()
+ << ", dialog thread: " << dialog->thread()
+ << "main thread: " << main_thread;
+
+ if (dialog->thread() != main_thread) {
+ LOG_E() << "dialog must be created on main thread";
+ return false;
+ }
+
+ QMetaObject::invokeMethod(
+ parent == nullptr ? QPointer<QObject>(QApplication::instance()) : parent,
+ [dialog, parent]() -> int {
+ LOG_D() << "show qdialog, current thread id:"
+ << QThread::currentThreadId();
+ dialog->setParent(parent);
+ dialog->show();
+ return 0;
+ });
+
+ return true;
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUICreateGUIObject(QObjectFactory factory,
+ void* data) -> void* {
+ QEventLoop loop;
+ void* object = nullptr;
+
+ QMetaObject::invokeMethod(QApplication::instance(), [&]() -> int {
+ LOG_D() << "create gui object, current thread id:"
+ << QThread::currentThreadId();
+ object = factory(data);
+ loop.quit();
+ return 0;
+ });
+
+ loop.exec();
+ return object;
+}
diff --git a/src/sdk/GFSDKUI.h b/src/sdk/GFSDKUI.h
index bf4c3721..f9307cee 100644
--- a/src/sdk/GFSDKUI.h
+++ b/src/sdk/GFSDKUI.h
@@ -32,15 +32,24 @@
extern "C" {
-using EntryFactory = void* (*)(const char*);
+using QObjectFactory = void* (*)(void*);
struct MetaData {
const char* key;
const char* value;
};
-auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIMountEntry(const char* id,
- MetaData** meta_data_array,
- int meta_data_array_size,
- EntryFactory factory) -> int;
+auto GPGFRONTEND_MODULE_SDK_EXPORT
+GFUIMountEntry(const char* id, MetaData** meta_data_array,
+ int meta_data_array_size, QObjectFactory factory) -> int;
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUICreateGUIObject(QObjectFactory factory,
+ void* data) -> void*;
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIMainWindowPtr() -> void*;
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIActiveWindowPtr() -> void*;
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIShowDialog(void* dialog,
+ void* parent) -> bool;
} \ No newline at end of file
diff --git a/src/sdk/private/CommonUtils.cpp b/src/sdk/private/GFSDKPrivat.cpp
index 68afcb5f..71136535 100644
--- a/src/sdk/private/CommonUtils.cpp
+++ b/src/sdk/private/GFSDKPrivat.cpp
@@ -26,7 +26,7 @@
*
*/
-#include "CommonUtils.h"
+#include "GFSDKPrivat.h"
#include <core/utils/MemoryUtils.h>
@@ -34,6 +34,8 @@
#include "GFSDKModule.h"
+Q_LOGGING_CATEGORY(sdk, "sdk")
+
auto GFStrDup(const QString& str) -> char* {
auto utf8_str = str.toUtf8();
auto* c_str = static_cast<char*>(
@@ -58,9 +60,10 @@ auto CharArrayToQMap(char** char_array, int size) -> QMap<QString, QString> {
QMap<QString, QString> map;
for (int i = 0; i < size; i += 2) {
QString const key = GFUnStrDup(char_array[i]);
- QString const value = QString::fromUtf8(char_array[i + 1]);
+ QString const value = GFUnStrDup(char_array[i + 1]);
map.insert(key, value);
}
+
return map;
}
@@ -100,4 +103,32 @@ auto ConvertEventParamsToMap(GFModuleEventParam* params)
}
return param_map;
-} \ No newline at end of file
+}
+
+auto CharArrayToQList(char** char_array, int size) -> QStringList {
+ QStringList list;
+ for (int i = 0; i < size; ++i) {
+ if (char_array[i] != nullptr) {
+ QString value = GFUnStrDup(char_array[i]);
+ list.append(value);
+ }
+ }
+ GpgFrontend::SecureFree(char_array);
+ return list;
+}
+
+auto QListToCharArray(const QStringList& list) -> char** {
+ char** char_array = static_cast<char**>(
+ GpgFrontend::SecureMalloc(list.size() * sizeof(char*)));
+
+ int index = 0;
+ for (const QString& item : list) {
+ QByteArray value = item.toUtf8();
+ char_array[index] =
+ static_cast<char*>(GpgFrontend::SecureMalloc(value.size() + 1));
+ std::strcpy(char_array[index], value.constData());
+ index++;
+ }
+
+ return char_array;
+}
diff --git a/src/sdk/private/CommonUtils.h b/src/sdk/private/GFSDKPrivat.h
index 9539befe..7cfa2c76 100644
--- a/src/sdk/private/CommonUtils.h
+++ b/src/sdk/private/GFSDKPrivat.h
@@ -28,6 +28,15 @@
#pragma once
+// declare logging category
+Q_DECLARE_LOGGING_CATEGORY(sdk)
+
+#define LOG_D() qCDebug(sdk)
+#define LOG_I() qCInfo(sdk)
+#define LOG_W() qCWarning(sdk)
+#define LOG_E() qCCritical(sdk)
+#define LOG_F() qCFatal(sdk)
+
struct GFModuleEventParam;
/**
@@ -77,4 +86,22 @@ auto QMapToCharArray(const QMap<QString, QString> &map, int &size) -> char **;
* @return QMap<QString, QString>
*/
auto ConvertEventParamsToMap(GFModuleEventParam *params)
- -> QMap<QString, QString>; \ No newline at end of file
+ -> QMap<QString, QString>;
+
+/**
+ * @brief
+ *
+ * @param char_array
+ * @param size
+ * @return QStringList
+ */
+auto CharArrayToQList(char **char_array, int size) -> QStringList;
+
+/**
+ * @brief
+ *
+ * @param list
+ * @param size
+ * @return char**
+ */
+auto QListToCharArray(const QStringList &list) -> char **; \ No newline at end of file
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index c9690c2a..7a8b9450 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -52,11 +52,4 @@ if(XCODE_BUILD)
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}")
endif()
-if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
- # lib output path
- set_target_properties(gpgfrontend_test PROPERTIES
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib)
-endif()
-
add_test(AllTestsInGpgFrontend gpgfrontend_test)
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index a253d0ee..644053be 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -69,13 +69,6 @@ target_include_directories(gpgfrontend_ui PUBLIC
# using std c++ 17
target_compile_features(gpgfrontend_ui PUBLIC cxx_std_17)
-if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
- # lib output path
- set_target_properties(gpgfrontend_ui PROPERTIES
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib)
-endif()
-
# for xcode archive build
if(XCODE_BUILD)
set_target_properties(gpgfrontend_ui
diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp
index 0baa1fbb..bc41f5f7 100644
--- a/src/ui/GpgFrontendUIInit.cpp
+++ b/src/ui/GpgFrontendUIInit.cpp
@@ -220,7 +220,7 @@ auto RunGpgFrontendUI(QApplication* app) -> int {
auto main_window = SecureCreateUniqueObject<GpgFrontend::UI::MainWindow>();
// pre-check, if application need to restart
- if (CommonUtils::GetInstance()->isApplicationNeedRestart()) {
+ if (CommonUtils::GetInstance()->IsApplicationNeedRestart()) {
FLOG_D("application need to restart, before main window init.");
return kDeepRestartCode;
}
diff --git a/src/ui/UIModuleManager.cpp b/src/ui/UIModuleManager.cpp
index ed18f473..89621f9c 100644
--- a/src/ui/UIModuleManager.cpp
+++ b/src/ui/UIModuleManager.cpp
@@ -61,7 +61,7 @@ auto UIModuleManager::DeclareMountPoint(
auto UIModuleManager::MountEntry(const QString& id,
QMap<QString, QString> meta_data,
- EntryFactory factory) -> bool {
+ QObjectFactory factory) -> bool {
if (id.isEmpty() || !mount_points_.contains(id)) return false;
if (factory == nullptr) return false;
@@ -82,7 +82,7 @@ auto UIModuleManager::QueryMountedEntries(QString id) -> QList<MountedUIEntry> {
}
auto MountedUIEntry::GetWidget() const -> QWidget* {
- return qobject_cast<QWidget*>(static_cast<QObject*>(factory_(id_.toUtf8())));
+ return qobject_cast<QWidget*>(static_cast<QObject*>(factory_(nullptr)));
}
auto MountedUIEntry::GetMetaDataByDefault(
@@ -176,4 +176,25 @@ void UIModuleManager::TranslateAllModulesParams() {
#endif
}
+auto UIModuleManager::RegisterQObject(const QString& id, QObject* p) -> bool {
+ if (id.isEmpty() || registered_qobjects_.contains(id)) return false;
+
+ registered_qobjects_[id] = p;
+ return true;
+}
+
+auto UIModuleManager::GetQObject(const QString& id) -> QObject* {
+ return registered_qobjects_.value(id, nullptr);
+}
+
+auto UIModuleManager::GetCapsule(const QString& uuid) -> std::any {
+ return capsule_.take(uuid);
+}
+
+auto UIModuleManager::MakeCapsule(std::any v) -> QString {
+ auto uuid = QUuid::createUuid().toString();
+ capsule_[uuid] = std::move(v);
+ return uuid;
+}
+
} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/UIModuleManager.h b/src/ui/UIModuleManager.h
index 15f80030..2388dc71 100644
--- a/src/ui/UIModuleManager.h
+++ b/src/ui/UIModuleManager.h
@@ -41,7 +41,7 @@ struct MountedUIEntry {
QString id_;
QMap<QString, QString> meta_data_;
QMap<QString, QString> meta_data_translated_;
- EntryFactory factory_;
+ QObjectFactory factory_;
MountedUIEntry() = default;
@@ -92,7 +92,7 @@ class GPGFRONTEND_UI_EXPORT UIModuleManager
* @return false
*/
auto MountEntry(const QString& id, QMap<QString, QString> meta_data,
- EntryFactory factory) -> bool;
+ QObjectFactory factory) -> bool;
/**
* @brief
@@ -113,6 +113,38 @@ class GPGFRONTEND_UI_EXPORT UIModuleManager
/**
* @brief
*
+ * @param id
+ * @return auto
+ */
+ auto RegisterQObject(const QString& id, QObject*) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param id
+ * @return auto
+ */
+ auto GetQObject(const QString& id) -> QObject*;
+
+ /**
+ * @brief
+ *
+ * @param id
+ * @return auto
+ */
+ auto MakeCapsule(std::any) -> QString;
+
+ /**
+ * @brief
+ *
+ * @param id
+ * @return auto
+ */
+ auto GetCapsule(const QString& uuid) -> std::any;
+
+ /**
+ * @brief
+ *
*/
void RegisterAllModuleTranslators();
@@ -128,6 +160,8 @@ class GPGFRONTEND_UI_EXPORT UIModuleManager
QMap<QString, ModuleTranslatorInfo> translator_data_readers_;
QList<QTranslator*> registered_translators_;
QList<QByteArray> read_translator_data_list_;
+ QMap<QString, QPointer<QObject>> registered_qobjects_;
+ QMap<QString, std::any> capsule_;
};
} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index b8fc9961..d8c0059b 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -55,8 +55,8 @@
namespace GpgFrontend::UI {
-std::unique_ptr<GpgFrontend::UI::CommonUtils>
- GpgFrontend::UI::CommonUtils::instance_ = nullptr;
+QScopedPointer<CommonUtils> CommonUtils::instance =
+ QScopedPointer<CommonUtils>(nullptr);
void show_verify_details(QWidget *parent, int channel,
InfoBoardWidget *info_board, GpgError error,
@@ -121,10 +121,10 @@ void process_operation(QWidget *parent, const QString &waiting_title,
}
auto CommonUtils::GetInstance() -> CommonUtils * {
- if (instance_ == nullptr) {
- instance_ = std::make_unique<CommonUtils>();
+ if (!instance) {
+ instance.reset(new CommonUtils());
}
- return instance_.get();
+ return instance.get();
}
CommonUtils::CommonUtils() : QWidget(nullptr) {
@@ -373,7 +373,7 @@ void CommonUtils::SlotExecuteGpgCommand(
void CommonUtils::SlotImportKeyFromKeyServer(
int channel, const KeyIdArgsList &key_ids,
- const ImportCallbackFunctiopn &callback) {
+ const ImportCallbackFunction &callback) {
auto target_keyserver =
KeyServerSO(SettingsObject("key_server")).GetTargetServer();
if (target_keyserver.isEmpty()) {
@@ -554,7 +554,7 @@ void CommonUtils::SlotRestartApplication(int code) {
}
}
-auto CommonUtils::isApplicationNeedRestart() -> bool {
+auto CommonUtils::IsApplicationNeedRestart() -> bool {
return application_need_to_restart_at_once_;
}
diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h
index dab442dd..6aae75ba 100644
--- a/src/ui/UserInterfaceUtils.h
+++ b/src/ui/UserInterfaceUtils.h
@@ -89,7 +89,7 @@ class CommonUtils : public QWidget {
* @brief
*
*/
- using ImportCallbackFunctiopn =
+ using ImportCallbackFunction =
std::function<void(const QString&, const QString&, size_t, size_t)>;
/**
@@ -131,7 +131,7 @@ class CommonUtils : public QWidget {
* @brief
*
*/
- auto isApplicationNeedRestart() -> bool;
+ auto IsApplicationNeedRestart() -> bool;
/**
* @brief
@@ -238,7 +238,7 @@ class CommonUtils : public QWidget {
*/
static void SlotImportKeyFromKeyServer(
int channel, const GpgFrontend::KeyIdArgsList& key_ids,
- const GpgFrontend::UI::CommonUtils::ImportCallbackFunctiopn& callback);
+ const CommonUtils::ImportCallbackFunction& callback);
/**
* @brief
@@ -282,7 +282,8 @@ class CommonUtils : public QWidget {
std::shared_ptr<GpgImportInformation>);
private:
- static std::unique_ptr<CommonUtils> instance_; ///<
+ static QScopedPointer<CommonUtils> instance; ///<
+
bool application_need_to_restart_at_once_ = false;
};
diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp
index 507ee467..dcd23a6b 100644
--- a/src/ui/dialog/SignersPicker.cpp
+++ b/src/ui/dialog/SignersPicker.cpp
@@ -82,6 +82,16 @@ auto SignersPicker::GetCheckedSigners() -> GpgFrontend::KeyIdArgsListPtr {
return key_list_->GetCheckedPrivateKey();
}
+auto SignersPicker::GetCheckedSignerKeyIds() -> QStringList {
+ auto priv_keys = key_list_->GetCheckedPrivateKey();
+
+ QStringList r;
+ for (const auto& priv_key : *priv_keys) {
+ r.append(priv_key);
+ }
+ return r;
+}
+
auto SignersPicker::GetStatus() const -> bool { return this->accepted_; }
} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/SignersPicker.h b/src/ui/dialog/SignersPicker.h
index 0b1b7cb9..accf6952 100644
--- a/src/ui/dialog/SignersPicker.h
+++ b/src/ui/dialog/SignersPicker.h
@@ -59,6 +59,12 @@ class SignersPicker : public GeneralDialog {
auto GetCheckedSigners() -> KeyIdArgsListPtr;
/**
+ * @brief Get the Checked Signer Key Ids object
+ *
+ * @return QStringList
+ */
+ auto GetCheckedSignerKeyIds() -> QStringList;
+ /**
*
* @return
*/
diff --git a/src/ui/dialog/controller/GnuPGControllerDialog.cpp b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
index fe334e45..72e9c276 100644
--- a/src/ui/dialog/controller/GnuPGControllerDialog.cpp
+++ b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
@@ -272,7 +272,9 @@ void GnuPGControllerDialog::set_settings() {
buffered_key_db_so_ = GetGpgKeyDatabaseInfos();
editable_key_db_so_ = buffered_key_db_so_;
- editable_key_db_so_.pop_front();
+ if (!editable_key_db_so_.isEmpty()) {
+ editable_key_db_so_.pop_front();
+ }
this->slot_refresh_key_database_table();
}
@@ -380,7 +382,9 @@ void GnuPGControllerDialog::slot_add_new_key_database() {
key_databases.append(key_database);
editable_key_db_so_ = buffered_key_db_so_;
- editable_key_db_so_.pop_front();
+ if (!editable_key_db_so_.isEmpty()) {
+ editable_key_db_so_.pop_front();
+ }
// refresh ui
slot_refresh_key_database_table();
@@ -429,6 +433,16 @@ void GnuPGControllerDialog::slot_remove_existing_key_database() {
for (int i = 0; i < row_size; i++) {
auto* const item = ui_->keyDatabaseTable->item(i, 1);
if (!item->isSelected()) continue;
+
+ QMessageBox::StandardButton reply = QMessageBox::question(
+ this, tr("Confirm Deletion"),
+ tr("Are you sure you want to delete the selected key database?"),
+ QMessageBox::Yes | QMessageBox::No);
+
+ if (reply != QMessageBox::Yes) {
+ return;
+ }
+
key_databases.remove(i);
break;
}
diff --git a/src/ui/dialog/controller/ModuleControllerDialog.cpp b/src/ui/dialog/controller/ModuleControllerDialog.cpp
index 8bae2ccc..77949a61 100644
--- a/src/ui/dialog/controller/ModuleControllerDialog.cpp
+++ b/src/ui/dialog/controller/ModuleControllerDialog.cpp
@@ -46,7 +46,7 @@ ModuleControllerDialog::ModuleControllerDialog(QWidget* parent)
ui_->setupUi(this);
ui_->actionsGroupBox->hide();
- ui_->moduleInfoLabel->setText(tr("Module Informations"));
+ ui_->moduleInfoLabel->setText(tr("Module Information"));
ui_->actionsGroupBox->setTitle(tr("Actions"));
ui_->showModsDirButton->setText(tr("Show Mods Directory"));
diff --git a/src/ui/main_window/GeneralMainWindow.cpp b/src/ui/main_window/GeneralMainWindow.cpp
index 1cdb44e0..76eda3fc 100644
--- a/src/ui/main_window/GeneralMainWindow.cpp
+++ b/src/ui/main_window/GeneralMainWindow.cpp
@@ -29,6 +29,7 @@
#include "GeneralMainWindow.h"
#include "core/model/SettingsObject.h"
+#include "ui/UIModuleManager.h"
#include "ui/struct/settings_object/AppearanceSO.h"
#include "ui/struct/settings_object/WindowStateSO.h"
@@ -36,9 +37,10 @@ namespace GpgFrontend::UI {
class GeneralWindowState {};
-GpgFrontend::UI::GeneralMainWindow::GeneralMainWindow(QString name,
+GpgFrontend::UI::GeneralMainWindow::GeneralMainWindow(QString id,
QWidget *parent)
- : QMainWindow(parent), name_(std::move(name)) {
+ : QMainWindow(parent), id_(std::move(id)) {
+ UIModuleManager::GetInstance().RegisterQObject(id_, this);
slot_restore_settings();
}
@@ -51,7 +53,7 @@ void GpgFrontend::UI::GeneralMainWindow::closeEvent(QCloseEvent *event) {
void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept {
try {
- WindowStateSO window_state(SettingsObject(name_ + "_state"));
+ WindowStateSO window_state(SettingsObject(id_ + "_state"));
if (!window_state.window_state_data.isEmpty()) {
// state sets pos & size of dock-widgets
@@ -112,13 +114,13 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept {
icon_style_ = toolButtonStyle();
} catch (...) {
- LOG_W() << "general main window: " << name_ << ", caught exception";
+ LOG_W() << "general main window: " << id_ << ", caught exception";
}
}
void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept {
try {
- SettingsObject general_windows_state(name_ + "_state");
+ SettingsObject general_windows_state(id_ + "_state");
// update geo of current dialog
size_ = this->size();
@@ -134,7 +136,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept {
general_windows_state.Store(window_state.Json());
} catch (...) {
- LOG_W() << "general main window: " << name_ << ", caught exception";
+ LOG_W() << "general main window: " << id_ << ", caught exception";
}
}
@@ -197,4 +199,6 @@ void GeneralMainWindow::update_rect_cache() {
this->parent_rect_ = QRect{0, 0, 0, 0};
}
}
+
+auto GeneralMainWindow::GetId() const -> QString { return id_; }
} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/main_window/GeneralMainWindow.h b/src/ui/main_window/GeneralMainWindow.h
index 7ef1234f..d7d28930 100644
--- a/src/ui/main_window/GeneralMainWindow.h
+++ b/src/ui/main_window/GeneralMainWindow.h
@@ -41,13 +41,20 @@ class GeneralMainWindow : public QMainWindow {
*
* @param name
*/
- explicit GeneralMainWindow(QString name, QWidget* parent = nullptr);
+ explicit GeneralMainWindow(QString id, QWidget* parent = nullptr);
/**
*
*/
~GeneralMainWindow() override;
+ /**
+ * @brief Get the Id object
+ *
+ * @return QString
+ */
+ [[nodiscard]] auto GetId() const -> QString;
+
protected:
/**
*
@@ -66,7 +73,7 @@ class GeneralMainWindow : public QMainWindow {
*/
void movePosition2CenterOfParent();
- QSize icon_size_{}; ///<
+ QSize icon_size_; ///<
int font_size_{}; ///<
Qt::ToolButtonStyle icon_style_; ///<
@@ -88,9 +95,9 @@ class GeneralMainWindow : public QMainWindow {
void update_rect_cache();
private:
- QString name_; ///<
- QPoint pos_; ///<
- QSize size_; ///<
+ QString id_; ///<
+ QPoint pos_; ///<
+ QSize size_; ///<
QRect rect_;
QRect screen_rect_;
QRect parent_rect_;
diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp
index 47e7487b..1fcb14df 100644
--- a/src/ui/main_window/MainWindow.cpp
+++ b/src/ui/main_window/MainWindow.cpp
@@ -29,9 +29,7 @@
#include "MainWindow.h"
#include "core/function/CacheManager.h"
-#include "core/function/CoreSignalStation.h"
#include "core/function/GlobalSettingStation.h"
-#include "core/model/GpgPassphraseContext.h"
#include "core/model/SettingsObject.h"
#include "core/module/ModuleManager.h"
#include "ui/UISignalStation.h"
@@ -74,7 +72,7 @@ void MainWindow::Init() noexcept {
attachment_dock_created_ = false;
/* Variable containing if restart is needed */
- this->SlotSetRestartNeeded(false);
+ this->SlotSetRestartNeeded(0);
// init menu bar
this->setMenuBar(new QMenuBar());
diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h
index ef3fda13..40dd5862 100644
--- a/src/ui/main_window/MainWindow.h
+++ b/src/ui/main_window/MainWindow.h
@@ -63,7 +63,6 @@ class MainWindow : public GeneralMainWindow {
static constexpr OperationType kVerify = 1 << 3;
static constexpr OperationType kEncryptAndSign = 1 << 4;
static constexpr OperationType kDecryptAndVerify = 1 << 5;
- static constexpr OperationType kVerifyEMail = 1 << 6;
};
/**
@@ -178,6 +177,30 @@ class MainWindow : public GeneralMainWindow {
void SlotDecryptEML();
/**
+ * @brief
+ *
+ */
+ void SlotSignEML();
+
+ /**
+ * @brief
+ *
+ */
+ void SlotEncryptEML();
+
+ /**
+ * @brief
+ *
+ */
+ void SlotEncryptSignEML();
+
+ /**
+ * @brief
+ *
+ */
+ void SlotDecryptVerifyEML();
+
+ /**
* @details decrypt and verify the text of currently active textedit-page
* with the currently checked keys
*/
@@ -299,18 +322,6 @@ class MainWindow : public GeneralMainWindow {
*/
void SlotGeneralDecryptVerify(bool);
- /**
- * @brief
- *
- */
- void SlotGeneralDecryptEMail(bool);
-
- /**
- * @brief
- *
- */
- void SlotGeneralVerifyEMail(bool);
-
private slots:
/**
@@ -532,6 +543,15 @@ class MainWindow : public GeneralMainWindow {
void slot_decrypt_email_by_eml_data_result_helper(
const QMap<QString, QString>& p);
+ /**
+ * @brief
+ *
+ * @param err_code
+ * @param error_string
+ * @return QString
+ */
+ auto slot_handle_module_error(const QMap<QString, QString>& p) -> bool;
+
private:
/**
* @details Create actions for the main-menu and the context-menu of the
@@ -601,7 +621,6 @@ class MainWindow : public GeneralMainWindow {
QMenu* key_menu_{}; ///< Submenu for key-operations
QMenu* view_menu_{}; ///< Submenu for view operations
QMenu* import_key_menu_{}; ///< Submenu for import operations
- QMenu* email_menu_{}; ///< Submenu for email operations
QToolBar* crypt_tool_bar_{}; ///< Toolbar holding crypt actions
QToolBar* file_tool_bar_{}; ///< Toolbar holding file actions
@@ -609,7 +628,6 @@ class MainWindow : public GeneralMainWindow {
QToolBar*
special_edit_tool_bar_{}; ///< Toolbar holding special edit actions
QToolBar* key_tool_bar_{}; ///< Toolbar holding key operations
- QToolBar* email_tool_bar_{};
QToolButton*
import_button_{}; ///< Tool button for import dropdown menu in toolbar
QDockWidget* key_list_dock_{}; ///< Encrypt Dock
@@ -617,6 +635,7 @@ class MainWindow : public GeneralMainWindow {
QDockWidget* info_board_dock_{};
QAction* new_tab_act_{}; ///< Action to create new tab
+ QAction* new_email_tab_act_{}; ///< Action to create email tab
QAction* switch_tab_up_act_{}; ///< Action to switch tab up
QAction* switch_tab_down_act_{}; ///< Action to switch tab down
QAction* open_act_{}; ///< Action to open file
@@ -681,9 +700,6 @@ class MainWindow : public GeneralMainWindow {
QAction* import_key_from_clipboard_act_{}; ///<
QAction* import_key_from_key_server_act_{}; ///<
- QAction* verify_email_by_eml_data_act_{}; ///<
- QAction* decrypt_email_by_eml_data_act_{};
-
QLabel* status_bar_icon_{}; ///<
KeyList* m_key_list_{}; ///<
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index c7579ff9..ea772b3e 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -31,12 +31,18 @@
#include "core/function/gpg/GpgKeyGetter.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
#include "core/function/result_analyse/GpgDecryptResultAnalyse.h"
+#include "core/function/result_analyse/GpgEncryptResultAnalyse.h"
+#include "core/function/result_analyse/GpgSignResultAnalyse.h"
#include "core/model/GpgDecryptResult.h"
+#include "core/model/GpgEncryptResult.h"
+#include "core/model/GpgSignResult.h"
#include "core/module/ModuleManager.h"
#include "core/typedef/GpgTypedef.h"
#include "core/utils/CommonUtils.h"
#include "core/utils/GpgUtils.h"
+#include "ui/UIModuleManager.h"
#include "ui/UserInterfaceUtils.h"
+#include "ui/dialog/SignersPicker.h"
#include "ui/dialog/help/AboutDialog.h"
#include "ui/dialog/import_export/KeyUploadDialog.h"
#include "ui/dialog/keypair_details/KeyDetailsDialog.h"
@@ -350,53 +356,31 @@ void MainWindow::slot_import_key_from_edit() {
}
void MainWindow::slot_verify_email_by_eml_data(const QByteArray& buffer) {
- Module::TriggerEvent(
- "EMAIL_VERIFY_EML_DATA",
- {
- {"eml_data", QString::fromLatin1(buffer.toBase64())},
- },
- [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
- Module::Event::Params p) {
- LOG_D() << "EMAIL_VERIFY_EML_DATA callback: " << i << ei;
- if (p["ret"] != "0" || !p["err"].isEmpty()) {
- LOG_E() << "An error occurred trying to verify email, "
- << "error message: " << p["err"];
-
- if (p["ret"] == "-2") {
- QString detailed_error = p["err"];
-
- QString info =
- tr("# EML Data Error\n\n"
- "The provided EML data does not conform to the "
- "structure described in RFC 3156 and cannot be "
- "validated.\n\n"
- "Details: %1\n\n"
- "What is EML Data?\n"
- "EML is a file format used to represent email messages. "
- "It typically contains the entire contents of an email, "
- "including headers, "
- "body text, attachments, and metadata. In order to validate "
- "the email properly, it is necessary to provide the "
- "complete, original EML "
- "data.\n\n"
- "For more information about the expected EML structure, "
- "please refer to the RFC 3156 standard:\n"
- "%2\n\n"
- "Please ensure the EML data follows the standard and try "
- "again.")
- .arg(detailed_error)
- .arg("https://www.rfc-editor.org/rfc/rfc3156.txt");
- slot_refresh_info_board(-2, info);
- }
-
- return;
- }
+ CommonUtils::WaitForOpera(
+ this, tr("Verifying"), [this, buffer](const OperaWaitingHd& hd) {
+ Module::TriggerEvent(
+ "EMAIL_VERIFY_EML_DATA",
+ {
+ {"eml_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
+ },
+ [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ LOG_D() << "EMAIL_VERIFY_EML_DATA callback: " << i << ei;
+
+ // end waiting dialog
+ hd();
- if (p.contains("signature") && p.contains("mime")) {
- slot_verify_email_by_eml_data_result_helper(p);
- }
+ // check if error occurred
+ if (slot_handle_module_error(p)) return -1;
- LOG_E() << "mime or signature data is missing";
+ if (p.contains("signature") && p.contains("mime")) {
+ slot_verify_email_by_eml_data_result_helper(p);
+ }
+
+ return 0;
+ });
});
}
@@ -405,49 +389,21 @@ void MainWindow::slot_decrypt_email_by_eml_data(const QByteArray& buffer) {
"EMAIL_DECRYPT_EML_DATA",
{
{"eml_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
},
[=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
Module::Event::Params p) {
LOG_D() << "EMAIL_DECRYPT_EML_DATA callback: " << i << ei;
- if (p["ret"] != "0" || !p["err"].isEmpty()) {
- LOG_E() << "An error occurred trying to decrypt email, "
- << "error message: " << p["err"];
-
- if (p["ret"] == "-2") {
- QString detailed_error = p["err"];
-
- QString info =
- tr("# EML Data Error\n\n"
- "The provided EML data does not conform to the "
- "structure described in RFC 3156 and cannot be "
- "validated.\n\n"
- "Details: %1\n\n"
- "What is EML Data?\n"
- "EML is a file format used to represent email messages. "
- "It typically contains the entire contents of an email, "
- "including headers, "
- "body text, attachments, and metadata. In order to validate "
- "the email properly, it is necessary to provide the "
- "complete, original EML "
- "data.\n\n"
- "For more information about the expected EML structure, "
- "please refer to the RFC 3156 standard:\n"
- "%2\n\n"
- "Please ensure the EML data follows the standard and try "
- "again.")
- .arg(detailed_error)
- .arg("https://www.rfc-editor.org/rfc/rfc3156.txt");
- slot_refresh_info_board(-2, info);
- }
-
- return;
- }
- if (p.contains("encrypted")) {
+ // check if error occurred
+ if (slot_handle_module_error(p)) return -1;
+
+ if (p.contains("eml_data")) {
slot_decrypt_email_by_eml_data_result_helper(p);
}
- LOG_E() << "mime or signature data is missing";
+ return 0;
});
}
@@ -540,50 +496,25 @@ void MainWindow::slot_verify_email_by_eml_data_result_helper(
.arg(prm_micalg_value));
email_info.append("\n");
- // set input buffer
- auto raw_data_buffer = GFBuffer(mime);
- auto signature_buffer = GFBuffer(signature);
+ if (!p["capsule_id"].isEmpty()) {
+ auto v =
+ UIModuleManager::GetInstance().GetCapsule(p.value("capsule_id", ""));
- CommonUtils::WaitForOpera(
- this, tr("Verifying"),
- [this, email_info, raw_data_buffer,
- signature_buffer](const OperaWaitingHd& hd) {
- GpgFrontend::GpgBasicOperator::GetInstance(
- m_key_list_->GetCurrentGpgContextChannel())
- .Verify(
- raw_data_buffer, signature_buffer,
- [this, email_info, hd](GpgError err,
- const DataObjectPtr& data_obj) {
- // stop waiting
- hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgVerifyResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
- auto verify_result =
- ExtractParams<GpgVerifyResult>(data_obj, 0);
-
- // analyse result
- auto result_analyse = GpgVerifyResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- verify_result);
- result_analyse.Analyse();
- auto verify_result_report = result_analyse.GetResultReport();
+ try {
+ auto sign_result = std::any_cast<GpgVerifyResult>(v);
+ auto result_analyse =
+ GpgVerifyResultAnalyse(m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, sign_result);
+ result_analyse.Analyse();
- slot_refresh_info_board(result_analyse.GetStatus(),
- email_info + verify_result_report);
+ slot_refresh_info_board(result_analyse.GetStatus(),
+ email_info + result_analyse.GetResultReport());
- if (!result_analyse.GetUnknownSignatures().isEmpty() &&
- Module::IsModuleActivate(kKeyServerSyncModuleID)) {
- slot_verifying_unknown_signature_helper(result_analyse);
- return;
- }
- });
- });
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"] << "convert to real type failed"
+ << e.what();
+ }
+ }
}
void MainWindow::slot_eml_verify_show_helper(const QString& email_info,
@@ -628,14 +559,15 @@ void MainWindow::SlotDecryptEML() {
void MainWindow::slot_decrypt_email_by_eml_data_result_helper(
const QMap<QString, QString>& p) {
- const auto encrypted = QByteArray::fromBase64(p["encrypted"].toLatin1());
-
auto timestamp = p.value("datetime", "-1").toLongLong();
auto datetime = tr("None");
if (timestamp > 0) {
datetime = QLocale().toString(QDateTime::fromMSecsSinceEpoch(timestamp));
}
+ const auto eml_data = QByteArray::fromBase64(p["eml_data"].toLatin1());
+ edit_->SlotFillTextEditWithText(eml_data);
+
QString email_info;
email_info.append("# E-Mail Information\n\n");
email_info.append(QString("- %1: %2\n")
@@ -654,39 +586,414 @@ void MainWindow::slot_decrypt_email_by_eml_data_result_helper(
email_info.append("\n");
- // data to transfer into task
- auto buffer = GFBuffer(encrypted);
+ if (!p["capsule_id"].isEmpty()) {
+ auto v =
+ UIModuleManager::GetInstance().GetCapsule(p.value("capsule_id", ""));
+
+ try {
+ auto sign_result = std::any_cast<GpgDecryptResult>(v);
+ auto result_analyse =
+ GpgDecryptResultAnalyse(m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, sign_result);
+ result_analyse.Analyse();
+
+ slot_refresh_info_board(result_analyse.GetStatus(),
+ email_info + result_analyse.GetResultReport());
+
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"] << "convert to real type failed"
+ << e.what();
+ }
+ }
+}
+
+void MainWindow::SlotEncryptEML() {
+ if (edit_->TabCount() == 0 || edit_->CurEMailPage() == nullptr) return;
+ auto checked_keys = m_key_list_->GetCheckedKeys();
+
+ if (checked_keys.isEmpty()) {
+ QMessageBox::warning(this, tr("No Key Selected"),
+ tr("Please select a key for encrypt the EML."));
+ return;
+ }
+ auto buffer = edit_->CurPlainText().toUtf8();
CommonUtils::WaitForOpera(
- this, tr("Decrypting"), [this, buffer](const OperaWaitingHd& hd) {
- GpgFrontend::GpgBasicOperator::GetInstance(
- m_key_list_->GetCurrentGpgContextChannel())
- .Decrypt(buffer, [this, hd](GpgError err,
- const DataObjectPtr& data_obj) {
- // stop waiting
+ this, tr("Encrypting"),
+ [this, buffer, checked_keys](const OperaWaitingHd& hd) {
+ Module::TriggerEvent(
+ "EMAIL_ENCRYPT_EML_DATA",
+ {
+ {"body_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
+ {"encrypt_keys", checked_keys.join(';')},
+ },
+
+ [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ LOG_D() << "EMAIL_ENCRYPT_EML_DATA callback: " << i << ei;
+
+ // close waiting dialog
hd();
- if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr ||
- !data_obj->Check<GpgDecryptResult, GFBuffer>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
+ if (p["ret"] != "0" || !p["err"].isEmpty()) {
+ LOG_E() << "An error occurred trying to decrypt email, "
+ << "error message: " << p["err"];
+
return;
}
- auto decrypt_result =
- ExtractParams<GpgDecryptResult>(data_obj, 0);
- auto out_buffer = ExtractParams<GFBuffer>(data_obj, 1);
- auto result_analyse = GpgDecryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- decrypt_result);
- result_analyse.Analyse();
- slot_result_analyse_show_helper(result_analyse);
-
- if (CheckGpgError(err) == GPG_ERR_NO_ERROR) {
- edit_->SlotFillTextEditWithText(
- out_buffer.ConvertToQByteArray());
+
+ if (!p["eml_data"].isEmpty()) {
+ edit_->SlotSetText2CurEMailPage(p.value("eml_data", ""));
+ }
+
+ if (!p["capsule_id"].isEmpty()) {
+ auto v = UIModuleManager::GetInstance().GetCapsule(
+ p.value("capsule_id", ""));
+
+ try {
+ auto encr_result = std::any_cast<GpgEncryptResult>(v);
+ auto result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, encr_result);
+ result_analyse.Analyse();
+ slot_result_analyse_show_helper(result_analyse);
+
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"]
+ << "convert to real type failed" << e.what();
+ }
+ }
+
+ LOG_E() << "mime or signature data is missing";
+ });
+ });
+}
+
+void MainWindow::SlotSignEML() {
+ if (edit_->TabCount() == 0 || edit_->CurEMailPage() == nullptr) return;
+ auto checked_keys = m_key_list_->GetCheckedKeys();
+
+ if (checked_keys.isEmpty()) {
+ QMessageBox::warning(this, tr("No Key Selected"),
+ tr("Please select a key for signing the EML."));
+ return;
+ }
+
+ if (checked_keys.size() > 1) {
+ QMessageBox::warning(this, tr("Multiple Keys Selected"),
+ tr("Please select only one key to sign the EML."));
+ return;
+ }
+
+ auto buffer = edit_->CurPlainText().toUtf8();
+
+ CommonUtils::WaitForOpera(
+ this, tr("Signing"),
+ [this, buffer, checked_keys](const OperaWaitingHd& hd) {
+ Module::TriggerEvent(
+ "EMAIL_SIGN_EML_DATA",
+ {
+ {"body_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
+ {"sign_key", checked_keys.front()},
+ },
+ [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ LOG_D() << "EMAIL_SIGN_EML_DATA callback: " << i << ei;
+
+ // close waiting dialog
+ hd();
+
+ // check if error occurred
+ if (slot_handle_module_error(p)) return -1;
+
+ if (!p["eml_data"].isEmpty()) {
+ edit_->SlotSetText2CurEMailPage(p.value("eml_data", ""));
+ }
+
+ if (!p["capsule_id"].isEmpty()) {
+ auto v = UIModuleManager::GetInstance().GetCapsule(
+ p.value("capsule_id", ""));
+
+ try {
+ auto sign_result = std::any_cast<GpgSignResult>(v);
+ auto result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, sign_result);
+ result_analyse.Analyse();
+ slot_result_analyse_show_helper(result_analyse);
+
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"]
+ << "convert to real type failed" << e.what();
+ }
}
+
+ return 0;
});
});
}
+void MainWindow::SlotEncryptSignEML() {
+ if (edit_->TabCount() == 0 || edit_->CurEMailPage() == nullptr) return;
+ auto checked_keys = m_key_list_->GetCheckedKeys();
+
+ if (checked_keys.isEmpty()) {
+ QMessageBox::warning(this, tr("No Key Selected"),
+ tr("Please select a key for encrypt the EML."));
+ return;
+ }
+
+ auto* signers_picker =
+ new SignersPicker(m_key_list_->GetCurrentGpgContextChannel(), this);
+ QEventLoop loop;
+ connect(signers_picker, &SignersPicker::finished, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ // return when canceled
+ if (!signers_picker->GetStatus()) return;
+
+ auto signer_keys = signers_picker->GetCheckedSignerKeyIds();
+
+ if (signer_keys.isEmpty()) {
+ QMessageBox::warning(this, tr("No Key Selected"),
+ tr("Please select a key for signing the EML."));
+ return;
+ }
+
+ if (signer_keys.size() > 1) {
+ QMessageBox::warning(this, tr("Multiple Keys Selected"),
+ tr("Please select only one key to sign the EML."));
+ return;
+ }
+
+ auto buffer = edit_->CurPlainText().toUtf8();
+
+ CommonUtils::WaitForOpera(
+ this, tr("Encrypting and Signing"),
+ [this, buffer, checked_keys, signer_keys](const OperaWaitingHd& hd) {
+ Module::TriggerEvent(
+ "EMAIL_ENCRYPT_SIGN_EML_DATA",
+ {
+ {"body_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
+ {"sign_key", signer_keys.front()},
+ {"encrypt_keys", checked_keys.front()},
+ },
+ [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ LOG_D() << "EMAIL_ENCRYPT_SIGN_EML_DATA callback: " << i << ei;
+
+ // close waiting dialog
+ hd();
+
+ // check if error occurred
+ if (slot_handle_module_error(p)) return -1;
+
+ if (!p["sign_capsule_id"].isEmpty() &&
+ !p["encr_capsule_id"].isEmpty()) {
+ auto v1 = UIModuleManager::GetInstance().GetCapsule(
+ p.value("sign_capsule_id", ""));
+ auto v2 = UIModuleManager::GetInstance().GetCapsule(
+ p.value("encr_capsule_id", ""));
+
+ try {
+ auto sign_result = std::any_cast<GpgSignResult>(v1);
+ auto encr_result = std::any_cast<GpgSignResult>(v1);
+ auto sign_result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, sign_result);
+ auto encr_result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, sign_result);
+
+ sign_result_analyse.Analyse();
+ encr_result_analyse.Analyse();
+ slot_result_analyse_show_helper(sign_result_analyse,
+ encr_result_analyse);
+
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"]
+ << "convert to real type failed" << e.what();
+ }
+ }
+
+ return 0;
+ });
+ });
+}
+
+void MainWindow::SlotDecryptVerifyEML() {
+ if (edit_->TabCount() == 0 || edit_->CurEMailPage() == nullptr) return;
+
+ auto buffer = edit_->CurPlainText().toUtf8();
+
+ CommonUtils::WaitForOpera(
+ this, tr("Decrypting and Verifying"),
+ [this, buffer](const OperaWaitingHd& hd) {
+ Module::TriggerEvent(
+ "EMAIL_DECRYPT_VERIFY_EML_DATA",
+ {
+ {"eml_data", QString::fromLatin1(buffer.toBase64())},
+ {"channel",
+ QString::number(m_key_list_->GetCurrentGpgContextChannel())},
+ },
+ [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ LOG_D() << "EMAIL_DECRYPT_VERIFY_EML_DATA callback: " << i << ei;
+
+ // close waiting dialog
+ hd();
+
+ // check if error occurred
+ if (slot_handle_module_error(p)) return -1;
+
+ edit_->SlotSetText2CurEMailPage(p.value("eml_data", ""));
+
+ const auto mime = QByteArray::fromBase64(p["mime"].toLatin1());
+ const auto signature =
+ QByteArray::fromBase64(p["signature"].toLatin1());
+ const auto part_mime_content_hash = p["mime_hash"];
+ const auto prm_micalg_value = p["micalg"];
+
+ auto timestamp = p.value("datetime", "-1").toLongLong();
+ auto datetime = tr("None");
+ if (timestamp > 0) {
+ datetime = QLocale().toString(
+ QDateTime::fromMSecsSinceEpoch(timestamp));
+ }
+
+ QString email_info;
+ email_info.append("# E-Mail Information\n\n");
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("From"))
+ .arg(p.value("from", tr("Unknown"))));
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("To"))
+ .arg(p.value("to", tr("Unknown"))));
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("Subject"))
+ .arg(p.value("subject", tr("None"))));
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("CC"))
+ .arg(p.value("cc", tr("None"))));
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("BCC"))
+ .arg(p.value("bcc", tr("None"))));
+ email_info.append(
+ QString("- %1: %2\n").arg(tr("Date")).arg(datetime));
+
+ email_info.append("\n");
+ email_info.append("# OpenPGP Information\n\n");
+ email_info.append(QString("- %1: %2\n")
+ .arg(tr("Signed EML Data Hash (SHA1)"))
+ .arg(part_mime_content_hash));
+ email_info.append(
+ QString("- %1: %2\n")
+ .arg(tr("Message Integrity Check Algorithm"))
+ .arg(prm_micalg_value));
+ email_info.append("\n");
+
+ if (!p["decr_capsule_id"].isEmpty() &&
+ !p["verify_capsule_id"].isEmpty()) {
+ auto v1 = UIModuleManager::GetInstance().GetCapsule(
+ p.value("decr_capsule_id", ""));
+ auto v2 = UIModuleManager::GetInstance().GetCapsule(
+ p.value("verify_capsule_id", ""));
+
+ try {
+ auto decr_result = std::any_cast<GpgDecryptResult>(v1);
+ auto verify_result = std::any_cast<GpgVerifyResult>(v2);
+ auto decr_result_analyse = GpgDecryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, decr_result);
+ auto verify_result_analyse = GpgVerifyResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(),
+ GPG_ERR_NO_ERROR, verify_result);
+
+ decr_result_analyse.Analyse();
+ verify_result_analyse.Analyse();
+ slot_refresh_info_board(
+ std::min(decr_result_analyse.GetStatus(),
+ verify_result_analyse.GetStatus()),
+ email_info + decr_result_analyse.GetResultReport() +
+ verify_result_analyse.GetResultReport());
+
+ } catch (const std::bad_any_cast& e) {
+ LOG_E() << "capsule" << p["capsule_id"]
+ << "convert to real type failed" << e.what();
+ }
+ }
+
+ return 0;
+ });
+ });
+}
+
+auto MainWindow::slot_handle_module_error(const QMap<QString, QString>& p)
+ -> bool {
+ if (p["ret"] == "-2") {
+ QString detailed_error = p["err"];
+
+ QString info =
+ tr("# EML Data Error\n\n"
+ "The provided EML data does not conform to RFC 3156 standards and "
+ "cannot be processed.\n\n"
+ "**Details:** %1\n\n"
+ "### What is EML Data?\n"
+ "EML is a file format for representing email messages, typically "
+ "including headers, body text, attachments, and metadata. "
+ "Complete and properly structured EML data is required for "
+ "validation.\n\n"
+ "### Suggested Solutions\n"
+ "1. Verify the EML data is complete and matches the structure "
+ "outlined in RFC 3156.\n"
+ "2. Refer to the official documentation for the EML structure: "
+ "%2\n\n"
+ "After correcting the EML data, try the operation again.")
+ .arg(detailed_error)
+ .arg("https://www.rfc-editor.org/rfc/rfc3156.txt");
+ slot_refresh_info_board(-2, info);
+ return true;
+ }
+
+ if (p["ret"] != "0" || !p["err"].isEmpty()) {
+ LOG_E() << "An error occurred trying to operate email, "
+ << "error message: " << p["err"];
+
+ QString error_message =
+ tr("# Email Operation Error\n\n"
+ "An error occurred during the email operation. The process "
+ "could not be completed.\n\n"
+ "**Details:**\n"
+ "- **Error Code:** %1\n"
+ "- **Error Message:** %2\n\n"
+ "### Possible Causes\n"
+ "1. The email data may be incomplete or corrupted.\n"
+ "2. The selected GPG key does not have the necessary "
+ "permissions.\n"
+ "3. Issues in the GPG environment or configuration.\n\n"
+ "### Suggested Solutions\n"
+ "1. Ensure the email data is complete and follows the expected "
+ "format.\n"
+ "2. Verify the GPG key has the required access permissions.\n"
+ "3. Check your GPG environment and configuration settings.\n"
+ "4. Review the error details above or application logs for "
+ "further troubleshooting.\n\n"
+ "If the issue persists, consider seeking technical support or "
+ "consulting the documentation.")
+ .arg(p["ret"])
+ .arg(p["err"]);
+
+ slot_refresh_info_board(-1, error_message);
+ return true;
+ }
+
+ return false;
+}
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index 105a2374..53fa29a4 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -80,11 +80,6 @@ void MainWindow::slot_switch_menu_control_mode(int index) {
decrypt_act_->setDisabled(disable);
decrypt_verify_act_->setDisabled(disable);
- if (Module::IsModuleActivate(kEmailModuleID)) {
- verify_email_by_eml_data_act_->setDisabled(disable);
- decrypt_email_by_eml_data_act_->setDisabled(disable);
- }
-
redo_act_->setDisabled(disable);
undo_act_->setDisabled(disable);
zoom_out_act_->setDisabled(disable);
@@ -189,11 +184,6 @@ void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) {
decrypt_act_->setDisabled(true);
decrypt_verify_act_->setDisabled(true);
- if (Module::IsModuleActivate(kEmailModuleID)) {
- verify_email_by_eml_data_act_->setDisabled(true);
- decrypt_email_by_eml_data_act_->setDisabled(true);
- }
-
// gnupg operations
if ((opera_type & MainWindow::OperationMenu::kVerify) != 0U) {
verify_act_->setDisabled(false);
@@ -213,12 +203,6 @@ void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) {
if ((opera_type & MainWindow::OperationMenu::kDecryptAndVerify) != 0U) {
decrypt_verify_act_->setDisabled(false);
}
-
- // email operations
- if (Module::IsModuleActivate(kEmailModuleID) &&
- (opera_type & MainWindow::OperationMenu::kVerifyEMail) != 0U) {
- verify_email_by_eml_data_act_->setDisabled(false);
- }
}
void MainWindow::SlotGeneralEncrypt(bool) {
@@ -233,6 +217,12 @@ void MainWindow::SlotGeneralEncrypt(bool) {
this->SlotDirectoryEncrypt(path);
}
}
+
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotEncryptEML();
+ return;
+ }
+
if (edit_->SlotCurPageTextEdit() != nullptr) {
this->SlotEncrypt();
}
@@ -254,6 +244,12 @@ void MainWindow::SlotGeneralDecrypt(bool) {
}
}
}
+
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotDecryptEML();
+ return;
+ }
+
if (edit_->SlotCurPageTextEdit() != nullptr) {
this->SlotDecrypt();
}
@@ -267,6 +263,12 @@ void MainWindow::SlotGeneralSign(bool) {
const auto file_info = QFileInfo(path);
if (file_info.isFile()) this->SlotFileSign(path);
}
+
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotSignEML();
+ return;
+ }
+
if (edit_->SlotCurPageTextEdit() != nullptr) this->SlotSign();
}
@@ -278,6 +280,12 @@ void MainWindow::SlotGeneralVerify(bool) {
const auto file_info = QFileInfo(path);
if (file_info.isFile()) this->SlotFileVerify(path);
}
+
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotVerifyEML();
+ return;
+ }
+
if (edit_->SlotCurPageTextEdit() != nullptr) this->SlotVerify();
}
@@ -293,6 +301,12 @@ void MainWindow::SlotGeneralEncryptSign(bool) {
this->SlotDirectoryEncryptSign(path);
}
}
+
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotEncryptSignEML();
+ return;
+ }
+
if (edit_->SlotCurPageTextEdit() != nullptr) {
this->SlotEncryptSign();
}
@@ -314,20 +328,15 @@ void MainWindow::SlotGeneralDecryptVerify(bool) {
}
}
}
- if (edit_->SlotCurPageTextEdit() != nullptr) {
- this->SlotDecryptVerify();
- }
-}
-void MainWindow::SlotGeneralVerifyEMail(bool) {
- if (edit_->SlotCurPageFileTreeView() != nullptr) {
- const auto* file_tree_view = edit_->SlotCurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
+ if (edit_->CurEMailPage() != nullptr) {
+ this->SlotDecryptVerifyEML();
+ return;
+ }
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) this->SlotFileVerifyEML(path);
+ if (edit_->SlotCurPageTextEdit() != nullptr) {
+ this->SlotDecryptVerify();
}
- if (edit_->SlotCurPageTextEdit() != nullptr) this->SlotVerifyEML();
}
void MainWindow::slot_clean_gpg_password_cache(bool) {
@@ -376,15 +385,4 @@ void MainWindow::slot_restart_gpg_components(bool) {
});
}
-void MainWindow::SlotGeneralDecryptEMail(bool) {
- // if (edit_->SlotCurPageFileTreeView() != nullptr) {
- // const auto* file_tree_view = edit_->SlotCurPageFileTreeView();
- // const auto path = file_tree_view->GetSelected();
-
- // const auto file_info = QFileInfo(path);
- // if (file_info.isFile()) this->SlotFileVerify(path);
- // }
- if (edit_->SlotCurPageTextEdit() != nullptr) this->SlotDecryptEML();
-}
-
} // namespace GpgFrontend::UI
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 9c2a5003..59ad8401 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -49,8 +49,8 @@ void MainWindow::create_actions() {
connect(open_act_, &QAction::triggered, edit_, &TextEdit::SlotOpen);
browser_act_ = create_action(
- "file_browser", tr("File Browser"), ":/icons/file-browser.png",
- tr("Open a file browser"), {QKeySequence(Qt::CTRL | Qt::Key_B)});
+ "file_browser", tr("File Panel"), ":/icons/file-operator.png",
+ tr("Open a file panel"), {QKeySequence(Qt::CTRL | Qt::Key_B)});
connect(browser_act_, &QAction::triggered, this,
&MainWindow::slot_open_file_tab);
@@ -141,29 +141,29 @@ void MainWindow::create_actions() {
/*
* Crypt Menu
*/
- encrypt_act_ = create_action("encrypt", tr("Encrypt"),
- ":/icons/encrypted.png", tr("Encrypt Message"),
+ encrypt_act_ = create_action("encrypt", tr("Encrypt"), ":/icons/lock.png",
+ tr("Encrypt Message"),
{QKeySequence(Qt::CTRL | Qt::Key_E)});
connect(encrypt_act_, &QAction::triggered, this,
&MainWindow::SlotGeneralEncrypt);
- encrypt_sign_act_ = create_action(
- "encrypt_sign", tr("Encrypt Sign"), ":/icons/encrypted_signed.png",
- tr("Encrypt and Sign Message"),
- {QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_E)});
+ encrypt_sign_act_ =
+ create_action("encrypt_sign", tr("Encrypt Sign"), ":/icons/compress.png",
+ tr("Encrypt and Sign Message"),
+ {QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_E)});
connect(encrypt_sign_act_, &QAction::triggered, this,
&MainWindow::SlotGeneralEncryptSign);
- decrypt_act_ = create_action("decrypt", tr("Decrypt"),
- ":/icons/decrypted.png", tr("Decrypt Message"),
+ decrypt_act_ = create_action("decrypt", tr("Decrypt"), ":/icons/unlock.png",
+ tr("Decrypt Message"),
{QKeySequence(Qt::CTRL | Qt::Key_D)});
connect(decrypt_act_, &QAction::triggered, this,
&MainWindow::SlotGeneralDecrypt);
- decrypt_verify_act_ = create_action(
- "decrypt_verify", tr("Decrypt Verify"), ":/icons/decrypted_verified.png",
- tr("Decrypt and Verify Message"),
- {QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D)});
+ decrypt_verify_act_ =
+ create_action("decrypt_verify", tr("Decrypt Verify"),
+ ":/icons/expand.png", tr("Decrypt and Verify Message"),
+ {QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D)});
connect(decrypt_verify_act_, &QAction::triggered, this,
&MainWindow::SlotGeneralDecryptVerify);
@@ -260,17 +260,11 @@ void MainWindow::create_actions() {
* E-Mail Menu
*/
if (Module::IsModuleActivate(kEmailModuleID)) {
- verify_email_by_eml_data_act_ = create_action(
- "verify_email_by_eml_data", tr("Verify E-Mail"),
- ":/icons/email-check.png", tr("Verify RAW E-Mail Data (EML)"));
- connect(verify_email_by_eml_data_act_, &QAction::triggered, this,
- &MainWindow::SlotGeneralVerifyEMail);
-
- decrypt_email_by_eml_data_act_ = create_action(
- "decrypt_email_by_eml_data", tr("Decrypt E-Mail"),
- ":/icons/email-open.png", tr("Decrypt RAW E-Mail Data (EML)"));
- connect(decrypt_email_by_eml_data_act_, &QAction::triggered, this,
- &MainWindow::SlotGeneralDecryptEMail);
+ new_email_tab_act_ =
+ create_action("new_email_tab", tr("New E-Mail"), ":/icons/email.png",
+ tr("Create A New E-Mail Tab"));
+ connect(new_email_tab_act_, &QAction::triggered, edit_,
+ &TextEdit::SlotNewEMailTab);
}
/*
@@ -407,6 +401,11 @@ void MainWindow::create_actions() {
void MainWindow::create_menus() {
file_menu_ = menuBar()->addMenu(tr("File"));
file_menu_->addAction(new_tab_act_);
+
+ if (Module::IsModuleActivate(kEmailModuleID)) {
+ file_menu_->addAction(new_email_tab_act_);
+ }
+
file_menu_->addAction(browser_act_);
file_menu_->addAction(open_act_);
file_menu_->addSeparator();
@@ -465,12 +464,6 @@ void MainWindow::create_menus() {
advance_menu_->addAction(gnupg_controller_open_act_);
advance_menu_->addAction(module_controller_open_act_);
- if (Module::IsModuleActivate(kEmailModuleID)) {
- email_menu_ = menuBar()->addMenu(tr("E-Mail"));
- email_menu_->addAction(verify_email_by_eml_data_act_);
- email_menu_->addAction(decrypt_email_by_eml_data_act_);
- }
-
view_menu_ = menuBar()->addMenu(tr("View"));
help_menu_ = menuBar()->addMenu(tr("Help"));
@@ -494,6 +487,11 @@ void MainWindow::create_tool_bars() {
file_tool_bar_ = addToolBar(tr("File"));
file_tool_bar_->setObjectName("fileToolBar");
file_tool_bar_->addAction(new_tab_act_);
+
+ if (Module::IsModuleActivate(kEmailModuleID)) {
+ file_tool_bar_->addAction(new_email_tab_act_);
+ }
+
file_tool_bar_->addAction(open_act_);
file_tool_bar_->addAction(browser_act_);
view_menu_->addAction(file_tool_bar_->toggleViewAction());
@@ -501,9 +499,9 @@ void MainWindow::create_tool_bars() {
crypt_tool_bar_ = addToolBar(tr("Operations"));
crypt_tool_bar_->setObjectName("cryptToolBar");
crypt_tool_bar_->addAction(encrypt_act_);
- crypt_tool_bar_->addAction(encrypt_sign_act_);
+ // crypt_tool_bar_->addAction(encrypt_sign_act_);
crypt_tool_bar_->addAction(decrypt_act_);
- crypt_tool_bar_->addAction(decrypt_verify_act_);
+ // crypt_tool_bar_->addAction(decrypt_verify_act_);
crypt_tool_bar_->addAction(sign_act_);
crypt_tool_bar_->addAction(verify_act_);
view_menu_->addAction(crypt_tool_bar_->toggleViewAction());
@@ -530,14 +528,6 @@ void MainWindow::create_tool_bars() {
special_edit_tool_bar_->hide();
view_menu_->addAction(special_edit_tool_bar_->toggleViewAction());
- if (Module::IsModuleActivate(kEmailModuleID)) {
- email_tool_bar_ = addToolBar(tr("E-Mail"));
- email_tool_bar_->setObjectName("emailToolBar");
- email_tool_bar_->addAction(verify_email_by_eml_data_act_);
- email_tool_bar_->addAction(decrypt_email_by_eml_data_act_);
- view_menu_->addAction(email_tool_bar_->toggleViewAction());
- }
-
// Add dropdown menu for key import to keytoolbar
import_button_ = new QToolButton();
import_button_->setMenu(import_key_menu_);
diff --git a/src/ui/widgets/EMailEditorPage.cpp b/src/ui/widgets/EMailEditorPage.cpp
new file mode 100644
index 00000000..e37695be
--- /dev/null
+++ b/src/ui/widgets/EMailEditorPage.cpp
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2021-2024 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 "EMailEditorPage.h"
+
+#include "ui_PlainTextEditor.h"
+
+namespace GpgFrontend::UI {
+
+EMailEditorPage::EMailEditorPage() {
+ this->ui_->encodingLabel->setText("E-Mail");
+}
+
+EMailEditorPage::EMailEditorPage(const QString& file_path, QWidget* parent)
+ : PlainTextEditorPage(file_path, parent) {
+ this->ui_->encodingLabel->setText("E-Mail");
+}
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/widgets/EMailEditorPage.h b/src/ui/widgets/EMailEditorPage.h
new file mode 100644
index 00000000..a5eb6f50
--- /dev/null
+++ b/src/ui/widgets/EMailEditorPage.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2021-2024 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 <utility>
+
+#include "ui/GpgFrontendUI.h"
+#include "ui/widgets/PlainTextEditorPage.h"
+
+class Ui_FilePage;
+
+namespace GpgFrontend::UI {
+class EMailEditorPage : public PlainTextEditorPage {
+ Q_OBJECT
+ public:
+ EMailEditorPage();
+
+ EMailEditorPage(const QString& file_path, QWidget* parent);
+};
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index 4d9ce26a..998b4245 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -160,10 +160,6 @@ void FilePage::update_main_basical_opera_menu(const QString& selected_path) {
operation_type |= MainWindow::OperationMenu::kVerify;
}
- if (info.isFile() && (info.suffix() == "eml")) {
- operation_type |= MainWindow::OperationMenu::kVerifyEMail;
- }
-
emit SignalMainWindowlUpdateBasicalOperaMenu(operation_type);
}
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index 73328885..9498480e 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -328,6 +328,17 @@ auto KeyList::GetChecked() -> KeyIdArgsListPtr {
return ret;
}
+auto KeyList::GetCheckedKeys() -> QStringList {
+ auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget());
+ QStringList key_id_list;
+ for (int i = 0; i < key_table->GetRowCount(); i++) {
+ if (key_table->IsRowChecked(i)) {
+ key_id_list.append(key_table->GetKeyIdByRow(i));
+ }
+ }
+ return key_id_list;
+}
+
auto KeyList::GetAllPrivateKeys() -> KeyIdArgsListPtr {
auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget());
auto ret = std::make_unique<KeyIdArgsList>();
diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h
index 18c9576e..4216eba8 100644
--- a/src/ui/widgets/KeyList.h
+++ b/src/ui/widgets/KeyList.h
@@ -145,6 +145,13 @@ class KeyList : public QWidget {
auto GetChecked() -> KeyIdArgsListPtr;
/**
+ * @brief Get the Checked Keys object
+ *
+ * @return QStringList
+ */
+ auto GetCheckedKeys() -> QStringList;
+
+ /**
* @brief Get the Checked object
*
* @param key_table
diff --git a/src/ui/widgets/ModuleListView.cpp b/src/ui/widgets/ModuleListView.cpp
index 75396dde..835668b5 100644
--- a/src/ui/widgets/ModuleListView.cpp
+++ b/src/ui/widgets/ModuleListView.cpp
@@ -37,7 +37,7 @@ ModuleListView::ModuleListView(QWidget *parent)
setModel(model_);
setEditTriggers(QAbstractItemView::NoEditTriggers);
- load_module_informations();
+ load_module_information();
}
void ModuleListView::currentChanged(const QModelIndex &current,
@@ -49,7 +49,7 @@ void ModuleListView::currentChanged(const QModelIndex &current,
}
}
-void ModuleListView::load_module_informations() {
+void ModuleListView::load_module_information() {
auto &module_manager = Module::ModuleManager::GetInstance();
auto module_ids = module_manager.ListAllRegisteredModuleID();
diff --git a/src/ui/widgets/ModuleListView.h b/src/ui/widgets/ModuleListView.h
index 30922585..04a59797 100644
--- a/src/ui/widgets/ModuleListView.h
+++ b/src/ui/widgets/ModuleListView.h
@@ -48,6 +48,6 @@ class ModuleListView : public QListView {
private:
QStandardItemModel *model_;
- void load_module_informations();
+ void load_module_information();
};
}; // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/widgets/PlainTextEditorPage.h b/src/ui/widgets/PlainTextEditorPage.h
index c4423378..86ec0a56 100644
--- a/src/ui/widgets/PlainTextEditorPage.h
+++ b/src/ui/widgets/PlainTextEditorPage.h
@@ -115,8 +115,10 @@ class PlainTextEditorPage : public QWidget {
*/
void SignalUIBytesDisplayed();
- private:
+ protected:
std::shared_ptr<Ui_PlainTextEditor> ui_; ///<
+
+ private:
QString full_file_path_; ///< The path to the file handled in the tab
bool sign_marked_{}; ///< true, if the signed header is marked, false if not
bool read_done_ = false; ///<
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index 2b1f4766..1ea96fde 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -126,18 +126,31 @@ void TextEdit::SlotOpen() {
}
void TextEdit::SlotSave() {
- if (tab_widget_->count() == 0 || SlotCurPageTextEdit() == 0) {
+ if (tab_widget_->count() == 0) {
return;
}
- QString file_name = SlotCurPageTextEdit()->GetFilePath();
+ if (CurEMailPage() != nullptr) {
+ QString file_name = CurEMailPage()->GetFilePath();
- if (file_name.isEmpty()) {
- // QString docname = tabWidget->tabText(tabWidget->currentIndex());
- // docname.remove(0,2);
- SlotSaveAs();
- } else {
- saveFile(file_name);
+ if (file_name.isEmpty()) {
+ SlotSaveAsEML();
+ } else {
+ saveEMLFile(file_name);
+ }
+ return;
+ }
+
+ if (CurTextPage() != nullptr) {
+ QString file_name = SlotCurPageTextEdit()->GetFilePath();
+
+ if (file_name.isEmpty()) {
+ // QString docname = tabWidget->tabText(tabWidget->currentIndex());
+ // docname.remove(0,2);
+ SlotSaveAs();
+ } else {
+ saveFile(file_name);
+ }
}
}
@@ -171,6 +184,38 @@ auto TextEdit::saveFile(const QString& file_name) -> bool {
return false;
}
+auto TextEdit::saveEMLFile(const QString& file_name) -> bool {
+ if (file_name.isEmpty()) return false;
+
+ PlainTextEditorPage* page = CurEMailPage();
+ if (page == nullptr) return false;
+
+ QFile file(file_name);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QMessageBox::warning(
+ this, tr("Warning"),
+ tr("Cannot read file %1:\n%2.").arg(file_name).arg(file.errorString()));
+ return false;
+ }
+
+ QTextStream output_stream(&file);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ output_stream
+ << page->GetTextPage()->toPlainText().replace("\n", "\r\n").toLatin1();
+ QApplication::restoreOverrideCursor();
+ QTextDocument* document = page->GetTextPage()->document();
+
+ document->setModified(false);
+
+ int cur_index = tab_widget_->currentIndex();
+ tab_widget_->setTabText(cur_index, stripped_name(file_name));
+ page->SetFilePath(file_name);
+ page->NotifyFileSaved();
+
+ file.close();
+ return true;
+}
+
auto TextEdit::SlotSaveAs() -> bool {
if (tab_widget_->count() == 0 || SlotCurPageTextEdit() == nullptr) {
return true;
@@ -187,6 +232,22 @@ auto TextEdit::SlotSaveAs() -> bool {
return saveFile(QFileDialog::getSaveFileName(this, tr("Save file"), path));
}
+auto TextEdit::SlotSaveAsEML() -> bool {
+ if (tab_widget_->count() == 0 || CurEMailPage() == nullptr) {
+ return true;
+ }
+
+ PlainTextEditorPage* page = CurEMailPage();
+ QString path;
+ if (!page->GetFilePath().isEmpty()) {
+ path = page->GetFilePath();
+ } else {
+ path = tab_widget_->tabText(tab_widget_->currentIndex()).remove(0, 2);
+ }
+
+ return saveEMLFile(QFileDialog::getSaveFileName(this, tr("Save file"), path));
+}
+
void TextEdit::SlotCloseTab() {
slot_remove_tab(tab_widget_->currentIndex());
if (tab_widget_->count() != 0) {
@@ -321,6 +382,13 @@ auto TextEdit::MaybeSaveAnyTab() -> bool {
return false;
}
+void TextEdit::SlotSetText2CurEMailPage(const QString& text) {
+ if (CurTextPage() == nullptr) SlotNewEMailTab();
+ auto* edit = CurTextPage()->GetTextPage();
+ edit->clear();
+ edit->appendPlainText(text);
+}
+
void TextEdit::SlotAppendText2CurTextPage(const QString& text) {
if (CurTextPage() == nullptr) SlotNewTab();
CurTextPage()->GetTextPage()->appendPlainText(text);
@@ -554,4 +622,11 @@ auto TextEdit::CurPlainText() const -> QString {
}
auto TextEdit::TabWidget() const -> QTabWidget* { return tab_widget_; }
+
+auto TextEdit::CurEMailPage() const -> EMailEditorPage* {
+ return tab_widget_->CurEMailPage();
+}
+
+void TextEdit::SlotNewEMailTab() { tab_widget_->SlotNewEMailTab(); }
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/TextEdit.h b/src/ui/widgets/TextEdit.h
index 30540569..68b648e5 100644
--- a/src/ui/widgets/TextEdit.h
+++ b/src/ui/widgets/TextEdit.h
@@ -29,6 +29,7 @@
#pragma once
#include "ui/dialog/QuitDialog.h"
+#include "ui/widgets/EMailEditorPage.h"
#include "ui/widgets/FilePage.h"
#include "ui/widgets/PlainTextEditorPage.h"
@@ -78,6 +79,13 @@ class TextEdit : public QWidget {
/**
* @brief
*
+ * @return EMailEditorPage*
+ */
+ [[nodiscard]] auto CurEMailPage() const -> EMailEditorPage*;
+
+ /**
+ * @brief
+ *
* @return FilePage*
*/
[[nodiscard]] auto CurFilePage() const -> FilePage*;
@@ -161,6 +169,12 @@ class TextEdit : public QWidget {
void SlotNewTab();
/**
+ * @details Adds a new tab with the title "untitled"+countpage+".eml"
+ * Sets the focus to the new tab. Increase Tab-Count by one
+ */
+ void SlotNewEMailTab();
+
+ /**
* @details
*
*/
@@ -260,6 +274,21 @@ class TextEdit : public QWidget {
*/
void SlotAppendText2CurTextPage(const QString& text);
+ /**
+ * @brief
+ *
+ * @param text
+ */
+ void SlotSetText2CurEMailPage(const QString& text);
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ auto SlotSaveAsEML() -> bool;
+
protected:
/**
* @brief Saves the content of currentTab to the file filename
@@ -268,6 +297,13 @@ class TextEdit : public QWidget {
*/
auto saveFile(const QString& file_name) -> bool;
+ /**
+ * @brief
+ *
+ * @return auto
+ */
+ auto saveEMLFile(const QString& file_name) -> bool;
+
private slots:
/**
diff --git a/src/ui/widgets/TextEditTabWidget.cpp b/src/ui/widgets/TextEditTabWidget.cpp
index 97826f03..8007eb85 100644
--- a/src/ui/widgets/TextEditTabWidget.cpp
+++ b/src/ui/widgets/TextEditTabWidget.cpp
@@ -31,8 +31,9 @@
#include "core/function/GlobalSettingStation.h"
#include "core/model/CacheObject.h"
#include "ui/UISignalStation.h"
+#include "ui/widgets/EMailEditorPage.h"
+#include "ui/widgets/FilePage.h"
#include "ui/widgets/PlainTextEditorPage.h"
-#include "widgets/FilePage.h"
namespace GpgFrontend::UI {
@@ -80,6 +81,11 @@ void TextEditTabWidget::dropEvent(QDropEvent* event) {
continue;
}
+ if (file_info.suffix() == "eml") {
+ SlotOpenEMLFile(local_file);
+ return;
+ }
+
SlotOpenFile(local_file);
}
@@ -125,29 +131,58 @@ void TextEditTabWidget::SlotOpenFile(const QString& path) {
file.close();
}
-void TextEditTabWidget::SlotShowModified(bool changed) {
+
+void TextEditTabWidget::SlotOpenEMLFile(const QString& path) {
+ QFile file(path);
+ auto result = file.open(QIODevice::ReadOnly | QIODevice::Text);
+ if (result) {
+ auto* page = new EMailEditorPage(path, this);
+
+ connect(page->GetTextPage(), &QPlainTextEdit::textChanged, this,
+ &TextEditTabWidget::SlotShowModified);
+ connect(page->GetTextPage(), &QPlainTextEdit::selectionChanged, this,
+ &TextEditTabWidget::slot_save_status_to_cache_for_recovery);
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ auto index = this->addTab(page, stripped_name(path));
+ this->setTabIcon(index, QIcon(":/icons/email.png"));
+ this->setCurrentIndex(this->count() - 1);
+ QApplication::restoreOverrideCursor();
+ page->GetTextPage()->setFocus();
+ page->ReadFile();
+ } else {
+ QMessageBox::warning(
+ this, tr("Warning"),
+ tr("Cannot read file %1:\n%2.").arg(path).arg(file.errorString()));
+ }
+
+ file.close();
+}
+
+void TextEditTabWidget::SlotShowModified() {
// get current tab
int index = this->currentIndex();
- QString title = this->tabText(index);
+ QString title = this->tabText(index).trimmed();
- // if changed
- if (!changed) {
- this->setTabText(index, title.remove(0, 2));
- return;
- }
+ if (title.startsWith("*")) return;
// if doc is modified now, add leading * to title,
// otherwise remove the leading * from the title
if (CurTextPage()->GetTextPage()->document()->isModified()) {
- this->setTabText(index, title.trimmed().prepend("* "));
+ this->setTabText(index, title.prepend("* "));
} else {
this->setTabText(index, title.remove(0, 2));
}
}
+
auto TextEditTabWidget::CurTextPage() const -> PlainTextEditorPage* {
return qobject_cast<PlainTextEditorPage*>(this->currentWidget());
}
+auto TextEditTabWidget::CurEMailPage() const -> EMailEditorPage* {
+ return qobject_cast<EMailEditorPage*>(this->currentWidget());
+}
+
auto TextEditTabWidget::SlotCurPageTextEdit() -> PlainTextEditorPage* {
auto* cur_page = qobject_cast<PlainTextEditorPage*>(this->currentWidget());
return cur_page;
@@ -228,6 +263,22 @@ void TextEditTabWidget::SlotNewTab() {
connect(page->GetTextPage()->document(), &QTextDocument::contentsChanged,
this, &TextEditTabWidget::slot_save_status_to_cache_for_recovery);
}
+
+void TextEditTabWidget::SlotNewEMailTab() {
+ QString header = tr("untitled") + QString::number(++count_page_) + ".eml";
+
+ auto* page = new EMailEditorPage();
+ auto index = this->addTab(page, header);
+ this->setTabIcon(index, QIcon(":/icons/email.png"));
+ this->setCurrentIndex(this->count() - 1);
+ page->GetTextPage()->setFocus();
+
+ connect(page->GetTextPage(), &QPlainTextEdit::textChanged, this,
+ &TextEditTabWidget::SlotShowModified);
+ connect(page->GetTextPage(), &QPlainTextEdit::selectionChanged, this,
+ &TextEditTabWidget::slot_save_status_to_cache_for_recovery);
+}
+
void TextEditTabWidget::SlotNewTabWithContent(QString title,
const QString& content) {
QString header = tr("untitled") + QString::number(++count_page_) + ".txt";
diff --git a/src/ui/widgets/TextEditTabWidget.h b/src/ui/widgets/TextEditTabWidget.h
index b0cafae2..13ed00f0 100644
--- a/src/ui/widgets/TextEditTabWidget.h
+++ b/src/ui/widgets/TextEditTabWidget.h
@@ -28,10 +28,11 @@
#pragma once
-#include "widgets/FilePage.h"
namespace GpgFrontend::UI {
class PlainTextEditorPage;
+class EMailEditorPage;
+class FilePage;
class TextEditTabWidget : public QTabWidget {
Q_OBJECT
@@ -49,6 +50,12 @@ class TextEditTabWidget : public QTabWidget {
/**
* @brief
*
+ */
+ void SlotNewEMailTab();
+
+ /**
+ * @brief
+ *
* @param title
* @param content
*/
@@ -62,6 +69,13 @@ class TextEditTabWidget : public QTabWidget {
/**
* @brief
*
+ * @param path
+ */
+ void SlotOpenEMLFile(const QString& path);
+
+ /**
+ * @brief
+ *
*/
void SlotOpenDirectory(const QString& target_directory);
@@ -69,7 +83,7 @@ class TextEditTabWidget : public QTabWidget {
* @details put a * in front of current tabs title, if current textedit is
* modified
*/
- void SlotShowModified(bool);
+ void SlotShowModified();
/**
* @brief
@@ -83,6 +97,13 @@ class TextEditTabWidget : public QTabWidget {
*
* @return PlainTextEditorPage*
*/
+ [[nodiscard]] auto CurEMailPage() const -> EMailEditorPage*;
+
+ /**
+ * @brief
+ *
+ * @return PlainTextEditorPage*
+ */
auto SlotCurPageTextEdit() -> PlainTextEditorPage*;
/**
diff --git a/third_party/qttranslations b/third_party/qttranslations
-Subproject c4da2d3ed4511af796f88d0718aa9258908cc82
+Subproject 62d8170d01b861e58a6fa91c3f9ece4b9f9cc3a
diff --git a/ui/EmailListEditor.ui b/ui/EmailListEditor.ui
deleted file mode 100644
index 5cc0ddef..00000000
--- a/ui/EmailListEditor.ui
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>EmailListEditorDialog</class>
- <widget class="QDialog" name="EmailListEditorDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>618</width>
- <height>498</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Email List Editor</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="titleLabel">
- <property name="text">
- <string>Email List:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QListWidget" name="emaillistWidget">
- <property name="editTriggers">
- <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
- </property>
- <property name="dragEnabled">
- <bool>true</bool>
- </property>
- <property name="isWrapping" stdset="0">
- <bool>false</bool>
- </property>
- <property name="spacing">
- <number>6</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addEmailAddressButton">
- <property name="text">
- <string>Add An Email Address</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="tipsLabel">
- <property name="text">
- <string>Tips: You can double-click the email address in the edit list, or click the email to pop up the option menu.</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- <action name="actionDelete_Selected_Email_Address">
- <property name="text">
- <string>Delete Selected Email Address</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/ui/ModuleControllerDialog.ui b/ui/ModuleControllerDialog.ui
index 910a3de8..ac61c45a 100644
--- a/ui/ModuleControllerDialog.ui
+++ b/ui/ModuleControllerDialog.ui
@@ -86,7 +86,7 @@
<item>
<widget class="QLabel" name="moduleInfoLabel">
<property name="text">
- <string>Module Informations</string>
+ <string>Module Information</string>
</property>
</widget>
</item>
diff --git a/ui/PlainTextEditor.ui b/ui/PlainTextEditor.ui
index 266eba56..241c6f50 100644
--- a/ui/PlainTextEditor.ui
+++ b/ui/PlainTextEditor.ui
@@ -39,6 +39,12 @@
<property name="spacing">
<number>12</number>
</property>
+ <property name="leftMargin">
+ <number>5</number>
+ </property>
+ <property name="rightMargin">
+ <number>5</number>
+ </property>
<item>
<widget class="QLabel" name="loadingLabel">
<property name="text">
@@ -49,7 +55,7 @@
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
diff --git a/ui/SendMailDialog.ui b/ui/SendMailDialog.ui
deleted file mode 100644
index f68d2f45..00000000
--- a/ui/SendMailDialog.ui
+++ /dev/null
@@ -1,469 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>SendMailDialog</class>
- <widget class="QDialog" name="SendMailDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>995</width>
- <height>760</height>
- </rect>
- </property>
- <property name="cursor">
- <cursorShape>ArrowCursor</cursorShape>
- </property>
- <property name="contextMenuPolicy">
- <enum>Qt::NoContextMenu</enum>
- </property>
- <property name="windowTitle">
- <string>New Message</string>
- </property>
- <property name="sizeGripEnabled">
- <bool>false</bool>
- </property>
- <property name="modal">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QWidget" name="horizontalWidget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="senderLabel">
- <property name="text">
- <string>Sender</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="senderEdit"/>
- </item>
- <item>
- <widget class="Line" name="line">
- <property name="toolTipDuration">
- <number>0</number>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="lineWidth">
- <number>2</number>
- </property>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="ccButton">
- <property name="text">
- <string>CC</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="bccButton">
- <property name="text">
- <string>BCC</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="horizontalWidget_4" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="recipientLabel">
- <property name="text">
- <string>Recipient(s)</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="recipientEdit"/>
- </item>
- <item>
- <widget class="QPushButton" name="recipientsEditButton">
- <property name="text">
- <string>Edit Recipients(s)</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="horizontalWidget_5" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="subjectLabel">
- <property name="text">
- <string>Mail Subject</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="subjectEdit"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="horizontalWidget_6" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_9">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="gpgOperaLabel">
- <property name="text">
- <string>GPG Operations</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="senderKeySelectButton">
- <property name="text">
- <string>Select Sender GPG Key</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="recipientKeySelectButton">
- <property name="text">
- <string>Select Recipient(s) GPG Key</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="ccInputWidget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="ccLabel">
- <property name="text">
- <string>CC</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="ccEdit"/>
- </item>
- <item>
- <widget class="QPushButton" name="ccEditButton">
- <property name="text">
- <string>Edit CC(s)</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="bccInputWidget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="bccLabel">
- <property name="text">
- <string>BCC</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="bccEdit"/>
- </item>
- <item>
- <widget class="QPushButton" name="bccEditButton">
- <property name="text">
- <string>Edit BCC(s)</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="tipsLabel">
- <property name="text">
- <string>Tips: You can fill in multiple email addresses, please separate them with &quot;;&quot;.</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTextEdit" name="textEdit"/>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <item alignment="Qt::AlignLeft|Qt::AlignVCenter">
- <widget class="QLabel" name="senderKeyLabel">
- <property name="text">
- <string>Sender GPG Key:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="senderKeyValueLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_10">
- <item alignment="Qt::AlignLeft|Qt::AlignVCenter">
- <widget class="QLabel" name="recipientKeysLabel">
- <property name="text">
- <string>Recipient(s) GPG Key:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="recipientsKeyValueLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QLabel" name="errorLabel">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <item>
- <widget class="QCheckBox" name="contentEncryptCheckBox">
- <property name="text">
- <string>Encrypt content</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="attacSignatureCheckBox">
- <property name="text">
- <string>Attach signature</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="attachSenderPublickeyCheckBox">
- <property name="text">
- <string>Attach sender's public key</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item alignment="Qt::AlignRight">
- <widget class="QPushButton" name="sendMailButton">
- <property name="text">
- <string>Send Mail</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>