From bdad19d9d31c3aa4adee0b929846ded60d616b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AE=E7=94=9F=E8=8B=A5=E6=A2=A6?= <1070753498@qq.com> Date: Wed, 20 Sep 2023 19:00:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-tidy | 57 +-------- .github/workflows/clean_cache.yml | 40 ++++++ .github/workflows/cmake.yml | 51 +++++--- .github/workflows/delete_workflow.yml | 65 ++++++++++ .github/workflows/qmake.yml | 51 +++++--- .github/workflows/readme.yml | 4 +- .github/workflows/toolchain.yml | 77 +++++++++++ 3rdparty/breakpad.cc | 2 +- 3rdparty/breakpad.hpp | 4 +- .../qtsingleapplication/qtsingleapplication.h | 14 +- CMakeLists.txt | 6 +- Qt-Graphics.pro | 2 +- app/app.pro | 2 +- app/main.cpp | 3 +- gpugraphics/CMakeLists.txt | 11 ++ gpugraphics/gpugraphics.pro | 19 +++ gpugraphics/gpugraphics_global.hpp | 9 ++ gpugraphics/openglshaderprogram.cc | 66 ++++++++++ gpugraphics/openglshaderprogram.hpp | 23 ++++ {openglgraphics => gpugraphics}/openglview.cc | 121 ++++++++---------- .../openglview.hpp | 12 +- gpugraphics/shader.qrc | 6 + gpugraphics/shader/texture.frag | 12 ++ .../shader/texture.vert | 7 +- graphics/basicgraphicsitem.cpp | 6 +- graphics/graphicstextitem.hpp | 2 +- graphics/imageview.h | 2 +- mainwindow/CMakeLists.txt | 2 +- mainwindow/drawwidget.cpp | 2 +- mainwindow/imageviewer.cpp | 2 +- mainwindow/mainwindow.pro | 2 +- mainwindow/openglviewer.cc | 14 +- mainwindow/recordgifthread.cc | 6 +- mainwindow/selectionwidget.cc | 2 +- mainwindow/subtitlsplicingwidget.cc | 4 +- mainwindow/viewer.cc | 26 +++- mainwindow/viewer.hpp | 6 +- openglgraphics/CMakeLists.txt | 10 -- openglgraphics/openglgraphics.pro | 17 --- openglgraphics/openglgraphics_global.hpp | 9 -- openglgraphics/shader.qrc | 6 - openglgraphics/shader/texture.fs | 12 -- utils/logasync.cpp | 2 +- utils/utils.cpp | 20 +-- 44 files changed, 531 insertions(+), 285 deletions(-) create mode 100644 .github/workflows/clean_cache.yml create mode 100644 .github/workflows/delete_workflow.yml create mode 100644 .github/workflows/toolchain.yml create mode 100644 gpugraphics/CMakeLists.txt create mode 100644 gpugraphics/gpugraphics.pro create mode 100644 gpugraphics/gpugraphics_global.hpp create mode 100644 gpugraphics/openglshaderprogram.cc create mode 100644 gpugraphics/openglshaderprogram.hpp rename {openglgraphics => gpugraphics}/openglview.cc (64%) rename {openglgraphics => gpugraphics}/openglview.hpp (79%) create mode 100644 gpugraphics/shader.qrc create mode 100644 gpugraphics/shader/texture.frag rename openglgraphics/shader/texture.vs => gpugraphics/shader/texture.vert (75%) delete mode 100644 openglgraphics/CMakeLists.txt delete mode 100644 openglgraphics/openglgraphics.pro delete mode 100644 openglgraphics/openglgraphics_global.hpp delete mode 100644 openglgraphics/shader.qrc delete mode 100644 openglgraphics/shader/texture.fs diff --git a/.clang-tidy b/.clang-tidy index f95ff5f..d3a3536 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,60 +1,7 @@ --- -Checks: '-*,clang-analyzer-*,readability-*,performance-*,modernize-*,bugprone-*,cert-,cppcoreguidelines-,portability-*,llvm-*,google-*' +Checks: 'clang-analyzer-*,readability-*,performance-*,modernize-*,bugprone-*,cert-*,portability-*,llvm-*,google-*' WarningsAsErrors: '' HeaderFilterRegex: '.' AnalyzeTemporaryDtors: false -FormatStyle: file +FormatStyle: none User: user -CheckOptions: - - key: readability-identifier-naming.AbstractClassCase - value: CamelCase - - key: readability-identifier-naming.ClassCase - value: CamelCase - - key: readability-identifier-naming.ClassConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.ClassConstantPrefix - value: 'k' - - key: readability-identifier-naming.ClassMemberCase - value: lower_case - - key: readability-identifier-naming.ClassMemberPrefix - value: 'm_' - - key: readability-identifier-naming.ClassMethodCase - value: camelBack - - key: readability-identifier-naming.ConstexprVariableCase - value: UPPER_CASE - - key: readability-identifier-naming.ConstexprVariablePrefix - value: 'k' - - key: readability-identifier-naming.EnumCase - value: CamelCase - - key: readability-identifier-naming.EnumConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.EnumConstantPrefix - value: '' - - key: readability-identifier-naming.FunctionCase - value: camelBack - - key: readability-identifier-naming.FunctionParameterCase - value: lower_case - - key: readability-identifier-naming.GlobalConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.GlobalConstantPrefix - value: 'k' - - key: readability-identifier-naming.GlobalFunctionCase - value: camelBack - - key: readability-identifier-naming.GlobalVariableCase - value: lower_case - - key: readability-identifier-naming.GlobalVariablePrefix - value: 'g_' - - key: readability-identifier-naming.InlineNamespaceCase - value: lower_case - - key: readability-identifier-naming.LocalConstantCase - value: UPPER_CASE - - key: readability-identifier-naming.LocalConstantPrefix - value: 'k' - - key: readability-identifier-naming.LocalVariableCase - value: lower_case - - key: readability-identifier-naming.MacroDefinitionCase - value: UPPER_CASE - - key: readability-identifier-naming.NamespaceCase - value: lower_case - - key: bugprone-narrowing-conversions.IgnoreFloatingPointPrecisionLoss - value: 'false' diff --git a/.github/workflows/clean_cache.yml b/.github/workflows/clean_cache.yml new file mode 100644 index 0000000..2db7538 --- /dev/null +++ b/.github/workflows/clean_cache.yml @@ -0,0 +1,40 @@ +name: Cleanup caches by a branch +on: + # 每周一 0 点触发 + schedule: + - cron: '0 0 * * 1' + workflow_dispatch: + +jobs: + cleanup: + runs-on: ubuntu-latest + permissions: + # `actions:write` permission is required to delete caches + # See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id + actions: write + contents: read + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH=${{ github.ref }} + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4d142cc..afda2f4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,14 +4,24 @@ on: # push代码时触发workflow push: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - 'doc' + - '.github/workflows/clean_cache.yml' + - '.github/workflows/delete_workflow.yml' + - '.github/workflows/qmake.yml' + - '.github/workflows/readme.yml' + - '.github/workflows/toolchain.yml' + - 'doc/**' - '.clang-format' - '.gitignore' - 'LICENSE' - 'README*' pull_request: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - 'doc' + - '.github/workflows/clean_cache.yml' + - '.github/workflows/delete_workflow.yml' + - '.github/workflows/qmake.yml' + - '.github/workflows/readme.yml' + - '.github/workflows/toolchain.yml' + - 'doc/**' - '.clang-format' - '.gitignore' - 'LICENSE' @@ -29,30 +39,35 @@ jobs: - macos-latest - ubuntu-latest qt_ver: - - 6.5.2 + - 6.6.1 build_type: - "Release" generators: - "Ninja" + libs: + - breakpad giflib steps: - - name: cache vcpkg - uses: actions/cache@v3 - with: - path: | - C:\vcpkg\installed - /usr/local/share/vcpkg/installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}- - ${{ runner.os }}-vcpkg-installed- + - name: Restore windows vcpkg + if: startsWith(matrix.os, 'windows') + uses: actions/cache/restore@v3 + with: + path: C:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + - name: Restore macos or ubuntu vcpkg + if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') + uses: actions/cache/restore@v3 + with: + path: /usr/local/share/vcpkg/installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + - name: Install dependencies on windows if: startsWith(matrix.os, 'windows') run: | choco install ninja ninja --version cmake --version - vcpkg install breakpad giflib --triplet x64-windows + vcpkg install ${{ matrix.libs }} --triplet x64-windows - name: Install dependencies on macos if: startsWith(matrix.os, 'macos') run: | @@ -60,7 +75,7 @@ jobs: ninja --version cmake --version clang --version - vcpkg install breakpad giflib --triplet x64-osx + vcpkg install ${{ matrix.libs }} --triplet x64-osx - name: Install dependencies on ubuntu if: startsWith(matrix.os, 'ubuntu') run: | @@ -68,17 +83,17 @@ jobs: ninja --version cmake --version gcc --version - vcpkg install breakpad giflib --triplet x64-linux + vcpkg install ${{ matrix.libs }} --triplet x64-linux - name: Install Qt uses: jurplel/install-qt-action@v3 with: version: ${{ matrix.qt_ver }} install-deps: 'true' - modules: 'qt5compat addons.qtnetworkauth addons.qtimageformats' + modules: 'qt5compat qtnetworkauth qtimageformats' cache: 'true' - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 diff --git a/.github/workflows/delete_workflow.yml b/.github/workflows/delete_workflow.yml new file mode 100644 index 0000000..ae96aae --- /dev/null +++ b/.github/workflows/delete_workflow.yml @@ -0,0 +1,65 @@ +name: Delete old workflow runs +on: + workflow_dispatch: + inputs: + days: + description: 'Days-worth of runs to keep for each workflow' + required: true + default: '30' + minimum_runs: + description: 'Minimum runs to keep for each workflow' + required: true + default: '6' + delete_workflow_pattern: + description: 'Name or filename of the workflow (if not set, all workflows are targeted)' + required: false + delete_workflow_by_state_pattern: + description: 'Filter workflows by state: active, deleted, disabled_fork, disabled_inactivity, disabled_manually' + required: true + default: "ALL" + type: choice + options: + - "ALL" + - active + - deleted + - disabled_inactivity + - disabled_manually + delete_run_by_conclusion_pattern: + description: 'Remove runs based on conclusion: action_required, cancelled, failure, skipped, success' + required: true + default: "failure" + type: choice + options: + - "ALL" + - "Unsuccessful: action_required,cancelled,failure,skipped" + - action_required + - cancelled + - failure + - skipped + - success + dry_run: + description: 'Logs simulated changes, no deletions are performed' + required: false + +jobs: + del_runs: + runs-on: ubuntu-latest + permissions: + actions: write + steps: + - name: Delete workflow runs + uses: Mattraks/delete-workflow-runs@v2 + with: + token: ${{ github.token }} + repository: ${{ github.repository }} + retain_days: ${{ github.event.inputs.days }} + keep_minimum_runs: ${{ github.event.inputs.minimum_runs }} + delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }} + delete_workflow_by_state_pattern: ${{ github.event.inputs.delete_workflow_by_state_pattern }} + delete_run_by_conclusion_pattern: >- + ${{ + startsWith(github.event.inputs.delete_run_by_conclusion_pattern, 'Unsuccessful:') + && 'action_required,cancelled,failure,skipped' + || github.event.inputs.delete_run_by_conclusion_pattern + }} + dry_run: ${{ github.event.inputs.dry_run }} diff --git a/.github/workflows/qmake.yml b/.github/workflows/qmake.yml index 97e87e9..9a4baf4 100644 --- a/.github/workflows/qmake.yml +++ b/.github/workflows/qmake.yml @@ -4,14 +4,24 @@ on: # push代码时触发workflow push: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - 'doc' + - '.github/workflows/clean_cache.yml' + - '.github/workflows/delete_workflow.yml' + - '.github/workflows/cmake.yml' + - '.github/workflows/readme.yml' + - '.github/workflows/toolchain.yml' + - 'doc/**' - '.clang-format' - '.gitignore' - 'LICENSE' - 'README*' pull_request: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - 'doc' + - '.github/workflows/clean_cache.yml' + - '.github/workflows/delete_workflow.yml' + - '.github/workflows/cmake.yml' + - '.github/workflows/readme.yml' + - '.github/workflows/toolchain.yml' + - 'doc/**' - '.clang-format' - '.gitignore' - 'LICENSE' @@ -29,26 +39,31 @@ jobs: - macos-latest - ubuntu-latest qt_ver: - - 6.5.2 + - 6.6.1 + libs: + - breakpad giflib steps: - - name: cache vcpkg - uses: actions/cache@v3 - with: - path: | - C:\vcpkg\installed - /usr/local/share/vcpkg/installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}- - ${{ runner.os }}-vcpkg-installed- + - name: Restore windows vcpkg + if: startsWith(matrix.os, 'windows') + uses: actions/cache/restore@v3 + with: + path: C:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + - name: Restore macos or ubuntu vcpkg + if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') + uses: actions/cache/restore@v3 + with: + path: /usr/local/share/vcpkg/installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + - name: Install dependencies on windows if: startsWith(matrix.os, 'windows') run: | choco install ninja ninja --version cmake --version - vcpkg install breakpad giflib --triplet x64-windows + vcpkg install ${{ matrix.libs }} --triplet x64-windows - name: Install dependencies on macos if: startsWith(matrix.os, 'macos') run: | @@ -56,7 +71,7 @@ jobs: ninja --version cmake --version clang --version - vcpkg install breakpad giflib --triplet x64-osx + vcpkg install ${{ matrix.libs }} --triplet x64-osx - name: Install dependencies on ubuntu if: startsWith(matrix.os, 'ubuntu') run: | @@ -64,17 +79,17 @@ jobs: ninja --version cmake --version gcc --version - vcpkg install breakpad giflib --triplet x64-linux + vcpkg install ${{ matrix.libs }} --triplet x64-linux - name: Install Qt uses: jurplel/install-qt-action@v3 with: version: ${{ matrix.qt_ver }} install-deps: 'true' - modules: 'qt5compat addons.qtnetworkauth addons.qtimageformats' + modules: 'qt5compat qtnetworkauth qtimageformats' cache: 'true' - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml index 0cf4fb1..aff09d7 100644 --- a/.github/workflows/readme.yml +++ b/.github/workflows/readme.yml @@ -12,9 +12,9 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: node-version: 12.x # ISO Langusge Codes: https://cloud.google.com/translate/docs/languages diff --git a/.github/workflows/toolchain.yml b/.github/workflows/toolchain.yml new file mode 100644 index 0000000..3687fe3 --- /dev/null +++ b/.github/workflows/toolchain.yml @@ -0,0 +1,77 @@ +name: Build toolchain + +on: + # 清理 Cache 后触发 + workflow_run: + workflows: [Cleanup caches by a branch] + types: completed + # 手动触发 + workflow_dispatch: + +jobs: + build: + name: Build + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - windows-latest + - windows-2019 + - macos-latest + - ubuntu-latest + qt_ver: + - 6.6.1 + libs: + - breakpad giflib + + steps: + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: ${{ matrix.qt_ver }} + install-deps: 'true' + modules: 'qt5compat qtnetworkauth qtimageformats' + cache: 'true' + + - name: Install dependencies on windows + if: startsWith(matrix.os, 'windows') + shell: bash + run: | + choco install ninja + ninja --version + cmake --version + vcpkg install ${{ matrix.libs }} --triplet x64-windows + - name: Install dependencies on macos + if: startsWith(matrix.os, 'macos') + shell: bash + run: | + brew install ninja nasm pkg-config + ninja --version + cmake --version + clang --version + vcpkg install ${{ matrix.libs }} --triplet x64-osx + - name: Install dependencies on ubuntu + if: startsWith(matrix.os, 'ubuntu') + shell: bash + run: | + sudo apt-get update + sudo apt-get install ninja-build nasm build-essential libgl1-mesa-dev + ninja --version + cmake --version + gcc --version + vcpkg install ${{ matrix.libs }} --triplet x64-linux + + - name: cache windows vcpkg + if: startsWith(matrix.os, 'windows') + uses: actions/cache/save@v3 + with: + path: C:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + - name: cache macos or ubuntu vcpkg + if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') + uses: actions/cache/save@v3 + with: + path: /usr/local/share/vcpkg/installed + key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + diff --git a/3rdparty/breakpad.cc b/3rdparty/breakpad.cc index 1f0eb40..e463e92 100644 --- a/3rdparty/breakpad.cc +++ b/3rdparty/breakpad.cc @@ -38,7 +38,7 @@ void createEnvironment() if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { auto systemEnviroment = QProcess::systemEnvironment(); QString str; - for (const QString &info : qAsConst(systemEnviroment)) { + for (const QString &info : std::as_const(systemEnviroment)) { str += info; str += '\n'; } diff --git a/3rdparty/breakpad.hpp b/3rdparty/breakpad.hpp index 251f667..297f5c8 100644 --- a/3rdparty/breakpad.hpp +++ b/3rdparty/breakpad.hpp @@ -11,14 +11,14 @@ class THRIDPARTY_EXPORT BreakPad : public QObject { Q_OBJECT public: - static BreakPad *instance(); + static auto instance() -> BreakPad *; signals: void crash(); private: explicit BreakPad(QObject *parent = nullptr); - ~BreakPad(); + ~BreakPad() override; struct BreakPadPrivate; QScopedPointer d_ptr; diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.h b/3rdparty/qtsingleapplication/qtsingleapplication.h index b2320ca..858fd19 100644 --- a/3rdparty/qtsingleapplication/qtsingleapplication.h +++ b/3rdparty/qtsingleapplication/qtsingleapplication.h @@ -39,18 +39,18 @@ class THRIDPARTY_EXPORT QtSingleApplication : public QApplication public: QtSingleApplication(const QString &id, int &argc, char **argv); - ~QtSingleApplication(); + ~QtSingleApplication() override; - bool isRunning(qint64 pid = -1); + auto isRunning(qint64 pid = -1) -> bool; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); - QWidget* activationWindow() const; - bool event(QEvent *event) override; + [[nodiscard]] auto activationWindow() const -> QWidget*; + auto event(QEvent *event) -> bool override; - QString applicationId() const; + [[nodiscard]] auto applicationId() const -> QString; void setBlock(bool value); - bool sendMessage(const QString &message, int timeout = 5000, qint64 pid = -1); + auto sendMessage(const QString &message, int timeout = 5000, qint64 pid = -1) -> bool; void activateWindow(); Q_SIGNALS: @@ -58,7 +58,7 @@ class THRIDPARTY_EXPORT QtSingleApplication : public QApplication void fileOpenRequest(const QString &file); private: - QString instancesFileName(const QString &appId); + auto instancesFileName(const QString &appId) -> QString; qint64 firstPeer; QSharedMemory *instances; diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e59ac6..0fcae80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,11 +18,11 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(utils) if(CMAKE_HOST_WIN32) - list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.5.2\\msvc2019_64") + list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.6.1\\msvc2019_64") elseif(CMAKE_HOST_APPLE) elseif(CMAKE_HOST_UNIX) - list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.5.2/gcc_64") + list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.6.1/gcc_64") endif() project( @@ -87,7 +87,7 @@ endif() add_subdirectory(utils) add_subdirectory(3rdparty) +add_subdirectory(gpugraphics) add_subdirectory(graphics) -add_subdirectory(openglgraphics) add_subdirectory(mainwindow) add_subdirectory(app) diff --git a/Qt-Graphics.pro b/Qt-Graphics.pro index 4d69405..3133987 100644 --- a/Qt-Graphics.pro +++ b/Qt-Graphics.pro @@ -4,8 +4,8 @@ CONFIG += ordered SUBDIRS += \ utils\ 3rdparty \ + gpugraphics \ graphics \ - openglgraphics \ mainwindow \ app diff --git a/app/app.pro b/app/app.pro index 8ecbdb1..d14e58a 100644 --- a/app/app.pro +++ b/app/app.pro @@ -14,7 +14,7 @@ LIBS += -L$$APP_OUTPUT_PATH/../libs LIBS += \ -l$$replaceLibName(mainwindow) \ - -l$$replaceLibName(openglgraphics) \ + -l$$replaceLibName(gpugraphics) \ -l$$replaceLibName(graphics) \ -l$$replaceLibName(thirdparty) \ -l$$replaceLibName(utils) diff --git a/app/main.cpp b/app/main.cpp index 7274cb8..70d9bb3 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -24,8 +24,9 @@ void setAppInfo() auto main(int argc, char *argv[]) -> int { #if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - if (!qEnvironmentVariableIsSet("QT_OPENGL")) + if (!qEnvironmentVariableIsSet("QT_OPENGL")) { QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); + } #else qputenv("QSG_RHI_BACKEND", "opengl"); #endif diff --git a/gpugraphics/CMakeLists.txt b/gpugraphics/CMakeLists.txt new file mode 100644 index 0000000..ed643b3 --- /dev/null +++ b/gpugraphics/CMakeLists.txt @@ -0,0 +1,11 @@ +set(PROJECT_SOURCES gpugraphics_global.hpp openglshaderprogram.cc + openglshaderprogram.hpp openglview.cc openglview.hpp) + +qt_add_resources(SOURCES shader.qrc) + +add_custom_library(gpugraphics ${PROJECT_SOURCES} ${SOURCES}) +target_link_libraries(gpugraphics PRIVATE Qt6::Widgets Qt6::OpenGLWidgets) + +if(CMAKE_HOST_WIN32) + target_compile_definitions(gpugraphics PRIVATE "GPUGRAPHICS_LIBRARY") +endif() diff --git a/gpugraphics/gpugraphics.pro b/gpugraphics/gpugraphics.pro new file mode 100644 index 0000000..f77d9cc --- /dev/null +++ b/gpugraphics/gpugraphics.pro @@ -0,0 +1,19 @@ +include(../libs.pri) + +QT += widgets openglwidgets + +DEFINES += GPUGRAPHICS_LIBRARY +TARGET = $$replaceLibName(gpugraphics) + +HEADERS += \ + gpugraphics_global.hpp \ + openglshaderprogram.hpp \ + openglview.hpp + +SOURCES += \ + openglshaderprogram.cc \ + openglview.cc + +RESOURCES += \ + shader.qrc + diff --git a/gpugraphics/gpugraphics_global.hpp b/gpugraphics/gpugraphics_global.hpp new file mode 100644 index 0000000..6db92f8 --- /dev/null +++ b/gpugraphics/gpugraphics_global.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +#if defined(GPUGRAPHICS_LIBRARY) +#define GPUAPHICS Q_DECL_EXPORT +#else +#define GPUAPHICS Q_DECL_IMPORT +#endif diff --git a/gpugraphics/openglshaderprogram.cc b/gpugraphics/openglshaderprogram.cc new file mode 100644 index 0000000..64f58eb --- /dev/null +++ b/gpugraphics/openglshaderprogram.cc @@ -0,0 +1,66 @@ +#include "openglshaderprogram.hpp" + +#include + +namespace GpuGraphics { + +class OpenGLShaderProgram::OpenGLShaderProgramPrivate +{ +public: + explicit OpenGLShaderProgramPrivate(OpenGLShaderProgram *q) + : q_ptr(q) + {} + + OpenGLShaderProgram *q_ptr; + + QOpenGLBuffer vbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); + QOpenGLBuffer ebo = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); +}; + +OpenGLShaderProgram::OpenGLShaderProgram(QObject *parent) + : QOpenGLShaderProgram(parent) + , d_ptr(new OpenGLShaderProgramPrivate(this)) +{} + +OpenGLShaderProgram::~OpenGLShaderProgram() +{ + clear(); +} + +void OpenGLShaderProgram::initVertex(const QString &pos, const QString &texCord) +{ + auto posAttr = attributeLocation(pos); + auto texCordAttr = attributeLocation(texCord); + + float vertices[] = { + // positions // texture coords + 1.0F, 1.0F, 0.0F, 1.0F, 1.0F, // top right + 1.0F, -1.0F, 0.0F, 1.0F, 0.0F, // bottom right + -1.0F, -1.0F, 0.0F, 0.0F, 0.0F, // bottom left + -1.0F, 1.0F, 0.0F, 0.0F, 1.0F // top left + }; + unsigned int indices[] = {0, 1, 3, 1, 2, 3}; + + d_ptr->vbo.destroy(); + d_ptr->vbo.create(); + d_ptr->vbo.bind(); + d_ptr->vbo.allocate(vertices, sizeof(vertices)); + + d_ptr->ebo.destroy(); + d_ptr->ebo.create(); + d_ptr->ebo.bind(); + d_ptr->ebo.allocate(indices, sizeof(indices)); + + setAttributeBuffer(posAttr, GL_FLOAT, 0, 3, sizeof(float) * 5); + enableAttributeArray(posAttr); + setAttributeBuffer(texCordAttr, GL_FLOAT, 3 * sizeof(float), 2, sizeof(float) * 5); + enableAttributeArray(texCordAttr); +} + +void OpenGLShaderProgram::clear() +{ + d_ptr->vbo.destroy(); + d_ptr->ebo.destroy(); +} + +} // namespace GpuGraphics diff --git a/gpugraphics/openglshaderprogram.hpp b/gpugraphics/openglshaderprogram.hpp new file mode 100644 index 0000000..3dc9581 --- /dev/null +++ b/gpugraphics/openglshaderprogram.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace GpuGraphics { + +class OpenGLShaderProgram : public QOpenGLShaderProgram, public QOpenGLFunctions +{ +public: + explicit OpenGLShaderProgram(QObject *parent = nullptr); + ~OpenGLShaderProgram() override; + + void initVertex(const QString &pos, const QString &texCord); + + void clear(); + +private: + class OpenGLShaderProgramPrivate; + QScopedPointer d_ptr; +}; + +} // namespace GpuGraphics diff --git a/openglgraphics/openglview.cc b/gpugraphics/openglview.cc similarity index 64% rename from openglgraphics/openglview.cc rename to gpugraphics/openglview.cc index 1db7619..1ad7550 100644 --- a/openglgraphics/openglview.cc +++ b/gpugraphics/openglview.cc @@ -1,31 +1,29 @@ #include "openglview.hpp" +#include "openglshaderprogram.hpp" #include -#include #include -namespace OpenglGraphics { +namespace GpuGraphics { class OpenglView::OpenglViewPrivate { public: - OpenglViewPrivate(OpenglView *q) + explicit OpenglViewPrivate(OpenglView *q) : q_ptr(q) { transform.setToIdentity(); menu = new QMenu(q_ptr); } - ~OpenglViewPrivate() {} + + ~OpenglViewPrivate() = default; OpenglView *q_ptr; - QScopedPointer programPtr; + QScopedPointer programPtr; GLuint texture; - QOpenGLBuffer vbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); - QOpenGLBuffer ebo = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); QImage image; - bool isImageChanged = false; QColor backgroundColor = Qt::white; QMatrix4x4 transform; @@ -51,8 +49,6 @@ OpenglView::~OpenglView() } makeCurrent(); d_ptr->programPtr.reset(); - d_ptr->vbo.destroy(); - d_ptr->ebo.destroy(); glDeleteTextures(1, &d_ptr->texture); doneCurrent(); } @@ -64,8 +60,6 @@ void OpenglView::setImageUrl(const QString &imageUrl) return; } - d_ptr->isImageChanged = true; - d_ptr->image = image.convertedTo(QImage::Format_RGBA8888_Premultiplied); auto size = d_ptr->image.size(); if (size.width() > width() || size.height() > height()) { @@ -74,6 +68,8 @@ void OpenglView::setImageUrl(const QString &imageUrl) resetToOriginalSize(); } + uploadTexture(); + emit imageUrlChanged(imageUrl); emit imageSizeChanged(size); } @@ -85,13 +81,14 @@ void OpenglView::resetToOriginalSize() } auto size = d_ptr->image.size(); - auto factor_w = qreal(size.width()) / width(); - auto factor_h = qreal(size.height()) / height(); + auto factor_w = static_cast(size.width()) / width(); + auto factor_h = static_cast(size.height()) / height(); d_ptr->transform.setToIdentity(); d_ptr->transform.scale(factor_w, factor_h, 1.0); emit emitScaleFactor(); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::fitToScreen() @@ -101,28 +98,31 @@ void OpenglView::fitToScreen() } auto size = d_ptr->image.size(); - auto factor_w = width() / qreal(size.width()); - auto factor_h = height() / qreal(size.height()); + auto factor_w = static_cast(width()) / size.width(); + auto factor_h = static_cast(height()) / size.height(); auto factor = qMin(factor_w, factor_h); d_ptr->transform.setToIdentity(); d_ptr->transform.scale(factor / factor_w, factor / factor_h, 1.0); emit emitScaleFactor(); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::rotateNinetieth() { d_ptr->transform.rotate(90, 0, 0, 1); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::anti_rotateNinetieth() { d_ptr->transform.rotate(-90, 0, 0, 1); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::initializeGL() @@ -135,13 +135,13 @@ void OpenglView::initializeGL() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - d_ptr->programPtr.reset(new QOpenGLShaderProgram(this)); - d_ptr->programPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/texture.vs"); - d_ptr->programPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/texture.fs"); + d_ptr->programPtr.reset(new OpenGLShaderProgram(this)); + d_ptr->programPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/texture.vert"); + d_ptr->programPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/texture.frag"); d_ptr->programPtr->link(); d_ptr->programPtr->bind(); - initVbo(); + d_ptr->programPtr->initVertex("aPos", "aTexCord"); initTexture(); d_ptr->programPtr->release(); @@ -153,15 +153,16 @@ void OpenglView::resizeGL(int w, int h) glViewport(0, 0, w * ratioF, w * ratioF); if (d_ptr->windowSize.isValid()) { - auto factor_w = d_ptr->windowSize.width() / qreal(w); - auto factor_h = d_ptr->windowSize.height() / qreal(h); + auto factor_w = static_cast(d_ptr->windowSize.width()) / w; + auto factor_h = static_cast(d_ptr->windowSize.height()) / h; d_ptr->transform.scale(factor_w, factor_h, 1.0); //qDebug() << "resizeGL" << factor_w << factor_h; emit emitScaleFactor(); } d_ptr->windowSize = QSize(w, h); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::paintGL() @@ -176,19 +177,6 @@ void OpenglView::paintGL() glActiveTexture(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, d_ptr->texture); - if (d_ptr->isImageChanged) { - d_ptr->isImageChanged = false; - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA, - d_ptr->image.width(), - d_ptr->image.height(), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - d_ptr->image.bits()); - glGenerateMipmap(GL_TEXTURE_2D); - } d_ptr->programPtr->setUniformValue("transform", d_ptr->transform); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); @@ -207,7 +195,8 @@ void OpenglView::wheelEvent(QWheelEvent *event) d_ptr->transform.scale(factor, factor, 1.0); emit emitScaleFactor(); - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, [this] { update(); }, Qt::QueuedConnection); } void OpenglView::mouseDoubleClickEvent(QMouseEvent *event) @@ -221,35 +210,6 @@ void OpenglView::contextMenuEvent(QContextMenuEvent *event) d_ptr->menu->exec(event->globalPos()); } -void OpenglView::initVbo() -{ - GLuint posAttr = GLuint(d_ptr->programPtr->attributeLocation("aPos")); - GLuint texCord = GLuint(d_ptr->programPtr->attributeLocation("aTexCord")); - float vertices[] = { - // positions // texture coords - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left - }; - unsigned int indices[] = {0, 1, 3, 1, 2, 3}; - - d_ptr->vbo.destroy(); - d_ptr->vbo.create(); - d_ptr->vbo.bind(); - d_ptr->vbo.allocate(vertices, sizeof(vertices)); - - d_ptr->ebo.destroy(); - d_ptr->ebo.create(); - d_ptr->ebo.bind(); - d_ptr->ebo.allocate(indices, sizeof(indices)); - - d_ptr->programPtr->setAttributeBuffer(posAttr, GL_FLOAT, 0, 3, sizeof(float) * 5); - d_ptr->programPtr->enableAttributeArray(posAttr); - d_ptr->programPtr->setAttributeBuffer(texCord, GL_FLOAT, 3 * sizeof(float), 2, sizeof(float) * 5); - d_ptr->programPtr->enableAttributeArray(texCord); -} - void OpenglView::initTexture() { glGenTextures(1, &d_ptr->texture); @@ -260,6 +220,25 @@ void OpenglView::initTexture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } +void OpenglView::uploadTexture() +{ + makeCurrent(); + d_ptr->programPtr->bind(); + glBindTexture(GL_TEXTURE_2D, d_ptr->texture); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + d_ptr->image.width(), + d_ptr->image.height(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + d_ptr->image.bits()); + glGenerateMipmap(GL_TEXTURE_2D); + d_ptr->programPtr->release(); + doneCurrent(); +} + void OpenglView::clear() { glClearColor(d_ptr->backgroundColor.redF(), @@ -285,4 +264,4 @@ void OpenglView::emitScaleFactor() emit scaleFactorChanged(factor); } -} // namespace OpenglGraphics +} // namespace GpuGraphics diff --git a/openglgraphics/openglview.hpp b/gpugraphics/openglview.hpp similarity index 79% rename from openglgraphics/openglview.hpp rename to gpugraphics/openglview.hpp index 19eff0f..229540d 100644 --- a/openglgraphics/openglview.hpp +++ b/gpugraphics/openglview.hpp @@ -1,19 +1,19 @@ #pragma once -#include "openglgraphics_global.hpp" +#include "gpugraphics_global.hpp" #include #include #include -namespace OpenglGraphics { +namespace GpuGraphics { -class OPENGLGRAPHICS OpenglView : public QOpenGLWidget, protected QOpenGLFunctions +class GPUAPHICS OpenglView : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: - OpenglView(QWidget *parent = nullptr); + explicit OpenglView(QWidget *parent = nullptr); ~OpenglView() override; public slots: @@ -41,8 +41,8 @@ public slots: void contextMenuEvent(QContextMenuEvent *event) override; private: - void initVbo(); void initTexture(); + void uploadTexture(); void clear(); void createPopMenu(); void emitScaleFactor(); @@ -51,4 +51,4 @@ public slots: QScopedPointer d_ptr; }; -} // namespace OpenglGraphics +} // namespace GpuGraphics diff --git a/gpugraphics/shader.qrc b/gpugraphics/shader.qrc new file mode 100644 index 0000000..f3557cf --- /dev/null +++ b/gpugraphics/shader.qrc @@ -0,0 +1,6 @@ + + + shader/texture.frag + shader/texture.vert + + diff --git a/gpugraphics/shader/texture.frag b/gpugraphics/shader/texture.frag new file mode 100644 index 0000000..7105db3 --- /dev/null +++ b/gpugraphics/shader/texture.frag @@ -0,0 +1,12 @@ +#version 450 + +layout(binding = 0) uniform sampler2D tex; // 纹理 + +layout(location = 0) in vec2 TexCord; // 纹理坐标 + +layout(location = 0) out vec4 FragColor; // 输出颜色 + +void main() +{ + FragColor = texture(tex, TexCord); +} diff --git a/openglgraphics/shader/texture.vs b/gpugraphics/shader/texture.vert similarity index 75% rename from openglgraphics/shader/texture.vs rename to gpugraphics/shader/texture.vert index 78d847d..1de42f2 100644 --- a/openglgraphics/shader/texture.vs +++ b/gpugraphics/shader/texture.vert @@ -1,10 +1,11 @@ -#version 330 core +#version 450 + +uniform mat4 transform; layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCord; -out vec2 TexCord; // 纹理坐标 -uniform mat4 transform; +layout(location = 0) out vec2 TexCord; // 纹理坐标 void main() { diff --git a/graphics/basicgraphicsitem.cpp b/graphics/basicgraphicsitem.cpp index 9307fc2..ecc765e 100644 --- a/graphics/basicgraphicsitem.cpp +++ b/graphics/basicgraphicsitem.cpp @@ -14,7 +14,7 @@ namespace Graphics { class BasicGraphicsItem::BasicGraphicsItemPrivate { public: - BasicGraphicsItemPrivate(QObject *parent) + explicit BasicGraphicsItemPrivate(QObject *parent) : owner(parent) {} @@ -117,7 +117,7 @@ void BasicGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) setCursor(Qt::SizeAllCursor); } - for (const QPointF &p : qAsConst(d_ptr->cache)) { + for (const QPointF &p : std::as_const(d_ptr->cache)) { QPointF m(margin() / 2, margin() / 2); QRectF area(p - m, p + m); if (area.contains(pos)) { @@ -178,7 +178,7 @@ void BasicGraphicsItem::drawAnchor(QPainter *painter) } QPolygonF polygonF = cache(); - for (const QPointF &p : qAsConst(polygonF)) { + for (const QPointF &p : std::as_const(polygonF)) { painter->fillRect(QRectF(p.x() - d_ptr->margin / 2, p.y() - d_ptr->margin / 2, d_ptr->margin, diff --git a/graphics/graphicstextitem.hpp b/graphics/graphicstextitem.hpp index 3d7d9ba..445251b 100644 --- a/graphics/graphicstextitem.hpp +++ b/graphics/graphicstextitem.hpp @@ -13,7 +13,7 @@ class GRAPHICS_EXPORT GraphicsTextItem : public QGraphicsTextItem public: enum { Type = UserType + 3 }; - GraphicsTextItem(QGraphicsItem *parent = nullptr); + explicit GraphicsTextItem(QGraphicsItem *parent = nullptr); [[nodiscard]] auto type() const -> int override { return Type; } diff --git a/graphics/imageview.h b/graphics/imageview.h index d6feb72..0f977f0 100644 --- a/graphics/imageview.h +++ b/graphics/imageview.h @@ -13,7 +13,7 @@ class GRAPHICS_EXPORT ImageView : public QGraphicsView Q_OBJECT public: explicit ImageView(QWidget *parent = nullptr); - ImageView(QGraphicsScene *scene, QWidget *parent = nullptr); + explicit ImageView(QGraphicsScene *scene, QWidget *parent = nullptr); ~ImageView() override; [[nodiscard]] auto pixmap() const -> QPixmap; diff --git a/mainwindow/CMakeLists.txt b/mainwindow/CMakeLists.txt index 9beb06d..5045f56 100644 --- a/mainwindow/CMakeLists.txt +++ b/mainwindow/CMakeLists.txt @@ -49,7 +49,7 @@ target_link_libraries( Qt6::OpenGLWidgets utils graphics - openglgraphics + gpugraphics egif) if(CMAKE_HOST_WIN32) diff --git a/mainwindow/drawwidget.cpp b/mainwindow/drawwidget.cpp index 030b95c..adfca17 100644 --- a/mainwindow/drawwidget.cpp +++ b/mainwindow/drawwidget.cpp @@ -237,7 +237,7 @@ void DrawWidget::buildConnect() connect(d_ptr->drawScene, &DrawScene::itemSelected, this, &DrawWidget::itemSelected); new QShortcut(QKeySequence::SelectAll, this, this, [this] { auto items = d_ptr->drawScene->items(); - for (auto item : qAsConst(items)) { + for (auto item : std::as_const(items)) { item->setSelected(true); } }); diff --git a/mainwindow/imageviewer.cpp b/mainwindow/imageviewer.cpp index d11006d..0e5d8ce 100644 --- a/mainwindow/imageviewer.cpp +++ b/mainwindow/imageviewer.cpp @@ -138,7 +138,7 @@ void ImageViewer::onImageChanged(const QString &url) d_ptr->urlLabel->setText(url); d_ptr->fileSizeLabel->setText(Utils::convertBytesToString(QFile(url).size())); - for (const ImageInfo &image : qAsConst(d_ptr->imageInfoList)) { + for (const ImageInfo &image : std::as_const(d_ptr->imageInfoList)) { if (image.fileInfo().absoluteFilePath() == url) { return; } diff --git a/mainwindow/mainwindow.pro b/mainwindow/mainwindow.pro index 2487f02..7bb3843 100644 --- a/mainwindow/mainwindow.pro +++ b/mainwindow/mainwindow.pro @@ -10,7 +10,7 @@ LIBS += \ -l$$replaceLibName(utils) \ -l$$replaceLibName(thirdparty) \ -l$$replaceLibName(graphics) \ - -l$$replaceLibName(openglgraphics) + -l$$replaceLibName(gpugraphics) DEFINES += QT_DEPRECATED_WARNINGS diff --git a/mainwindow/openglviewer.cc b/mainwindow/openglviewer.cc index 6b37da4..89698a4 100644 --- a/mainwindow/openglviewer.cc +++ b/mainwindow/openglviewer.cc @@ -1,7 +1,7 @@ #include "openglviewer.hpp" #include "imagelistmodel.h" -#include +#include #include #include @@ -12,7 +12,7 @@ class OpenglViewer::OpenglViewerPrivate OpenglViewerPrivate(OpenglViewer *q) : q_ptr(q) { - openglView = new OpenglGraphics::OpenglView(q_ptr); + openglView = new GpuGraphics::OpenglView(q_ptr); urlLabel = new QLabel("-", q_ptr); urlLabel->setWordWrap(true); @@ -26,7 +26,7 @@ class OpenglViewer::OpenglViewerPrivate OpenglViewer *q_ptr; - OpenglGraphics::OpenglView *openglView; + GpuGraphics::OpenglView *openglView; QLabel *urlLabel; QLabel *fileSizeLabel; @@ -99,7 +99,7 @@ void OpenglViewer::onImageChanged(const QString &url) d_ptr->urlLabel->setText(url); d_ptr->fileSizeLabel->setText(Utils::convertBytesToString(QFile(url).size())); - for (const ImageInfo &image : qAsConst(d_ptr->imageInfoList)) { + for (const ImageInfo &image : std::as_const(d_ptr->imageInfoList)) { if (image.fileInfo().absoluteFilePath() == url) { return; } @@ -186,15 +186,15 @@ QWidget *OpenglViewer::toolWidget() void OpenglViewer::buildConnect() { connect(d_ptr->openglView, - &OpenglGraphics::OpenglView::scaleFactorChanged, + &GpuGraphics::OpenglView::scaleFactorChanged, this, &OpenglViewer::onScaleFactorChanged); connect(d_ptr->openglView, - &OpenglGraphics::OpenglView::imageSizeChanged, + &GpuGraphics::OpenglView::imageSizeChanged, this, &OpenglViewer::onImageSizeChanged); connect(d_ptr->openglView, - &OpenglGraphics::OpenglView::imageUrlChanged, + &GpuGraphics::OpenglView::imageUrlChanged, this, &OpenglViewer::onImageChanged); connect(d_ptr->imageListView, &ImageListView::changeItem, this, &OpenglViewer::onChangedImage); diff --git a/mainwindow/recordgifthread.cc b/mainwindow/recordgifthread.cc index ef001eb..72013eb 100644 --- a/mainwindow/recordgifthread.cc +++ b/mainwindow/recordgifthread.cc @@ -177,7 +177,7 @@ void RecordGifThread::encode1(const QVector &images) { /// [1] QScopedPointer gifEncoderPtr(createGifEncoder()); - for (const auto &image : qAsConst(images)) { + for (const auto &image : std::as_const(images)) { ///[2] push(gifEncoderPtr.data(), image); } @@ -191,7 +191,7 @@ void RecordGifThread::encode2(const QVector &images) { /// [1] QScopedPointer gifWriterPtr(createGifWriter()); - for (const auto &image : qAsConst(images)) { + for (const auto &image : std::as_const(images)) { ///[2] push(gifWriterPtr.data(), image); } @@ -270,7 +270,7 @@ void RecordGifThread::encode2() /// [1] QScopedPointer gifEncoderPtr(createGifEncoder()); QScopedPointer gifWriterPtr(createGifWriter()); - for (const auto &path : qAsConst(imagePaths)) { + for (const auto &path : std::as_const(imagePaths)) { QImage image(path); if (image.isNull()) { continue; diff --git a/mainwindow/selectionwidget.cc b/mainwindow/selectionwidget.cc index c49bd1c..52cd3de 100644 --- a/mainwindow/selectionwidget.cc +++ b/mainwindow/selectionwidget.cc @@ -309,7 +309,7 @@ void SelectionWidget::paintEvent(QPaintEvent *event) p.setRenderHint(QPainter::Antialiasing); p.setBrush(m_color); auto areas = handlerAreas(); - for (const auto &rect : qAsConst(areas)) { + for (const auto &rect : std::as_const(areas)) { p.drawEllipse(rect); } } diff --git a/mainwindow/subtitlsplicingwidget.cc b/mainwindow/subtitlsplicingwidget.cc index fe5e501..0936cf2 100644 --- a/mainwindow/subtitlsplicingwidget.cc +++ b/mainwindow/subtitlsplicingwidget.cc @@ -18,7 +18,7 @@ class GenerateTask : public QRunnable void run() override { QImage image; - for (const auto &info : qAsConst(m_infos)) { + for (const auto &info : std::as_const(m_infos)) { auto i = QImage(info.imagePath); if (image.isNull()) { auto clipRect = QRect(QPoint(0, 0), info.imageRect.bottomRight()); @@ -101,7 +101,7 @@ void SubtitlSplicingWidget::onOpenImage() } d_ptr->listWidget->clear(); - for (const auto &path : qAsConst(paths)) { + for (const auto &path : std::as_const(paths)) { auto item = new QListWidgetItem; item->setSizeHint(QSize(1, 300)); auto view = new SectionalSubtitlesView(this); diff --git a/mainwindow/viewer.cc b/mainwindow/viewer.cc index 65aa55b..fedf972 100644 --- a/mainwindow/viewer.cc +++ b/mainwindow/viewer.cc @@ -3,17 +3,21 @@ #include #include +#include Viewer::Viewer(QWidget *parent) : QWidget(parent) {} -Viewer::~Viewer() {} +Viewer::~Viewer() +{ + ImageLoadRunnable::terminateAll(); +} class ImageLoadRunnable::ImageLoadRunnablePrivate { public: - ImageLoadRunnablePrivate(ImageLoadRunnable *q) + explicit ImageLoadRunnablePrivate(ImageLoadRunnable *q) : q_ptr(q) {} @@ -22,8 +26,12 @@ class ImageLoadRunnable::ImageLoadRunnablePrivate QPointer viewPtr; QString fileUrl; qint64 taskCount; + + static std::atomic_bool running; }; +std::atomic_bool ImageLoadRunnable::ImageLoadRunnablePrivate::running = true; + ImageLoadRunnable::ImageLoadRunnable(const QString &fileUrl, Viewer *view, qint64 taskCount) : d_ptr(new ImageLoadRunnablePrivate(this)) { @@ -34,13 +42,21 @@ ImageLoadRunnable::ImageLoadRunnable(const QString &fileUrl, Viewer *view, qint6 setAutoDelete(true); } -ImageLoadRunnable::~ImageLoadRunnable() {} +ImageLoadRunnable::~ImageLoadRunnable() = default; + +void ImageLoadRunnable::terminateAll() +{ + ImageLoadRunnablePrivate::running.store(false); + auto *instance = QThreadPool::globalInstance(); + instance->clear(); + instance->waitForDone(); +} void ImageLoadRunnable::run() { const QFileInfo file(d_ptr->fileUrl); const QFileInfoList list = file.absoluteDir().entryInfoList(QDir::Files | QDir::NoDotAndDotDot); - for (const QFileInfo &info : qAsConst(list)) { + for (const QFileInfo &info : std::as_const(list)) { QImage image(info.absoluteFilePath()); if (image.isNull()) { continue; @@ -48,7 +64,7 @@ void ImageLoadRunnable::run() if (image.width() > WIDTH || image.height() > WIDTH) { image = image.scaled(WIDTH, WIDTH, Qt::KeepAspectRatio, Qt::SmoothTransformation); } - if (d_ptr->viewPtr.isNull()) { + if (d_ptr->viewPtr.isNull() || !d_ptr->running.load()) { return; } if (!d_ptr->viewPtr->setImage(info, image, d_ptr->taskCount)) { diff --git a/mainwindow/viewer.hpp b/mainwindow/viewer.hpp index 888eb4a..43f2aa6 100644 --- a/mainwindow/viewer.hpp +++ b/mainwindow/viewer.hpp @@ -10,7 +10,9 @@ class Viewer : public QWidget explicit Viewer(QWidget *parent = nullptr); ~Viewer() override; - virtual auto setImage(const QFileInfo &info, const QImage &image, const qint64 taskCount) -> bool = 0; + virtual auto setImage(const QFileInfo &info, const QImage &image, const qint64 taskCount) + -> bool + = 0; }; class ImageLoadRunnable : public QRunnable @@ -19,6 +21,8 @@ class ImageLoadRunnable : public QRunnable ImageLoadRunnable(const QString &fileUrl, Viewer *view, qint64 taskCount); ~ImageLoadRunnable() override; + static void terminateAll(); + protected: void run() override; diff --git a/openglgraphics/CMakeLists.txt b/openglgraphics/CMakeLists.txt deleted file mode 100644 index 9657f18..0000000 --- a/openglgraphics/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(PROJECT_SOURCES openglgraphics_global.hpp openglview.cc openglview.hpp) - -qt_add_resources(SOURCES shader.qrc) - -add_custom_library(openglgraphics ${PROJECT_SOURCES} ${SOURCES}) -target_link_libraries(openglgraphics PRIVATE Qt6::Widgets Qt6::OpenGLWidgets) - -if(CMAKE_HOST_WIN32) - target_compile_definitions(openglgraphics PRIVATE "OPENGLGRAPHICS_LIBRARY") -endif() diff --git a/openglgraphics/openglgraphics.pro b/openglgraphics/openglgraphics.pro deleted file mode 100644 index d1fa679..0000000 --- a/openglgraphics/openglgraphics.pro +++ /dev/null @@ -1,17 +0,0 @@ -include(../libs.pri) - -QT += widgets openglwidgets - -DEFINES += OPENGLGRAPHICS_LIBRARY -TARGET = $$replaceLibName(openglgraphics) - -HEADERS += \ - openglgraphics_global.hpp \ - openglview.hpp - -SOURCES += \ - openglview.cc - -RESOURCES += \ - shader.qrc - diff --git a/openglgraphics/openglgraphics_global.hpp b/openglgraphics/openglgraphics_global.hpp deleted file mode 100644 index 80e6799..0000000 --- a/openglgraphics/openglgraphics_global.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -#if defined(OPENGLGRAPHICS_LIBRARY) -#define OPENGLGRAPHICS Q_DECL_EXPORT -#else -#define OPENGLGRAPHICS Q_DECL_IMPORT -#endif diff --git a/openglgraphics/shader.qrc b/openglgraphics/shader.qrc deleted file mode 100644 index b8f5384..0000000 --- a/openglgraphics/shader.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - shader/texture.fs - shader/texture.vs - - diff --git a/openglgraphics/shader/texture.fs b/openglgraphics/shader/texture.fs deleted file mode 100644 index d90e79e..0000000 --- a/openglgraphics/shader/texture.fs +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core - -out vec4 FragColor; // 输出颜色 - -in vec2 TexCord; // 纹理坐标 - -uniform sampler2D tex; // 纹理 - -void main() -{ - FragColor = texture(tex, TexCord); -} diff --git a/utils/logasync.cpp b/utils/logasync.cpp index 6f9d920..4077b64 100644 --- a/utils/logasync.cpp +++ b/utils/logasync.cpp @@ -111,7 +111,7 @@ void FileUtil::autoDelFile() const QDateTime cur = QDateTime::currentDateTime(); const QDateTime pre = cur.addDays(-d_ptr->autoDelFileDays); - for (const QFileInfo &info : qAsConst(list)) { + for (const QFileInfo &info : std::as_const(list)) { if (info.lastModified() <= pre) { dir.remove(info.fileName()); } diff --git a/utils/utils.cpp b/utils/utils.cpp index b5a9605..fa49bdc 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -14,7 +14,7 @@ void Utils::setQSS() const QJsonObject json(jsonFromFile(qApp->applicationDirPath() + "/config/config.json")); const QStringList qssPath(json.value("qss_files").toVariant().toStringList()); QString qss; - for (const QString &path : qAsConst(qssPath)) { + for (const QString &path : std::as_const(qssPath)) { qDebug() << QObject::tr("Loading QSS file: %1.").arg(path); QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -34,7 +34,7 @@ void Utils::loadFonts() const QJsonObject json(jsonFromFile(qApp->applicationDirPath() + "/config/config.json")); const QStringList fontFiles(json.value("font_files").toVariant().toStringList()); - for (const QString &file : qAsConst(fontFiles)) { + for (const QString &file : std::as_const(fontFiles)) { qDebug() << QObject::tr("Loading Font file: %1").arg(file); QFontDatabase::addApplicationFont(file); } @@ -83,23 +83,17 @@ void Utils::printBuildInfo() void Utils::setHighDpiEnvironmentVariable() { - if (Utils::HostOsInfo().isMacHost()) { + if (Utils::HostOsInfo::isMacHost()) { return; } - if (Utils::HostOsInfo().isWindowsHost() && !qEnvironmentVariableIsSet("QT_OPENGL")) { -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); -#endif - } - if (Utils::HostOsInfo().isWindowsHost() + if (Utils::HostOsInfo::isWindowsHost() && !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") // legacy in 5.6, but still functional && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif } @@ -175,7 +169,7 @@ void removeFiles(const QString &path) return; } const QFileInfoList entries = dir.entryInfoList(QDir::AllEntries | QDir::Hidden); - for (const QFileInfo &fi : qAsConst(entries)) { + for (const QFileInfo &fi : std::as_const(entries)) { if (fi.isSymLink() || fi.isFile()) { QFile f(fi.filePath()); if (!f.remove()) { @@ -218,7 +212,7 @@ void Utils::removeDirectory(const QString &path) QDir d; dirs.append(path); removeFiles(path); - for (const QString &dir : qAsConst(dirs)) { + for (const QString &dir : std::as_const(dirs)) { errno = 0; if (d.exists(path) && !d.rmdir(dir)) { const QString errorMessage = QObject::tr("Cannot remove directory \"%1\": %2") @@ -297,7 +291,7 @@ auto Utils::desktopGeometry() -> QRect { QRect geometry; auto screens = QGuiApplication::screens(); - for (auto *const screen : qAsConst(screens)) { + for (auto *const screen : std::as_const(screens)) { QRect scrRect = screen->geometry(); scrRect.moveTo(scrRect.x() / screen->devicePixelRatio(), scrRect.y() / screen->devicePixelRatio());