aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitea/workflows/develop-qt5.yml13
-rw-r--r--.gitea/workflows/develop-qt6.yml27
-rw-r--r--.github/workflows/release-qt5.yml12
-rw-r--r--.github/workflows/release.yml4
-rw-r--r--.github/workflows/testing-nightly.yml15
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/core/function/GlobalSettingStation.cpp6
-rw-r--r--src/core/function/gpg/GpgContext.cpp12
-rw-r--r--src/ui/dialog/Wizard.cpp167
-rw-r--r--src/ui/widgets/FilePage.cpp29
-rw-r--r--src/ui/widgets/FilePage.h2
-rw-r--r--src/ui/widgets/FileTreeView.cpp82
-rw-r--r--src/ui/widgets/FileTreeView.h6
-rw-r--r--ui/FilePage.ui23
15 files changed, 200 insertions, 206 deletions
diff --git a/.gitea/workflows/develop-qt5.yml b/.gitea/workflows/develop-qt5.yml
index 3bfc405a..9d31214a 100644
--- a/.gitea/workflows/develop-qt5.yml
+++ b/.gitea/workflows/develop-qt5.yml
@@ -27,12 +27,7 @@ name: Develop CI Qt5
on:
push:
- branches: ["dev/**"]
- paths-ignore:
- - "resource/lfs/locale/**"
- - "**.md"
- pull_request:
- branches: ["dev/**"]
+ branches: ["develop", "dev/**"]
paths-ignore:
- "resource/lfs/locale/**"
- "**.md"
@@ -84,11 +79,11 @@ jobs:
run: |
mkdir ${{github.workspace}}/build/final-artifact
cd ${{github.workspace}}/build/final-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
+ wget -O linuxdeployqt.AppImage -c -nv https://ftp.bktus.com/linuxdeployqt/linuxdeployqt-01052025-x86_64.AppImage
+ chmod u+x linuxdeployqt.AppImage
mkdir -p ${{github.workspace}}/build/artifacts/AppDir/usr/share/doc/libc6
touch ${{github.workspace}}/build/artifacts/AppDir/usr/share/doc/libc6/copyright
- ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms/libqoffscreen.so -appimage -unsupported-allow-new-glibc
+ ./linuxdeployqt.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms/libqoffscreen.so -appimage -unsupported-allow-new-glibc
echo "BUILD_TYPE_LOWER=${BUILD_TYPE,,}" >> ${GITHUB_ENV}
echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> ${GITHUB_ENV}
diff --git a/.gitea/workflows/develop-qt6.yml b/.gitea/workflows/develop-qt6.yml
index 794fedc2..65dcf6cb 100644
--- a/.gitea/workflows/develop-qt6.yml
+++ b/.gitea/workflows/develop-qt6.yml
@@ -27,16 +27,10 @@ name: Develop CI Qt6
on:
push:
- branches: ["dev/**"]
+ branches: ["develop", "dev/**"]
paths-ignore:
- "resource/lfs/locale/**"
- "**.md"
- pull_request:
- branches: ["dev/**"]
- paths-ignore:
- - "resource/lfs/locale/**"
- - "**.md"
-
env:
BUILD_TYPE: Debug
@@ -79,18 +73,6 @@ jobs:
ninja
sudo ninja install
- - name: Build & Install Full SDK
- run: |
- cmake -B ${{github.workspace}}/build-full-sdk -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_TYPE_FULL_SDK=ON
- cmake --build ${{github.workspace}}/build-full-sdk --config {{$env.BUILD_TYPE}} -- -v
- sudo cmake --install ${{github.workspace}}/build-full-sdk --config {{$env.BUILD_TYPE}}
-
- - name: Build Integrated Modules
- run: |
- cmake -S ${{github.workspace}}/modules -B ${{github.workspace}}/modules/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/modules/build/artifacts
- cmake --build ${{github.workspace}}/modules/build --config {{$env.BUILD_TYPE}} -- -v
- cmake --install ${{github.workspace}}/modules/build --config {{$env.BUILD_TYPE}}
-
- name: Build GpgFrontend
run: |
cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_BUILD_APP_IMAGE=On
@@ -101,17 +83,16 @@ jobs:
- name: Copy Modules & Package App Image
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
- wget -c -nv https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
- chmod u+x linuxdeployqt-continuous-x86_64.AppImage
+ wget -O linuxdeployqt.AppImage -c -nv https://ftp.bktus.com/linuxdeployqt/linuxdeployqt-01052025-x86_64.AppImage
+ chmod u+x linuxdeployqt.AppImage
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
qtchooser -install qt6 $(which qmake6)
export QT_SELECT=qt6
mkdir -p ${{github.workspace}}/build/artifacts/AppDir/usr/share/doc/libc6
touch ${{github.workspace}}/build/artifacts/AppDir/usr/share/doc/libc6/copyright
- ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms/libqoffscreen.so -appimage -executable-dir=${{github.workspace}}/build/artifacts/AppDir/usr/modules/ -unsupported-allow-new-glibc
+ ./linuxdeployqt.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms/libqoffscreen.so -appimage -executable-dir=${{github.workspace}}/build/artifacts/AppDir/usr/lib/modules -unsupported-allow-new-glibc
echo "BUILD_TYPE_LOWER=${BUILD_TYPE,,}" >> ${GITHUB_ENV}
echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> ${GITHUB_ENV}
diff --git a/.github/workflows/release-qt5.yml b/.github/workflows/release-qt5.yml
index fd1f7ba0..8fdf1fc4 100644
--- a/.github/workflows/release-qt5.yml
+++ b/.github/workflows/release-qt5.yml
@@ -184,7 +184,7 @@ jobs:
- name: Build GpgFrontend (Linux)
run: |
- cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_QT5_BUILD=ON
+ cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DGPGFRONTEND_QT5_BUILD=ON -DGPGFRONTEND_BUILD_APP_IMAGE=ON
cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -v
if: runner.os == 'Linux'
@@ -242,13 +242,13 @@ jobs:
cp TRANSLATORS build/artifacts/
cp COPYING build/artifacts/
cp gpgfrontend.ico build/artifacts/bin/
- rm -rf build/artifacts/bin/modules/*.a
+ rm -rf build/artifacts/bin/*.a
touch build/artifacts/bin/PORTABLE.txt
cd build
- windeployqt-qt6 --no-translations --force ./artifacts/bin/libgf_core.dll
- windeployqt-qt6 --no-translations --force ./artifacts/bin/libgf_ui.dll
- windeployqt-qt6 --no-translations --force ./artifacts/bin/libgf_test.dll
- windeployqt-qt6 --no-translations --force ./artifacts/bin/GpgFrontend.exe
+ windeployqt --no-translations --force ./artifacts/bin/libgf_core.dll
+ windeployqt --no-translations --force ./artifacts/bin/libgf_ui.dll
+ windeployqt --no-translations --force ./artifacts/bin/libgf_test.dll
+ windeployqt --no-translations --force ./artifacts/bin/GpgFrontend.exe
mkdir upload-artifact
cd artifacts
zip -r ../upload-artifact/GpgFrontend-${{env.SHORT_SHA}}-x86_64.zip *
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ab0b4f79..d94b6e87 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -262,7 +262,7 @@ jobs:
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
- ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms,wayland-graphics-integration-client,wayland-decoration-client,wayland-shell-integration -appimage
+ ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms,wayland-graphics-integration-client,wayland-decoration-client,wayland-shell-integration -appimage -executable-dir=${{github.workspace}}/build/artifacts/AppDir/usr/lib/modules
echo "BUILD_TYPE_LOWER=${BUILD_TYPE,,}" >> ${GITHUB_ENV}
echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> ${GITHUB_ENV}
if: runner.os == 'Linux'
@@ -319,7 +319,9 @@ jobs:
cp TRANSLATORS build/artifacts/
cp COPYING build/artifacts/
cp gpgfrontend.ico build/artifacts/bin/
+ rm -rf build/artifacts/bin/*.a
rm -rf build/artifacts/bin/modules/*.a
+ mv build/artifacts/bin/modules build/artifacts/modules
touch build/artifacts/bin/PORTABLE.txt
cd build
windeployqt-qt6 --no-translations --force ./artifacts/bin/libgf_core.dll
diff --git a/.github/workflows/testing-nightly.yml b/.github/workflows/testing-nightly.yml
index 1a41b8e6..6d4eac6a 100644
--- a/.github/workflows/testing-nightly.yml
+++ b/.github/workflows/testing-nightly.yml
@@ -249,7 +249,7 @@ jobs:
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
- ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms,wayland-graphics-integration-client,wayland-decoration-client,wayland-shell-integration -appimage
+ ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/artifacts/AppDir/usr/share/applications/*.desktop -no-translations -extra-plugins=iconengines,platforms,wayland-graphics-integration-client,wayland-decoration-client,wayland-shell-integration -appimage -executable-dir=${{github.workspace}}/build/artifacts/AppDir/usr/lib/modules
echo "BUILD_TYPE_LOWER=${BUILD_TYPE,,}" >> ${GITHUB_ENV}
echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> ${GITHUB_ENV}
if: runner.os == 'Linux'
@@ -306,7 +306,9 @@ jobs:
cp TRANSLATORS build/artifacts/
cp COPYING build/artifacts/
cp gpgfrontend.ico build/artifacts/bin/
+ rm -rf build/artifacts/bin/*.a
rm -rf build/artifacts/bin/modules/*.a
+ mv build/artifacts/bin/modules build/artifacts/modules
touch build/artifacts/bin/PORTABLE.txt
cd build
windeployqt-qt6 --no-translations --force ./artifacts/bin/libgf_core.dll
@@ -358,13 +360,22 @@ jobs:
- name: List files
run: ls -rl artifacts/
+ - name: Generate Release Title with Date
+ id: release_title
+ run: echo "title=Nightly Build $(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+
+ - name: Delete Old Nightly Release
+ run: gh release delete --repo saturneric/GpgFrontend --cleanup-tag --yes nightly
+ env:
+ GH_TOKEN: ${{ secrets.USER_GITHUB_TOKEN }}
+
- name: Update Nightly Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.USER_GITHUB_TOKEN }}
with:
tag_name: nightly
- name: "Nightly Build"
+ name: ${{ steps.release_title.outputs.title }}
draft: false
prerelease: true
body: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0664e51e..02d8cd59 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,9 +23,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-cmake_minimum_required(VERSION 3.16)
-
-message(STATUS "Current Generator: ${CMAKE_GENERATOR}")
+cmake_minimum_required(VERSION 3.24)
if(CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_SOURCE_DIR}/cmake/FlagsOverridesXcode.cmake")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 828f5f9f..3d58193b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -487,7 +487,7 @@ if(BUILD_APP_FOR_PACKAGE)
set(CPACK_RPM_PACKAGE_LICENSE "GPLv3")
set(CPACK_RPM_PACKAGE_GROUP "Applications/System")
set(CPACK_RPM_PACKAGE_REQUIRES
- "libassuan >= 2.5.0, gpgme >= 1.12.0, qt6-qtbase >= 6.0.0, gtk-update-icon-cache")
+ "gpgme >= 1.24.2, qt6-qtbase >= 6.4.2, qt6-qtbase-gui >= 6.4.2, libarchive >= 3.6.2, gtk-update-icon-cache")
set(CPACK_RPM_PACKAGE_URL "${CPACK_PACKAGE_HOMEPAGE_URL}")
set(CPACK_RPM_PACKAGE_LICENSE_FILE "${CMAKE_SOURCE_DIR}/COPYING")
set(CPACK_RPM_PACKAGE_DOCUMENTATION "${CMAKE_SOURCE_DIR}/README.md")
@@ -508,7 +508,7 @@ if(BUILD_APP_FOR_PACKAGE)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "[email protected]")
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
set(CPACK_DEBIAN_PACKAGE_DEPENDS
- "libassuan0 (>= 2.5.0), libgpgme11 (>= 1.12.0), qt6-base-dev (>= 6.0.0), gtk-update-icon-cache")
+ "libgpgme11t64 (>= 1.24.2), libqt6core6t64 (>= 6.4.2), libqt6gui6t64 (>= 6.4.2), libqt6widgets6t64 (>= 6.4.2), libarchive13 (>= 3.6.2), gtk-update-icon-cache")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_PACKAGE_HOMEPAGE_URL}")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
set(CPACK_DEBIAN_PACKAGE_LICENSE "GPLv3")
diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp
index 21f1c743..28b4ade7 100644
--- a/src/core/function/GlobalSettingStation.cpp
+++ b/src/core/function/GlobalSettingStation.cpp
@@ -170,13 +170,7 @@ class GlobalSettingStation::Impl {
#endif
#if defined(_WIN32) || defined(WIN32)
-
-#ifdef NDEBUG
return exec_binary_path + "/../modules";
-#else
- return exec_binary_path + "/../modules/bin";
-#endif
-
#endif
#if defined(__APPLE__) && defined(__MACH__)
diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp
index 49d39650..0f7d30de 100644
--- a/src/core/function/gpg/GpgContext.cpp
+++ b/src/core/function/gpg/GpgContext.cpp
@@ -88,7 +88,7 @@ class GpgAgentProcess {
args.append("--disable-scdaemon");
}
- LOG_E() << "gpg-agent start args: " << args << "channel:" << channel_;
+ LOG_D() << "gpg-agent start args: " << args << "channel:" << channel_;
process_.setProgram(info.absoluteFilePath());
process_.setArguments(args);
@@ -162,8 +162,8 @@ class GpgContext::Impl {
[[nodiscard]] auto Good() const -> bool { return good_; }
- auto SetPassphraseCb(const gpgme_ctx_t &ctx,
- gpgme_passphrase_cb_t cb) -> bool {
+ auto SetPassphraseCb(const gpgme_ctx_t &ctx, gpgme_passphrase_cb_t cb)
+ -> bool {
if (gpgme_get_pinentry_mode(ctx) != GPGME_PINENTRY_MODE_LOOPBACK) {
if (CheckGpgError(gpgme_set_pinentry_mode(
ctx, GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) {
@@ -258,8 +258,8 @@ class GpgContext::Impl {
return res == pass_size + 1 ? 0 : GPG_ERR_CANCELED;
}
- static auto TestStatusCb(void *hook, const char *keyword,
- const char *args) -> gpgme_error_t {
+ static auto TestStatusCb(void *hook, const char *keyword, const char *args)
+ -> gpgme_error_t {
FLOG_D("keyword %s", keyword);
return GPG_ERR_NO_ERROR;
}
@@ -544,7 +544,7 @@ class GpgContext::Impl {
args.append({"--kill", "gpg-agent"});
- LOG_E() << "gpgconf kill args: " << args
+ LOG_D() << "gpgconf kill args: " << args
<< "channel:" << parent_->GetChannel();
QProcess process;
diff --git a/src/ui/dialog/Wizard.cpp b/src/ui/dialog/Wizard.cpp
index a126d995..4f2dbbdf 100644
--- a/src/ui/dialog/Wizard.cpp
+++ b/src/ui/dialog/Wizard.cpp
@@ -59,84 +59,87 @@ void Wizard::slot_wizard_accepted() {
}
IntroPage::IntroPage(QWidget* parent) : QWizardPage(parent) {
- setTitle(tr("Getting Started..."));
- setSubTitle(tr("... with GpgFrontend"));
-
- auto* top_label = new QLabel(
- tr("Welcome to GpgFrontend for decrypting and signing text or files!") +
- " <br><br><a href='https://gpgfrontend.bktus.com'>GpgFrontend</a> " +
- tr("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and "
- "Installation-Free OpenPGP Crypto Tool. ") +
- tr("To get started, be sure to check out the") +
+ setTitle(tr("Welcome to GpgFrontend"));
+ setSubTitle(tr("Your OpenPGP encryption companion."));
+
+ // Intro text
+ auto* intro_label = new QLabel(
+ tr("<b>GpgFrontend</b> is a free, user-friendly, and cross-platform tool "
+ "for "
+ "OpenPGP encryption, decryption, and signing of text and files.") +
+ "<br><br>" + tr("To get started, take a quick look at the") +
" <a href='https://gpgfrontend.bktus.com/overview/glance'>" +
- tr("Overview") + "</a> (" +
- tr("by clicking the link, the page will open in your web browser") +
- "). <br>");
- top_label->setTextFormat(Qt::RichText);
- top_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
- top_label->setOpenExternalLinks(true);
- top_label->setWordWrap(true);
-
- // QComboBox for language selection
+ tr("Overview Page") + "</a>." + " " +
+ tr("It will open in your default browser."));
+ intro_label->setTextFormat(Qt::RichText);
+ intro_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ intro_label->setOpenExternalLinks(true);
+ intro_label->setWordWrap(true);
+
+ // Language info
auto* lang_label =
- new QLabel(tr("If it supports the language currently being used in your "
- "system, GpgFrontend will automatically set it."));
+ new QLabel(tr("GpgFrontend will automatically use the language of your "
+ "system if supported. "
+ "You can change the language later in settings."));
lang_label->setWordWrap(true);
- // set layout and add widgets
+ // Layout
auto* layout = new QVBoxLayout;
- layout->addWidget(top_label);
- layout->addStretch();
+ layout->addWidget(intro_label);
+ layout->addSpacing(20);
layout->addWidget(lang_label);
-
+ layout->addStretch();
setLayout(layout);
}
auto IntroPage::nextId() const -> int { return Wizard::kPAGE_CHOOSE; }
ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) {
- setTitle(tr("Choose your action..."));
- setSubTitle(tr("...by clicking on the appropriate link."));
-
- auto* keygen_label = new QLabel(
- tr("If you have never used GpgFrontend before and also don't own a gpg "
- "key yet you may possibly want to read how to") +
- " <a href=\"https://gpgfrontend.bktus.com/guides/generate-key\">" +
- tr("Generate Key") + "</a><hr>");
- keygen_label->setTextFormat(Qt::RichText);
- keygen_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
- keygen_label->setOpenExternalLinks(true);
- keygen_label->setWordWrap(true);
-
- auto* encr_decy_text_label = new QLabel(
- tr("If you want to learn how to encrypt, decrypt, sign and verify text, "
- "you can read ") +
- "<a href=\"https://gpgfrontend.bktus.com/guides/encrypt-decrypt-text\">" +
- tr("Encrypt & Decrypt Text") + "</a> " + tr("or") +
- " <a href=\"https://gpgfrontend.bktus.com/guides/sign-verify-text\">" +
- tr("Sign & Verify Text") + "</a><hr>");
-
- encr_decy_text_label->setTextFormat(Qt::RichText);
- encr_decy_text_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
- encr_decy_text_label->setOpenExternalLinks(true);
- encr_decy_text_label->setWordWrap(true);
-
- auto* sign_verify_text_label = new QLabel(
- tr("If you want to operate file, you can read ") +
- "<a href=\"https://gpgfrontend.bktus.com/guides/encrypt-decrypt-file\">" +
- tr("Encrypt & Sign File") + "</a> " + tr("or") +
- " <a href=\"https://gpgfrontend.bktus.com/guides/sign-verify-file\">" +
- tr("Sign & Verify File") + "</a><hr>");
- sign_verify_text_label->setTextFormat(Qt::RichText);
- sign_verify_text_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
- sign_verify_text_label->setOpenExternalLinks(true);
- sign_verify_text_label->setWordWrap(true);
-
- auto* layout = new QVBoxLayout();
- layout->addWidget(keygen_label);
- layout->addWidget(encr_decy_text_label);
- layout->addWidget(sign_verify_text_label);
+ setTitle(tr("Welcome to GpgFrontend"));
+ setSubTitle(tr("These quick guides will help you get started."));
+
+ auto* layout = new QVBoxLayout;
+
+ // Section 1: Fundamental Concepts
+ auto* concepts_title = new QLabel(tr("<b>New to encryption?</b>"));
+ auto* concepts_desc = new QLabel(
+ tr("Understand the basics of OpenPGP and how GpgFrontend works."));
+ auto* concepts_link = new QLabel(
+ "<a "
+ "href=\"https://gpgfrontend.bktus.com/guides/fundamental-concepts/\">" +
+ tr("Fundamental Concepts") + "</a>");
+
+ // Section 2: Text operations
+ auto* textops_title = new QLabel(tr("<b>Working with text?</b>"));
+ auto* textops_desc = new QLabel(
+ tr("Learn how to encrypt, decrypt, sign, and verify text messages."));
+ auto* textops_link = new QLabel(
+ "<a href=\"https://gpgfrontend.bktus.com/guides/text-opetations/\">" +
+ tr("Text Operations Guide") + "</a>");
+
+ // Section 3: File operations
+ auto* fileops_title = new QLabel(tr("<b>Working with files?</b>"));
+ auto* fileops_desc =
+ new QLabel(tr("Learn how to encrypt, sign, and verify files securely."));
+ auto* fileops_link = new QLabel(
+ "<a href=\"https://gpgfrontend.bktus.com/guides/file-operations/\">" +
+ tr("File Operations Guide") + "</a>");
+
+ // All labels: uniform setup
+ const QList<QLabel*> labels = {concepts_title, concepts_desc, concepts_link,
+ textops_title, textops_desc, textops_link,
+ fileops_title, fileops_desc, fileops_link};
+ for (auto* l : labels) {
+ l->setTextFormat(Qt::RichText);
+ l->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ l->setOpenExternalLinks(true);
+ l->setWordWrap(true);
+ layout->addWidget(l);
+ }
+
+ layout->addStretch(); // push content upward
setLayout(layout);
+
next_page_ = Wizard::kPAGE_CONCLUSION;
}
@@ -152,42 +155,46 @@ void ChoosePage::slot_jump_page(const QString& page) {
}
ConclusionPage::ConclusionPage(QWidget* parent) : QWizardPage(parent) {
- setTitle(tr("Ready."));
- setSubTitle(tr("Have fun with GpgFrontend!"));
+ setTitle(tr("You're all set!"));
+ setSubTitle(tr("GpgFrontend is ready to use."));
auto* bottom_label = new QLabel(
- tr("You are ready to use GpgFrontend now.<br><br>") +
- "<a href=\"https://gpgfrontend.bktus.com/guides/fundamental-concepts\">" +
- tr("The Online Document") + "</a>" +
- tr(" will get you started with GpgFrontend. Anytime you encounter "
- "problems, please try to find help from the documentation") +
- "<br>");
-
+ tr("GpgFrontend is now fully set up and ready to go.") + "<br><br>" +
+ tr("If you encounter any issues or have questions, feel free to ") +
+ "<a href=\"https://github.com/saturneric/GpgFrontend/issues\">" +
+ tr("submit an issue on GitHub") + "</a> " + tr("or ") +
+ "<a href=\"https://gpgfrontend.bktus.com/overview/contact/\">" +
+ tr("contact the developer") + "</a>." + "<br>" +
+ tr("Any feedback is welcome and valuable!"));
bottom_label->setTextFormat(Qt::RichText);
bottom_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
bottom_label->setOpenExternalLinks(true);
bottom_label->setWordWrap(true);
- open_help_check_box_ = new QCheckBox(tr("Open offline help."));
+ // Option checkboxes
+ open_help_check_box_ = new QCheckBox(tr("Open offline help now"));
open_help_check_box_->setChecked(true);
dont_show_wizard_checkbox_ =
- new QCheckBox(tr("Don't show the wizard again."));
+ new QCheckBox(tr("Don't show this setup wizard again"));
dont_show_wizard_checkbox_->setChecked(true);
- check_updates_checkbox_ =
- new QCheckBox(tr("Check for updates at each startup."));
+ check_updates_checkbox_ = new QCheckBox(tr("Check for updates on startup"));
check_updates_checkbox_->setChecked(true);
+ // Register fields
registerField("showWizard", dont_show_wizard_checkbox_);
registerField("checkUpdate", check_updates_checkbox_);
+ // Layout
auto* layout = new QVBoxLayout;
layout->addWidget(bottom_label);
- layout->addWidget(dont_show_wizard_checkbox_);
+ layout->addSpacing(15);
+ // layout->addWidget(open_help_check_box_);
layout->addWidget(check_updates_checkbox_);
+ layout->addWidget(dont_show_wizard_checkbox_);
+ layout->addStretch();
setLayout(layout);
- setVisible(true);
}
auto ConclusionPage::nextId() const -> int { return -1; }
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index 95dbfac9..59a3c9ed 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -37,21 +37,20 @@ namespace GpgFrontend::UI {
FilePage::FilePage(QWidget* parent, const QString& target_path)
: QWidget(parent),
- ui_(GpgFrontend::SecureCreateSharedObject<Ui_FilePage>()),
- file_tree_view_(new FileTreeView(this, target_path)) {
+ ui_(GpgFrontend::SecureCreateSharedObject<Ui_FilePage>()) {
ui_->setupUi(this);
- ui_->trewViewLayout->addWidget(file_tree_view_);
ui_->batchModeButton->setToolTip(tr("Switch Batch Mode"));
- connect(ui_->upPathButton, &QPushButton::clicked, file_tree_view_,
+ connect(ui_->upPathButton, &QPushButton::clicked, ui_->treeView,
&FileTreeView::SlotUpLevel);
connect(ui_->refreshButton, &QPushButton::clicked, this,
&FilePage::SlotGoPath);
- connect(this->ui_->newDirButton, &QPushButton::clicked, file_tree_view_,
+ connect(this->ui_->newDirButton, &QPushButton::clicked, ui_->treeView,
&FileTreeView::SlotMkdir);
- ui_->pathEdit->setText(file_tree_view_->GetCurrentPath());
+ ui_->treeView->SetPath(target_path);
+ ui_->pathEdit->setText(ui_->treeView->GetCurrentPath());
path_edit_completer_ = new QCompleter(this);
path_complete_model_ = new QStringListModel();
@@ -64,13 +63,13 @@ FilePage::FilePage(QWidget* parent, const QString& target_path)
option_popup_menu_ = new QMenu(this);
auto* show_hidden_act = new QAction(tr("Show Hidden File"), this);
show_hidden_act->setCheckable(true);
- connect(show_hidden_act, &QAction::triggered, file_tree_view_,
+ connect(show_hidden_act, &QAction::triggered, ui_->treeView,
&FileTreeView::SlotShowHiddenFile);
option_popup_menu_->addAction(show_hidden_act);
auto* show_system_act = new QAction(tr("Show System File"), this);
show_system_act->setCheckable(true);
- connect(show_system_act, &QAction::triggered, file_tree_view_,
+ connect(show_system_act, &QAction::triggered, ui_->treeView,
&FileTreeView::SlotShowSystemFile);
option_popup_menu_->addAction(show_system_act);
@@ -105,30 +104,30 @@ FilePage::FilePage(QWidget* parent, const QString& target_path)
connect(this, &FilePage::SignalRefreshInfoBoard,
UISignalStation::GetInstance(),
&UISignalStation::SignalRefreshInfoBoard);
- connect(file_tree_view_, &FileTreeView::SignalPathChanged, this,
+ connect(ui_->treeView, &FileTreeView::SignalPathChanged, this,
[this](const QString& path) { this->ui_->pathEdit->setText(path); });
- connect(file_tree_view_, &FileTreeView::SignalPathChanged, this,
+ connect(ui_->treeView, &FileTreeView::SignalPathChanged, this,
&FilePage::SignalPathChanged);
- connect(file_tree_view_, &FileTreeView::SignalOpenFile,
+ connect(ui_->treeView, &FileTreeView::SignalOpenFile,
UISignalStation::GetInstance(),
&UISignalStation::SignalMainWindowOpenFile);
- connect(file_tree_view_, &FileTreeView::SignalSelectedChanged, this,
+ connect(ui_->treeView, &FileTreeView::SignalSelectedChanged, this,
&FilePage::update_main_basic_opera_menu);
connect(this, &FilePage::SignalCurrentTabChanged, this,
[this]() { update_main_basic_opera_menu(GetSelected()); });
connect(this, &FilePage::SignalMainWindowUpdateBasicOperaMenu,
UISignalStation::GetInstance(),
&UISignalStation::SignalMainWindowUpdateBasicOperaMenu);
- connect(ui_->batchModeButton, &QToolButton::toggled, file_tree_view_,
+ connect(ui_->batchModeButton, &QToolButton::toggled, ui_->treeView,
&FileTreeView::SlotSwitchBatchMode);
}
auto FilePage::GetSelected() const -> QStringList {
- return file_tree_view_->GetSelectedPaths();
+ return ui_->treeView->GetSelectedPaths();
}
void FilePage::SlotGoPath() {
- file_tree_view_->SlotGoPath(ui_->pathEdit->text());
+ ui_->treeView->SlotGoPath(ui_->pathEdit->text());
}
void FilePage::keyPressEvent(QKeyEvent* event) {
diff --git a/src/ui/widgets/FilePage.h b/src/ui/widgets/FilePage.h
index fbf99ae9..94b90b0d 100644
--- a/src/ui/widgets/FilePage.h
+++ b/src/ui/widgets/FilePage.h
@@ -29,7 +29,6 @@
#pragma once
#include "ui/GpgFrontendUI.h"
-#include "ui/widgets/FileTreeView.h"
#include "ui/widgets/InfoBoardWidget.h"
class Ui_FilePage;
@@ -126,7 +125,6 @@ class FilePage : public QWidget {
QMenu* popup_menu_{}; ///<
QMenu* option_popup_menu_{}; ///<
- FileTreeView* file_tree_view_;
bool ascii_mode_;
private slots:
diff --git a/src/ui/widgets/FileTreeView.cpp b/src/ui/widgets/FileTreeView.cpp
index 8ebd7274..db628d60 100644
--- a/src/ui/widgets/FileTreeView.cpp
+++ b/src/ui/widgets/FileTreeView.cpp
@@ -35,7 +35,7 @@
namespace GpgFrontend::UI {
-FileTreeView::FileTreeView(QWidget* parent, const QString& target_path)
+FileTreeView::FileTreeView(QWidget* parent)
: QTreeView(parent), dir_model_(new QFileSystemModel(this)) {
dir_model_->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
dir_model_->setRootPath(QDir::homePath());
@@ -58,43 +58,6 @@ FileTreeView::FileTreeView(QWidget* parent, const QString& target_path)
&FileTreeView::slot_adjust_column_widths);
connect(dir_model_, &QFileSystemModel::dataChanged, this,
&FileTreeView::slot_adjust_column_widths);
-
- LOG_D() << "try to open target path:" << target_path;
-
- QFileInfo info(target_path);
- QString effective_path;
-
- if (info.exists()) {
- effective_path =
- info.isFile() ? info.absolutePath() : info.absoluteFilePath();
- } else {
- effective_path = QDir::currentPath();
- }
-
- LOG_D() << "effective path:" << effective_path;
-
- dir_model_->setRootPath(effective_path);
- current_path_ = dir_model_->rootPath();
- QModelIndex root_index = dir_model_->index(current_path_);
-
- if (root_index.isValid()) {
- QPointer<FileTreeView> self(this);
- this->setRootIndex(root_index);
- QTimer::singleShot(200, [=]() {
- if (self != nullptr && info.isFile()) {
- self->setCurrentIndex(dir_model_->index(info.absoluteFilePath()));
- self->expand(currentIndex().parent());
- self->scrollTo(currentIndex(), QAbstractItemView::PositionAtCenter);
- self->selectionModel()->select(
- currentIndex(),
- QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
- }
- });
- } else {
- LOG_W() << "invalid path, fallback to current dir.";
- current_path_ = QDir::currentPath();
- this->setRootIndex(dir_model_->index(current_path_));
- }
}
void FileTreeView::selectionChanged(const QItemSelection& selected,
@@ -446,9 +409,8 @@ void FileTreeView::slot_calculate_hash() {
return;
}
auto result = ExtractParams<QString>(data_object, 0);
- emit UISignalStation::GetInstance()
- -> SignalRefreshInfoBoard(result,
- InfoBoardStatus::INFO_ERROR_OK);
+ emit UISignalStation::GetInstance() -> SignalRefreshInfoBoard(
+ result, InfoBoardStatus::INFO_ERROR_OK);
},
"calculate_file_hash");
});
@@ -481,4 +443,42 @@ void FileTreeView::SlotSwitchBatchMode(bool batch) {
selectionModel()->clearSelection();
}
+void FileTreeView::SetPath(const QString& target_path) {
+ LOG_D() << "try to open target path:" << target_path;
+
+ QFileInfo info(target_path);
+ QString effective_path;
+
+ if (info.exists()) {
+ effective_path =
+ info.isFile() ? info.absolutePath() : info.absoluteFilePath();
+ } else {
+ effective_path = QDir::currentPath();
+ }
+
+ LOG_D() << "effective path:" << effective_path;
+
+ dir_model_->setRootPath(effective_path);
+ current_path_ = dir_model_->rootPath();
+ QModelIndex root_index = dir_model_->index(current_path_);
+
+ if (root_index.isValid()) {
+ QPointer<FileTreeView> self(this);
+ this->setRootIndex(root_index);
+ QTimer::singleShot(200, [=]() {
+ if (self != nullptr && info.isFile()) {
+ self->setCurrentIndex(dir_model_->index(info.absoluteFilePath()));
+ self->expand(currentIndex().parent());
+ self->scrollTo(currentIndex(), QAbstractItemView::PositionAtCenter);
+ self->selectionModel()->select(
+ currentIndex(),
+ QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
+ }
+ });
+ } else {
+ LOG_W() << "invalid path, fallback to current dir.";
+ current_path_ = QDir::currentPath();
+ this->setRootIndex(dir_model_->index(current_path_));
+ }
+}
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/FileTreeView.h b/src/ui/widgets/FileTreeView.h
index 333e06bc..e7ddb607 100644
--- a/src/ui/widgets/FileTreeView.h
+++ b/src/ui/widgets/FileTreeView.h
@@ -41,7 +41,11 @@ class FileTreeView : public QTreeView {
* @param parent
* @param target_path
*/
- explicit FileTreeView(QWidget* parent, const QString& target_path);
+ explicit FileTreeView(QWidget* parent);
+
+ /**
+ */
+ void SetPath(const QString& target_path);
/**
* @brief Get the Current Path object
diff --git a/ui/FilePage.ui b/ui/FilePage.ui
index b9ae7043..97a3ad94 100644
--- a/ui/FilePage.ui
+++ b/ui/FilePage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>858</width>
- <height>64</height>
+ <width>805</width>
+ <height>666</height>
</rect>
</property>
<property name="sizePolicy">
@@ -16,12 +16,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="maximumSize">
- <size>
- <width>1041</width>
- <height>619</height>
- </size>
- </property>
<property name="windowTitle">
<string>Form</string>
</property>
@@ -190,7 +184,11 @@
</layout>
</item>
<item>
- <layout class="QVBoxLayout" name="trewViewLayout"/>
+ <layout class="QVBoxLayout" name="trewViewLayout">
+ <item>
+ <widget class="GpgFrontend::UI::FileTreeView" name="treeView"/>
+ </item>
+ </layout>
</item>
</layout>
</item>
@@ -198,6 +196,13 @@
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>GpgFrontend::UI::FileTreeView</class>
+ <extends>QTreeView</extends>
+ <header>ui/widgets/FileTreeView.h</header>
+ </customwidget>
+ </customwidgets>
<resources>
<include location="../gpgfrontend.qrc"/>
</resources>