490 lines
17 KiB
CMake
490 lines
17 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
|
|
|
project(TZshot VERSION 1.0 LANGUAGES CXX C)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
set(CMAKE_AUTOMOC ON)
|
|
set(CMAKE_AUTORCC ON)
|
|
set(CMAKE_AUTOUIC ON)
|
|
|
|
include(ExternalProject)
|
|
|
|
find_package(Qt6 REQUIRED COMPONENTS
|
|
Core
|
|
Gui
|
|
Widgets
|
|
Network
|
|
Concurrent
|
|
LinguistTools
|
|
)
|
|
|
|
qt_standard_project_setup()
|
|
|
|
# ── Third-party build options ─────────────────────────────────
|
|
option(BUILD_THIRDPART_OCR "Auto build OCR libs" ON)
|
|
option(OCR_FETCH_FROM_GITHUB "Fetch Leptonica/Tesseract from GitHub before building" ON)
|
|
|
|
# ── 翻译文件 ──────────────────────────────────────────────
|
|
set(TS_FILES
|
|
i18n/app_zh_CN.ts
|
|
i18n/app_en.ts
|
|
)
|
|
|
|
# ── 平台无关源文件 ────────────────────────────────────────
|
|
set(SOURCES
|
|
src/main.cpp
|
|
src/app/tzshot_app.cpp
|
|
src/app/tzshot_app.h
|
|
src/app/tzshot_services.cpp
|
|
src/app/tzshot_services.h
|
|
src/app/tzshot_widget_runtime.cpp
|
|
src/app/tzshot_widget_runtime.h
|
|
src/tray_icon_helper.cpp
|
|
src/tray_icon_helper.h
|
|
src/language_manager.cpp
|
|
src/language_manager.h
|
|
src/sticky_image_store.cpp
|
|
src/sticky_image_store.h
|
|
src/instance_activation.cpp
|
|
src/instance_activation.h
|
|
src/singleton.h
|
|
src/widgets/about_dialog.cpp
|
|
src/widgets/about_dialog.h
|
|
src/widgets/sticky_pin_widget.cpp
|
|
src/widgets/sticky_pin_widget.h
|
|
src/widgets/sticky_canvas_widget.cpp
|
|
src/widgets/sticky_canvas_widget.h
|
|
src/widgets/capture_overlay_widget.cpp
|
|
src/widgets/capture_overlay_widget.h
|
|
src/widgets/gif_record_overlay_widget.cpp
|
|
src/widgets/gif_record_overlay_widget.h
|
|
src/widgets/long_capture_controller.cpp
|
|
src/widgets/long_capture_controller.h
|
|
src/widgets/magnifier_widget.cpp
|
|
src/widgets/magnifier_widget.h
|
|
src/widgets/selection_mask_controller.cpp
|
|
src/widgets/selection_mask_controller.h
|
|
src/widgets/ocr_result_widget.cpp
|
|
src/widgets/ocr_result_widget.h
|
|
src/widgets/vision_result_widget.cpp
|
|
src/widgets/vision_result_widget.h
|
|
src/widgets/settings_dialog.cpp
|
|
src/widgets/settings_dialog.h
|
|
src/widgets/widget_window_bridge.cpp
|
|
src/widgets/widget_window_bridge.h
|
|
|
|
# Model
|
|
src/model/desktop_snapshot.cpp
|
|
src/model/desktop_snapshot.h
|
|
src/model/app_settings.cpp
|
|
src/model/app_settings.h
|
|
|
|
# ViewModel
|
|
src/viewmodel/screenshot_view_model.cpp
|
|
src/viewmodel/screenshot_view_model.h
|
|
src/viewmodel/sticky_view_model.cpp
|
|
src/viewmodel/sticky_view_model.h
|
|
src/viewmodel/ai_view_model.cpp
|
|
src/viewmodel/ai_view_model.h
|
|
src/viewmodel/storage_view_model.cpp
|
|
src/viewmodel/storage_view_model.h
|
|
src/viewmodel/gif_record_view_model.cpp
|
|
src/viewmodel/gif_record_view_model.h
|
|
src/viewmodel/scroll_capture_view_model.cpp
|
|
src/viewmodel/scroll_capture_view_model.h
|
|
src/viewmodel/ocr_view_model.cpp
|
|
src/viewmodel/ocr_view_model.h
|
|
src/viewmodel/vision_view_model.cpp
|
|
src/viewmodel/vision_view_model.h
|
|
|
|
# GIF Encoder
|
|
src/gif_encoder/gif.h
|
|
src/gif_encoder/gif_encoder.cpp
|
|
src/gif_encoder/gif_encoder.h
|
|
src/gif_encoder/gif_frame_grabber.cpp
|
|
src/gif_encoder/gif_frame_grabber.h
|
|
src/scroll/scroll_stitcher.cpp
|
|
src/scroll/scroll_stitcher.h
|
|
|
|
# OCR
|
|
src/ocr/ocr_engine.cpp
|
|
src/ocr/ocr_engine.h
|
|
|
|
src/paint_board/shape/shape.cpp
|
|
src/paint_board/shape/shape.h
|
|
src/paint_board/shape/shape_type.h
|
|
src/paint_board/shape/shape_factory.cpp
|
|
src/paint_board/shape/shape_factory.h
|
|
src/paint_board/shape/two_point_shape.cpp
|
|
src/paint_board/shape/two_point_shape.h
|
|
src/paint_board/shape/arrow_shape.cpp
|
|
src/paint_board/shape/arrow_shape.h
|
|
src/paint_board/shape/blur_shape.cpp
|
|
src/paint_board/shape/blur_shape.h
|
|
src/paint_board/shape/ellipse_shape.cpp
|
|
src/paint_board/shape/ellipse_shape.h
|
|
src/paint_board/shape/mosaic_shape.cpp
|
|
src/paint_board/shape/mosaic_shape.h
|
|
src/paint_board/shape/pen_shape.cpp
|
|
src/paint_board/shape/pen_shape.h
|
|
src/paint_board/shape/rect_shape.cpp
|
|
src/paint_board/shape/rect_shape.h
|
|
src/paint_board/shape/text_shape.cpp
|
|
src/paint_board/shape/text_shape.h
|
|
src/paint_board/shape/number_shape.cpp
|
|
src/paint_board/shape/number_shape.h
|
|
|
|
# AI
|
|
src/ai_call/ai_call_base.cpp
|
|
src/ai_call/ai_call_base.h
|
|
src/ai_call/ai_type.h
|
|
src/ai_call/qwen_ai_call.cpp
|
|
src/ai_call/qwen_ai_call.h
|
|
src/ai_call/seedream_ai_call.cpp
|
|
src/ai_call/seedream_ai_call.h
|
|
src/ai_call/doubao_vision_call.cpp
|
|
src/ai_call/doubao_vision_call.h
|
|
|
|
# Shortcut — 跨平台公共部分
|
|
src/shortcut_key/globalshortcut.cpp
|
|
src/shortcut_key/globalshortcut.h
|
|
|
|
# Resources
|
|
qml.qrc
|
|
)
|
|
|
|
# ── 平台专属源文件 ────────────────────────────────────────
|
|
if(UNIX)
|
|
list(APPEND SOURCES
|
|
src/shortcut_key/linux_grab.c
|
|
src/shortcut_key/linux_grab.h
|
|
)
|
|
endif()
|
|
|
|
if(WIN32)
|
|
list(APPEND SOURCES
|
|
resource/windows/tzshot.rc
|
|
src/shortcut_key/win_grab.c
|
|
src/shortcut_key/win_grab.h
|
|
)
|
|
endif()
|
|
|
|
qt_add_executable(TZshot
|
|
${SOURCES}
|
|
)
|
|
|
|
# ── include 路径 ──────────────────────────────────────────
|
|
target_include_directories(TZshot PRIVATE
|
|
src
|
|
src/ai_call
|
|
src/gif_encoder
|
|
src/ocr
|
|
src/paint_board
|
|
src/paint_board/shape
|
|
src/model
|
|
src/viewmodel
|
|
src/scroll
|
|
src/shortcut_key
|
|
)
|
|
|
|
# ── 编译定义 ──────────────────────────────────────────────
|
|
target_compile_definitions(TZshot PRIVATE
|
|
QT_DEPRECATED_WARNINGS
|
|
)
|
|
|
|
target_compile_definitions(TZshot PRIVATE
|
|
$<$<CONFIG:Debug>:STICKY_MEM_DEBUG>
|
|
)
|
|
|
|
# ── Qt 模块链接 ───────────────────────────────────────────
|
|
target_link_libraries(TZshot PRIVATE
|
|
Qt6::Core
|
|
Qt6::Gui
|
|
Qt6::Widgets
|
|
Qt6::Network
|
|
Qt6::Concurrent
|
|
)
|
|
|
|
# ── 平台系统库 ────────────────────────────────────────────
|
|
if(UNIX)
|
|
target_link_libraries(TZshot PRIVATE
|
|
X11
|
|
xcb
|
|
pthread
|
|
)
|
|
|
|
set(OCR_ENABLED FALSE)
|
|
set(OCR_PREFIX "$ENV{OCR_PREFIX}")
|
|
if(OCR_PREFIX STREQUAL "")
|
|
set(OCR_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/thirdpart/ocr")
|
|
endif()
|
|
|
|
set(OCR_LIB_DIR "")
|
|
if(EXISTS "${OCR_PREFIX}/lib/libtesseract.so" OR EXISTS "${OCR_PREFIX}/lib/libtesseract.a")
|
|
set(OCR_LIB_DIR "${OCR_PREFIX}/lib")
|
|
elseif(EXISTS "${OCR_PREFIX}/lib64/libtesseract.so" OR EXISTS "${OCR_PREFIX}/lib64/libtesseract.a")
|
|
set(OCR_LIB_DIR "${OCR_PREFIX}/lib64")
|
|
endif()
|
|
|
|
if(NOT OCR_LIB_DIR STREQUAL "")
|
|
target_include_directories(TZshot PRIVATE
|
|
"${OCR_PREFIX}/include"
|
|
"${OCR_PREFIX}/include/leptonica"
|
|
)
|
|
target_link_directories(TZshot PRIVATE "${OCR_LIB_DIR}")
|
|
target_link_libraries(TZshot PRIVATE tesseract leptonica)
|
|
target_compile_definitions(TZshot PRIVATE
|
|
ENABLE_OCR
|
|
OCR_TESSDATA_DIR=\"${OCR_PREFIX}/share/tessdata\"
|
|
)
|
|
set(OCR_ENABLED TRUE)
|
|
message(STATUS "OCR enabled via thirdpart: ${OCR_PREFIX}")
|
|
endif()
|
|
|
|
if(NOT OCR_ENABLED)
|
|
find_package(PkgConfig QUIET)
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(TESSERACT QUIET IMPORTED_TARGET tesseract)
|
|
pkg_check_modules(LEPT QUIET IMPORTED_TARGET lept)
|
|
if(TESSERACT_FOUND AND LEPT_FOUND)
|
|
target_link_libraries(TZshot PRIVATE PkgConfig::TESSERACT PkgConfig::LEPT)
|
|
target_compile_definitions(TZshot PRIVATE ENABLE_OCR)
|
|
message(STATUS "OCR enabled via pkg-config: tesseract + lept")
|
|
else()
|
|
message(STATUS "OCR disabled: thirdpart OCR not found and pkg-config tesseract/lept unavailable")
|
|
endif()
|
|
else()
|
|
message(STATUS "OCR disabled: PkgConfig not found")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(WIN32)
|
|
target_link_libraries(TZshot PRIVATE
|
|
user32 # RegisterHotKey / UnregisterHotKey / EnumWindows
|
|
gdi32
|
|
)
|
|
|
|
set(OCR_ENABLED FALSE)
|
|
if(BUILD_THIRDPART_OCR AND OCR_FETCH_FROM_GITHUB)
|
|
set(OCR_THIRDPART_DIR "${CMAKE_CURRENT_SOURCE_DIR}/thirdpart")
|
|
set(OCR_INSTALL_DIR "${OCR_THIRDPART_DIR}/ocr-install")
|
|
set(OCR_TESSDATA_DIR "${OCR_INSTALL_DIR}/share/tessdata")
|
|
# ExternalProject build trees must be generator-specific.
|
|
# Otherwise switching between Ninja/VS reuses incompatible CMake caches.
|
|
set(OCR_EP_KEY "${CMAKE_GENERATOR}-${CMAKE_GENERATOR_PLATFORM}")
|
|
string(REGEX REPLACE "[^A-Za-z0-9_.-]" "_" OCR_EP_KEY "${OCR_EP_KEY}")
|
|
set(OCR_EP_ROOT_DIR "${OCR_THIRDPART_DIR}/_ep_${OCR_EP_KEY}")
|
|
set(OCR_ZLIB_VERSION "v1.3.1")
|
|
set(OCR_LIBPNG_VERSION "v1.6.43")
|
|
set(OCR_LIBJPEG_TURBO_VERSION "3.0.3")
|
|
set(OCR_LIBTIFF_VERSION "v4.7.0")
|
|
set(OCR_LEPTONICA_VERSION "1.87.0")
|
|
set(OCR_TESSERACT_VERSION "5.5.2")
|
|
# Imported target include dirs are validated at generate time.
|
|
# Create expected install dirs up front; actual contents are produced by ExternalProject.
|
|
file(MAKE_DIRECTORY
|
|
"${OCR_INSTALL_DIR}/include"
|
|
"${OCR_INSTALL_DIR}/lib"
|
|
"${OCR_TESSDATA_DIR}"
|
|
)
|
|
|
|
# Make ExternalProject follow current build type (Debug/Release) on
|
|
# single-config generators (e.g. Ninja in Qt Creator kits).
|
|
set(OCR_EP_BUILD_TYPE_ARG "")
|
|
if(NOT CMAKE_CONFIGURATION_TYPES)
|
|
if(CMAKE_BUILD_TYPE STREQUAL "")
|
|
set(OCR_EP_BUILD_TYPE "Debug")
|
|
else()
|
|
set(OCR_EP_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
|
|
endif()
|
|
set(OCR_EP_BUILD_TYPE_ARG "-DCMAKE_BUILD_TYPE=${OCR_EP_BUILD_TYPE}")
|
|
endif()
|
|
|
|
ExternalProject_Add(zlib_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/zlib"
|
|
GIT_REPOSITORY "https://github.com/madler/zlib.git"
|
|
GIT_TAG "${OCR_ZLIB_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DBUILD_SHARED_LIBS=ON
|
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
ExternalProject_Add(libpng_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/libpng"
|
|
GIT_REPOSITORY "https://github.com/pnggroup/libpng.git"
|
|
GIT_TAG "${OCR_LIBPNG_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
DEPENDS zlib_ep
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
|
|
-DZLIB_ROOT=${OCR_INSTALL_DIR}
|
|
-DPNG_SHARED=ON
|
|
-DPNG_TESTS=OFF
|
|
-DPNG_EXECUTABLES=OFF
|
|
-DPNG_FRAMEWORK=OFF
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
ExternalProject_Add(libjpeg_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/libjpeg"
|
|
GIT_REPOSITORY "https://github.com/libjpeg-turbo/libjpeg-turbo.git"
|
|
GIT_TAG "${OCR_LIBJPEG_TURBO_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DBUILD_SHARED_LIBS=ON
|
|
-DENABLE_SHARED=ON
|
|
-DENABLE_STATIC=OFF
|
|
-DWITH_TURBOJPEG=ON
|
|
-DWITH_JPEG8=ON
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
ExternalProject_Add(libtiff_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/libtiff"
|
|
GIT_REPOSITORY "https://github.com/libsdl-org/libtiff.git"
|
|
GIT_TAG "${OCR_LIBTIFF_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
DEPENDS zlib_ep
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
|
|
-DBUILD_SHARED_LIBS=ON
|
|
-Dzlib=ON
|
|
-Djpeg=OFF
|
|
-Dwebp=OFF
|
|
-Dzstd=OFF
|
|
-Dlzma=OFF
|
|
-Djbig=OFF
|
|
-Dlerc=OFF
|
|
-Dtiff-tools=OFF
|
|
-Dtiff-tests=OFF
|
|
-Dtiff-contrib=OFF
|
|
-Dtiff-docs=OFF
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
ExternalProject_Add(leptonica_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/leptonica"
|
|
GIT_REPOSITORY "https://github.com/DanBloomberg/leptonica.git"
|
|
GIT_TAG "${OCR_LEPTONICA_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
DEPENDS libpng_ep libjpeg_ep libtiff_ep
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
|
|
-DBUILD_SHARED_LIBS=ON
|
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
|
-DSW_BUILD=OFF
|
|
-DSTRICT_CONF=ON
|
|
-DENABLE_ZLIB=ON
|
|
-DENABLE_PNG=ON
|
|
-DENABLE_GIF=OFF
|
|
-DENABLE_JPEG=ON
|
|
-DENABLE_TIFF=ON
|
|
-DENABLE_WEBP=OFF
|
|
-DENABLE_OPENJPEG=OFF
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
ExternalProject_Add(tesseract_ep
|
|
PREFIX "${OCR_EP_ROOT_DIR}/tesseract"
|
|
GIT_REPOSITORY "https://github.com/tesseract-ocr/tesseract.git"
|
|
GIT_TAG "${OCR_TESSERACT_VERSION}"
|
|
UPDATE_DISCONNECTED 1
|
|
DEPENDS leptonica_ep
|
|
CMAKE_ARGS
|
|
-DCMAKE_INSTALL_PREFIX=${OCR_INSTALL_DIR}
|
|
-DCMAKE_PREFIX_PATH=${OCR_INSTALL_DIR}
|
|
-DBUILD_SHARED_LIBS=ON
|
|
-DSW_BUILD=OFF
|
|
-DBUILD_TRAINING_TOOLS=OFF
|
|
-DBUILD_TESTS=OFF
|
|
-DDISABLE_ARCHIVE=ON
|
|
-DDISABLE_CURL=ON
|
|
-DOPENMP_BUILD=OFF
|
|
${OCR_EP_BUILD_TYPE_ARG}
|
|
)
|
|
|
|
add_dependencies(TZshot tesseract_ep)
|
|
|
|
target_include_directories(TZshot PRIVATE "${OCR_INSTALL_DIR}/include")
|
|
target_link_directories(TZshot PRIVATE "${OCR_INSTALL_DIR}/lib")
|
|
set(OCR_LEPTONICA_LINK_NAME "leptonica-${OCR_LEPTONICA_VERSION}$<$<CONFIG:Debug>:d>")
|
|
if(MINGW)
|
|
# Our MinGW Leptonica ExternalProject installs libleptonica.dll.a
|
|
# without a version/debug suffix, so link against that stable name.
|
|
set(OCR_LEPTONICA_LINK_NAME "leptonica")
|
|
endif()
|
|
target_link_libraries(TZshot PRIVATE
|
|
"tesseract55$<$<CONFIG:Debug>:d>"
|
|
"${OCR_LEPTONICA_LINK_NAME}"
|
|
Ws2_32
|
|
)
|
|
|
|
target_compile_definitions(TZshot PRIVATE
|
|
ENABLE_OCR
|
|
OCR_TESSDATA_DIR=\"${OCR_TESSDATA_DIR}\"
|
|
)
|
|
|
|
# Ensure runtime OCR DLLs are available beside TZshot.exe.
|
|
add_custom_command(TARGET TZshot POST_BUILD
|
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
|
"${OCR_INSTALL_DIR}/bin"
|
|
"$<TARGET_FILE_DIR:TZshot>"
|
|
VERBATIM
|
|
)
|
|
|
|
set(OCR_ENABLED TRUE)
|
|
message(STATUS "OCR enabled via GitHub fetch/build (Leptonica ${OCR_LEPTONICA_VERSION}, Tesseract ${OCR_TESSERACT_VERSION})")
|
|
endif()
|
|
|
|
if(NOT OCR_ENABLED)
|
|
message(STATUS "OCR disabled on Windows: BUILD_THIRDPART_OCR/OCR_FETCH_FROM_GITHUB is OFF")
|
|
endif()
|
|
|
|
# Windows 子系统:Release 用 /SUBSYSTEM:WINDOWS 隐藏控制台窗口
|
|
set_target_properties(TZshot PROPERTIES
|
|
WIN32_EXECUTABLE $<IF:$<CONFIG:Debug>,FALSE,TRUE>
|
|
)
|
|
endif()
|
|
|
|
# ── 翻译 ──────────────────────────────────────────────────
|
|
qt_add_translations(TZshot
|
|
TS_FILES ${TS_FILES}
|
|
QM_FILES_OUTPUT_VARIABLE QM_FILES
|
|
)
|
|
|
|
# Package generated .qm files into the app resource at :/i18n.
|
|
foreach(qm_file IN LISTS QM_FILES)
|
|
get_filename_component(qm_name "${qm_file}" NAME)
|
|
set_source_files_properties("${qm_file}" PROPERTIES
|
|
QT_RESOURCE_ALIAS "${qm_name}"
|
|
)
|
|
endforeach()
|
|
|
|
qt_add_resources(TZshot "i18n_translations"
|
|
PREFIX "/i18n"
|
|
FILES ${QM_FILES}
|
|
)
|
|
|
|
# ── 安装 ──────────────────────────────────────────────────
|
|
if(UNIX AND NOT ANDROID)
|
|
install(TARGETS TZshot
|
|
DESTINATION /opt/TZshot/bin
|
|
)
|
|
endif()
|
|
|
|
if(WIN32)
|
|
install(TARGETS TZshot
|
|
DESTINATION bin
|
|
)
|
|
endif()
|