##########################################################################
##                                                                      ##
## Copyright (C) 2011-2026 Lukas Spies                                  ##
## Contact: https://photoqt.org                                         ##
##                                                                      ##
## This file is part of PhotoQt.                                        ##
##                                                                      ##
## PhotoQt is free software: you can redistribute it and/or modify      ##
## it under the terms of the GNU General Public License as published by ##
## the Free Software Foundation, either version 2 of the License, or    ##
## (at your option) any later version.                                  ##
##                                                                      ##
## PhotoQt is distributed in the hope that it will be useful,           ##
## but WITHOUT ANY WARRANTY; without even the implied warranty of       ##
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        ##
## GNU General Public License for more details.                         ##
##                                                                      ##
## You should have received a copy of the GNU General Public License    ##
## along with PhotoQt. If not, see <http://www.gnu.org/licenses/>.      ##
##                                                                      ##
##########################################################################

##############################################
# CMakeLists for PhotoQt: http://photoqt.org #
##############################################

cmake_minimum_required(VERSION 3.16)
project(photoqt LANGUAGES C CXX)

##################################################################
####  GLOBAL VERSION STRING FOR ALL FILES (INCLUDING CPP/QML) ####
##################################################################

SET(APPVERSION "5.4")

###################################
####  ENSURE BUILD TYPE IS SET ####
###################################

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

#############################
####  GET list of files  ####
#############################

include(CMake/ListFilesCPlusPlus.cmake)
include(CMake/ListFilesQML.cmake)

#############################################
#### OPTIONS THAT CAN BE SET BY THE USER ####
#############################################

option(WITH_IMAGEMAGICK           "Configure with support for the ImageMagick library" ON)
option(WITH_GRAPHICSMAGICK        "Configure with support for the GraphicsMagick library" OFF)
option(WITH_LIBRAW                "Configure with support for the libraw library" ON)
option(WITH_DEVIL                 "Configure with support for the DevIL library" ON)
option(WITH_POPPLER               "Configure with support for the Poppler library" ON)
option(WITH_QTPDF                 "Configure with support for the QtPDF module (instead of Poppler)" ON)
option(WITH_LIBARCHIVE            "Configure with support for the libarchive library" ON)
option(WITH_VIDEO_QT              "Configure with video support through Qt" ON)
option(WITH_VIDEO_MPV             "Configure with video support through MPV" ON)
option(WITH_LIBVIPS               "Configure with support for the libvips library" OFF)
option(WITH_RESVG                 "Configure with support for the resvg library (better SVG support)" OFF)
option(WITH_LIBSAI                "Configure with support for the libsai library (requires C++20 support)" OFF)

option(WITH_EXTENSIONS_SUPPORT    "Enable support for extensions (requires yaml-cpp and qca)" ON)
option(WITH_EXTENSIONS_NONSYS_OPENSSL              "Verify non-system (external) extensions using OpenSSL" ON)
option(WITH_EXTENSIONS_NONSYS_LIBRARY_VERIFICATION "Include the shared library (.so/.dll) when verifying non-system extensions" ON)
option(WITH_EXIV2                 "Configure with support for the Exiv2 library" ON)
option(WITH_EXIV2_ENABLE_BMFF     "Configure with BMFF format support in Exiv2 (if available) - only needed for Exiv2 0.27.x and before" ON)
option(WITH_ZXING                 "Configure with support for the ZXing library (QR and barcodes detection)" ON)
option(WITH_CHROMECAST            "Configure with support for Chromecast (through Python)" ON)
option(WITH_CHROMECAST_PIPINSTALL "Allows CMake to attempt to install PyChromecast locally using pip" OFF)
option(WITH_LOCATION              "Configure with support for the QtPositioning/QtLocation QML modules" ON)
option(WITH_LCMS2                 "Configure with support for the Little CMS library (advanced color management)" ON)
option(WITH_MOTIONPHOTO           "Configure with support for Google Motion Photos and Apple Live Photos" ON)
option(WITH_PHOTOSPHERE           "Configure with support for photo spheres and 360 degree panoramic views" ON)
option(WITH_PHOTOSPHERE_QRHI      "Use private Qt6 Gui header QRhi to figure our maximum possible texture size" OFF)
option(WITH_PUGIXML               "Configure with support for the pugixml library (in place of Qt's XML support)" OFF)
option(WITH_FFMPEGTHUMBNAILER     "Use ffmpegthumbnailer's C++ API instead of calling the executable" OFF)

option(WITH_WAYLANDSPECIFIC       "Enable optional Wayland-specific code to allow for further optimizations." ON)
option(WITH_JPEG2000_WORKAROUNDS  "Enable specific workarounds for JPEG-2000" ON)
option(WITH_TESTING               "Enable and build some unit tests" OFF)
option(WITH_RUNCPPCHECK           "Analyse source code with cppcheck" OFF)
option(WITH_FLATPAKBUILD          "Enable this option if this is a build for Flatpak" OFF)
option(WITH_APPIMAGEBUILD         "Enable this option if this is an AppImage build" OFF)
option(WITH_ADAPTSOURCE           "Adapt and change the source files for the current Qt version (if necessary)" OFF)
option(WITHOUT_ICU                "Enable this option if your Qt6 setup has no ICU support" OFF)
option(WITH_PORTABLETWEAKS        "Apply tweaks for a build of a portable version" OFF)

set(EXTENSIONS_NONSYS_CUSTOM_PUBLIC_KEY "" CACHE STRING "Add a custom public key to be used for extension verification.")

#####################################
#### RESOLVE CONFLICTING OPTIONS ####
#####################################

if(WITH_QTPDF)
    if(WITH_POPPLER)
        set(WITH_POPPLER OFF)
        message("** For displaying PDF documents you have to choose either Poppler OR QtPDF.")
        message("** Poppler has been automatically disabled in favour of QtPDF.")
    endif()
endif()

if(WITH_IMAGEMAGICK)
    if(WITH_GRAPHICSMAGICK)
        set(WITH_GRAPHICSMAGICK OFF)
        message("** ImageMagick and GraphicsMagick cannot be used at the same time.")
        message("** GraphicsMagick has been automatically disabled in favour of ImageMagick.")
    endif()
endif()

##################################
#### INTERNAL ADAPTED OPTIONS ####
##################################

# these will be set to ON when enabled AND when found
# and will be set to OFF otherwise
# this way the user facing options remain unchanged
# and there is clearer info about which ones FAILED to be enabled

set(_WITH_IMAGEMAGICK           ${WITH_IMAGEMAGICK})
set(_WITH_GRAPHICSMAGICK        ${WITH_GRAPHICSMAGICK})
set(_WITH_LIBRAW                ${WITH_LIBRAW})
set(_WITH_DEVIL                 ${WITH_DEVIL})
set(_WITH_POPPLER               ${WITH_POPPLER})
set(_WITH_QTPDF                 ${WITH_QTPDF})
set(_WITH_LIBARCHIVE            ${WITH_LIBARCHIVE})
set(_WITH_VIDEO_QT              ${WITH_VIDEO_QT})
set(_WITH_VIDEO_MPV             ${WITH_VIDEO_MPV})
set(_WITH_LIBVIPS               ${WITH_LIBVIPS})
set(_WITH_RESVG                 ${WITH_RESVG})
set(_WITH_LIBSAI                ${WITH_LIBSAI})

set(_WITH_EXTENSIONS_SUPPORT    ${WITH_EXTENSIONS_SUPPORT})
set(_WITH_EXTENSIONS_NONSYS_OPENSSL              ${WITH_EXTENSIONS_NONSYS_OPENSSL})
set(_WITH_EXTENSIONS_NONSYS_LIBRARY_VERIFICATION ${WITH_EXTENSIONS_NONSYS_LIBRARY_VERIFICATION})
set(_WITH_EXIV2                 ${WITH_EXIV2})
set(_WITH_EXIV2_ENABLE_BMFF     ${WITH_EXIV2_ENABLE_BMFF})
set(_WITH_ZXING                 ${WITH_ZXING})
set(_WITH_CHROMECAST            ${WITH_CHROMECAST})
set(_WITH_CHROMECAST_PIPINSTALL ${WITH_CHROMECAST_PIPINSTALL})
set(_WITH_LOCATION              ${WITH_LOCATION})
set(_WITH_LCMS2                 ${WITH_LCMS2})
set(_WITH_MOTIONPHOTO           ${WITH_MOTIONPHOTO})
set(_WITH_PHOTOSPHERE           ${WITH_PHOTOSPHERE})
set(_WITH_PHOTOSPHERE_QRHI      ${WITH_PHOTOSPHERE_QRHI})
set(_WITH_PUGIXML               ${WITH_PUGIXML})
set(_WITH_FFMPEGTHUMBNAILER     ${WITH_FFMPEGTHUMBNAILER})

set(_WITH_WAYLANDSPECIFIC       ${WITH_WAYLANDSPECIFIC})
set(_WITH_JPEG2000_WORKAROUNDS  ${WITH_JPEG2000_WORKAROUNDS})
set(_WITH_TESTING               ${WITH_TESTING})
set(_WITH_RUNCPPCHECK           ${WITH_RUNCPPCHECK})
set(_WITH_FLATPAKBUILD          ${WITH_FLATPAKBUILD})
set(_WITH_APPIMAGEBUILD         ${WITH_APPIMAGEBUILD})
set(_WITH_ADAPTSOURCE           ${WITH_ADAPTSOURCE})
set(_WITHOUT_ICU                ${WITHOUT_ICU})
set(_WITH_PORTABLETWEAKS        ${WITH_PORTABLETWEAKS})

################################
#### SET ADDITIONAL SOURCES ####
################################

SET(photoqt_QML_ADDITIONAL "")

################################
#### FIND REQUIRED PACKAGES ####
################################

find_package(Qt6 6.4 REQUIRED COMPONENTS Quick Widgets Sql Core Svg Concurrent Multimedia PrintSupport DBus LinguistTools)

if(_WITH_PHOTOSPHERE_QRHI)
    # this module is needed for getting the maximum texture size possible using QRhi
    find_package(Qt6 COMPONENTS GuiPrivate)
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")

find_package(ECM REQUIRED NO_MODULE)
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})

#########

if(_WITH_IMAGEMAGICK)
    find_package(ImageMagick COMPONENTS Magick++)
    if(NOT ${ImageMagick_FOUND})
        message("** ImageMagick not found. Disabling.")
        SET(_WITH_IMAGEMAGICK OFF)
    else()
        SET(_WITH_IMAGEMAGICK ON)
    endif()
endif()

if(_WITH_GRAPHICSMAGICK)
    find_package(GraphicsMagick)
    if(NOT ${MAGICK++_FOUND})
        message("** GraphicsMagick not found. Disabling.")
        SET(_WITH_GRAPHICSMAGICK OFF)
    else()
        SET(_WITH_GRAPHICSMAGICK ON)
    endif()
endif()

if(_WITH_LIBRAW)
    find_package(LibRaw)
    if(NOT ${LibRaw_FOUND})
        message("** LibRaw not found. Disabling.")
        SET(_WITH_LIBRAW OFF)
    else()
        SET(_WITH_LIBRAW ON)
    endif()
endif()

if(_WITH_DEVIL)
    find_package(DevIL)
    if(NOT ${DevIL_FOUND})
        message("** DevIL not found. Disabling.")
        SET(_WITH_DEVIL OFF)
    else()
        SET(_WITH_DEVIL ON)
    endif()
endif()

if(_WITH_POPPLER)
    find_package(Poppler COMPONENTS Qt6)
    if(NOT ${Poppler_FOUND})
        message("** Poppler not found. Disabling.")
        SET(_WITH_POPPLER OFF)
    else()
        SET(_WITH_POPPLER ON)
    endif()
endif()

if(_WITH_QTPDF)
    find_package(Qt6 COMPONENTS Pdf)
    if(NOT ${Qt6Pdf_FOUND})
        message("** Qt PDF component not found. Disabling.")
        SET(_WITH_QTPDF OFF)
    else()
        SET(_WITH_QTPDF ON)
    endif()
endif()

if(_WITH_LIBARCHIVE)
    find_package(LibArchive)
    if(NOT ${LibArchive_FOUND})
        message("** LibArchive not found. Disabling.")
        SET(_WITH_LIBARCHIVE OFF)
    else()
        SET(_WITH_LIBARCHIVE ON)
    endif()
endif()

if(_WITH_VIDEO_MPV)
    find_package(Libmpv)
    if(NOT ${Libmpv_FOUND})
        message("** libmpv not found. Disabling.")
        SET(_WITH_VIDEO_MPV OFF)
    else()
        SET(_WITH_VIDEO_MPV ON)
    endif()
endif()

if(_WITH_LIBVIPS)
    find_package(PkgConfig REQUIRED)
    pkg_search_module(GLIB glib-2.0 gobject-2.0)
    if(NOT ${GLIB_FOUND})
        message("** glib not found. Disabling libvips.")
        SET(_WITH_LIBVIPS OFF)
    else()
        pkg_search_module(VIPS vips-cpp)
        if(NOT ${VIPS_FOUND})
            message("** libvips not found. Disabling.")
            SET(_WITH_LIBVIPS OFF)
        else()
            SET(_WITH_LIBVIPS ON)
        endif()
    endif()
endif()

if(_WITH_LIBSAI)
    find_package(Libsai)
    if(NOT ${Libsai_FOUND})
        message("** Libsai not found. Disabling.")
        SET(_WITH_LIBSAI OFF)
    else()
        SET(_WITH_LIBSAI ON)
        set(CMAKE_CXX_STANDARD 20)
    endif()
endif()

if(_WITH_EXTENSIONS_SUPPORT)
    find_package(yaml-cpp)
    if(NOT ${yaml-cpp_FOUND})
        message("** yaml-cpp not found. Disabling extensions.")
        SET(_WITH_EXTENSIONS_SUPPORT OFF)
    else()
        SET(_WITH_EXTENSIONS_SUPPORT ON)
    endif()
endif()

if(NOT _WITH_EXTENSIONS_SUPPORT)
    message("** since extensions are disabled, also disabling OpenSSL verification")
    SET(_WITH_EXTENSIONS_NONSYS_OPENSSL OFF)
endif()

if(_WITH_EXTENSIONS_NONSYS_OPENSSL)
    find_package(OpenSSL REQUIRED)
    if(NOT ${OpenSSL_FOUND})
        message("** OpenSSL not found. Disabling non-system extensions verification.")
        SET(_WITH_EXTENSIONS_NONSYS_OPENSSL OFF)
    else()
        SET(_WITH_EXTENSIONS_NONSYS_OPENSSL ON)
    endif()
endif()

if(_WITH_EXIV2)
    find_package(exiv2)
    if(NOT ${exiv2_FOUND})
        message("** Exiv2 not found. Disabling.")
        SET(_WITH_EXIV2 OFF)
    else()
        SET(_WITH_EXIV2 ON)
    endif()
endif()

if(_WITH_PUGIXML)
    find_package(pugixml)
    if(NOT ${pugixml_FOUND})
        message("** pugixml not found. Disabling.")
        SET(_WITH_PUGIXML OFF)
    else()
        SET(_WITH_PUGIXML ON)
    endif()
endif()
# this is a seperate check as this option might be set to OFF in the block above
if(NOT _WITH_PUGIXML)
    find_package(Qt6 6.4 REQUIRED COMPONENTS Xml)
endif()

if(_WITH_ZXING)
    find_package(ZXing)
    if(NOT ${ZXing_FOUND})
        message("** ZXing not found. Disabling.")
        SET(_WITH_ZXING OFF)
    else()
        SET(_WITH_ZXING ON)
        find_file(ZXINGQTINC "ZXing/ZXingQt.h" PATHS ${INCLUDE_DIRECTORIES})
        if(EXISTS ${ZXINGQTINC})
            SET(photoqt_SOURCES ${photoqt_SOURCES} ${ZXINGQTINC})
        endif()
    endif()
endif()

if(_WITH_CHROMECAST)
    find_package(Python3 COMPONENTS Interpreter)
    if(NOT ${Python3_FOUND})
        message("** Python3 not found. Disabling Chromecast.")
        SET(_WITH_CHROMECAST OFF)
    elseif(NOT ${Python3_Interpreter_FOUND})
        message("** Python3 Interpreter not found. Disabling Chromecast.")
        SET(_WITH_CHROMECAST OFF)
    else()
        SET(_WITH_CHROMECAST ON)
    endif()
endif()

if(_WITH_LCMS2)
    find_package(LCMS2)
    if(NOT ${LCMS2_FOUND})
        message("** LCMS2 not found. Disabling.")
        SET(_WITH_LCMS2 OFF)
    else()
        SET(_WITH_LCMS2 ON)
    endif()
endif()

if(_WITH_FLATPAKBUILD)
    find_package(PkgConfig)
    if(NOT ${PkgConfig_FOUND})
        message("** PkgConfig not found. Disabling flatpak workaround.")
        SET(_WITH_FLATPAKBUILD OFF)
    else()
        pkg_search_module(GLIB glib-2.0 gobject-2.0 gio-2.0)
        if(NOT ${GLIB_FOUND})
            message("** GLIB not found. Disabling flatpak workaround.")
            SET(_WITH_FLATPAKBUILD OFF)
        else()
            SET(_WITH_FLATPAKBUILD ON)
        endif()
    endif()
endif()

if(_WITH_WAYLANDSPECIFIC)
    find_package(Wayland COMPONENTS Client)
    if(NOT ${WAYLAND_CLIENT_FOUND})
        message("** Wayland not found. Disabling.")
        SET(_WITH_WAYLANDSPECIFIC OFF)
    else()
        SET(_WITH_WAYLANDSPECIFIC ON)
    endif()
endif()

if(_WITH_LOCATION)
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_LOCATION})
else()
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_NOLOCATION})
endif()

if(_WITH_VIDEO_QT)
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_QTMULTIMEDIA})
else()
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_NOQTMULTIMEDIA})
endif()

if(_WITH_VIDEO_MPV)
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_LIBMPV})
    SET(photoqt_SOURCES ${photoqt_SOURCES} ${photoqt_SOURCES_LIBMPV})
else()
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_NOLIBMPV})
endif()

if(_WITH_PHOTOSPHERE)
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_PHOTOSPHERE})
else()
    SET(photoqt_QML_ADDITIONAL ${photoqt_QML_ADDITIONAL} ${photoqt_QML_NOPHOTOSPHERE})
endif()

# Any additional sources are added to the full list.
SET(photoqt_QML ${photoqt_QML} ${photoqt_QML_ADDITIONAL} ${photoqt_QML_SINGLETONS})

#################################
#### EXTENSIONS KEY HANDLING ####
#################################

file(COPY misc/extensions/extensions.key DESTINATION "${CMAKE_BINARY_DIR}")
if(EXTENSIONS_NONSYS_CUSTOM_PUBLIC_KEY STREQUAL "")
    message(" ** Using only built-in public key for non-system extension verification.")
    file(COPY misc/extensions/extensions_nocustom.qrc DESTINATION "${CMAKE_BINARY_DIR}")
    file(RENAME "${CMAKE_BINARY_DIR}/extensions_nocustom.qrc" "${CMAKE_BINARY_DIR}/extensions.qrc")
else()
    message(" ** Adding custom RSA public key for extension verification.")
    message(" ** This allows signing the extensions with the corresponding private key for verification.")
    # get filename
    get_filename_component(keyfn "${EXTENSIONS_NONSYS_CUSTOM_PUBLIC_KEY}" NAME)
    # copy custom key to tmp directory
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/extensionstmp")
    file(COPY "${EXTENSIONS_NONSYS_CUSTOM_PUBLIC_KEY}" DESTINATION "${CMAKE_BINARY_DIR}/extensionstmp/")
    # rename to standard filename
    file(RENAME "${CMAKE_BINARY_DIR}/extensionstmp/${keyfn}" "${CMAKE_BINARY_DIR}/extensionstmp/custom_extensions.key")
    # copy to bin dir
    file(COPY "${CMAKE_BINARY_DIR}/extensionstmp/custom_extensions.key" DESTINATION "${CMAKE_BINARY_DIR}")
    execute_process(COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/extensionstmp/custom_extensions.key")
    # and remove tmp directory
    file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/extensionstmp/")
    # copy over matching qrc file
    file(COPY misc/extensions/extensions_custom.qrc DESTINATION "${CMAKE_BINARY_DIR}/")
    file(RENAME "${CMAKE_BINARY_DIR}/extensions_custom.qrc" "${CMAKE_BINARY_DIR}/extensions.qrc")
    # add macro
    target_compile_definitions(photoqt PRIVATE PQMHAVECUSTOMKEY)
endif()

######################
#### RUN CPPCHECK ####
######################

if(_WITH_RUNCPPCHECK)

    # Find CppCheck executable
    find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck)

    # If CppCheck executable found
    if(CMAKE_CXX_CPPCHECK)

        message("** Analyzing source code with cppcheck")

        # Append desired arguments to CppCheck
        list(APPEND CMAKE_CXX_CPPCHECK
                "--enable=warning"
                "--inconclusive"
                "--library=qt"
        )

    endif()

else()

    unset(CMAKE_CXX_CPPCHECK CACHE)

endif()


########################################
#### Handle Qt<6.4/5 specific stuff ####
########################################

# there are some QML properties and items that were added with later versions of Qt
# since QML does not support macros, we need to make do with adjusting the source code if needed
# this is of course guarded behind an opt-in option presented to the user
foreach(QTV 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13)

    string(REPLACE "." "" QTVnodot ${QTV})
    math(EXPR QTVnodotMINUS1 "${QTVnodot}-1")

    # some things is only available since Qt 6.x
    if(Qt6_VERSION VERSION_LESS ${QTV})

        # we need to modify the code slightly to make it work with Qt 6.x-
        foreach(QMLFILE ${photoqt_QML})

            file(READ ${QMLFILE} FILE_CONTENTS)

            set(anything_changed FALSE)

            # switch on Qt 6.x- specific code
            if(FILE_CONTENTS MATCHES "/\\*1off_Qt${QTVnodotMINUS1}")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*1off_Qt${QTVnodotMINUS1}\n" "/*1on_Qt${QTVnodotMINUS1}*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()
            if(FILE_CONTENTS MATCHES "2off_Qt${QTVnodotMINUS1}\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "2off_Qt${QTVnodotMINUS1}\\*/\n" "/*2on_Qt${QTVnodotMINUS1}*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()

            # switch off Qt 6.x specific code
            if(FILE_CONTENTS MATCHES "/\\*1on_Qt${QTVnodot}\\+\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*1on_Qt${QTVnodot}\\+\\*/\n" "/*1off_Qt${QTVnodot}+\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()
            if(FILE_CONTENTS MATCHES "/\\*2on_Qt${QTVnodot}\\+\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*2on_Qt${QTVnodot}\\+\\*/\n" "2off_Qt${QTVnodot}+*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()

            if(Qt6_VERSION VERSION_EQUAL 6.4)

                # pragma ComponentBehavior causes issues with Qt 6.4 (and isn't supported before)
                if(FILE_CONTENTS MATCHES "pragma ComponentBehavior: Bound")
                    string(REPLACE "pragma ComponentBehavior: Bound" "/*Qt64:pragma/ComponentBehavior:/Bound*/" FILE_CONTENTS "${FILE_CONTENTS}")
                endif()

                # Qt 6.4 struggles with properties of type list somewhat randomly
                # Replacing them all by var keeps the code working and avoids any issues
                if(FILE_CONTENTS MATCHES "list\\<")
                    set(anything_changed TRUE)
                    string(REPLACE "property list<int>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<string>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<double>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<real>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<var>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<bool>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<point>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<PQMenu>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<PQButton>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<PQButtonElement>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<PQComboBox>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    string(REPLACE "property list<PQSliderSpinBox>" "property var" FILE_CONTENTS "${FILE_CONTENTS}")
                    # a list<string> is used in a few places as type in function definitions
                    string(REPLACE ": list<string>" ": var" FILE_CONTENTS "${FILE_CONTENTS}")
                endif()

            endif()

            if(anything_changed)
                if(_WITH_ADAPTSOURCE)
                    file(WRITE ${QMLFILE} "${FILE_CONTENTS}")
                else()
                    message("File to be changed: ${QMLFILE}")
                    message(FATAL_ERROR "Error: Source files are not adapted for Qt older than ${QTV}. You need to enable the WITH_ADAPTSOURCE option to automatically convert them!")
                endif()
            endif()

        endforeach()

    else()

        # we potentially need to undo some of the changes done above for Qt 6.4 specific code
        foreach(QMLFILE ${photoqt_QML})

            file(READ ${QMLFILE} FILE_CONTENTS)

            set(anything_changed FALSE)

            # switch off Qt 6.x- specific code
            if(FILE_CONTENTS MATCHES "/\\*1on_Qt${QTVnodotMINUS1}\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*1on_Qt${QTVnodotMINUS1}\\*/\n" "/*1off_Qt${QTVnodotMINUS1}\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()
            if(FILE_CONTENTS MATCHES "/\\*2on_Qt${QTVnodotMINUS1}\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*2on_Qt${QTVnodotMINUS1}\\*/\n" "2off_Qt${QTVnodotMINUS1}*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()

            # switch on Qt 6.x specific code
            if(FILE_CONTENTS MATCHES "/\\*1off_Qt${QTVnodot}\\+")
                set(anything_changed TRUE)
                string(REGEX REPLACE "/\\*1off_Qt${QTVnodot}\\+\n" "/*1on_Qt${QTVnodot}+*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()
            if(FILE_CONTENTS MATCHES "2off_Qt${QTVnodot}\\+\\*/")
                set(anything_changed TRUE)
                string(REGEX REPLACE "2off_Qt${QTVnodot}\\+\\*/\n" "/*2on_Qt${QTVnodot}+*/\n" FILE_CONTENTS "${FILE_CONTENTS}")
            endif()

            if(anything_changed)
                if(_WITH_ADAPTSOURCE)
                    file(WRITE ${QMLFILE} "${FILE_CONTENTS}")
                else()
                    message("File to be changed: ${QMLFILE}")
                    message(FATAL_ERROR "Error: Source files were prepared for Qt older than ${QTV} and are not adapted for Qt ${QTV} and above. You need to enable the WITH_ADAPTSOURCE option to automatically convert them!")
                endif()
            endif()

        endforeach()

    endif()

endforeach()


########################
#### QT SETUP STUFF ####
########################

qt_standard_project_setup(REQUIRES 6.4)

qt_add_resources(photoqt_SOURCES misc/misc.qrc img/img.qrc img/filetypes.qrc python/python.qrc ${CMAKE_BINARY_DIR}/extensions.qrc)

# Add Qt Designer files (currently only one, not likely to change anytime soon)
qt_wrap_ui(photoqt_HEADER_ui cplusplus/other/startuphandler/pqc_wizard.ui)
set(photoqt_SOURCES ${photoqt_SOURCES} ${photoqt_HEADER_ui})


#############################
#### Add the executable ####
#############################

if(WIN32)
    qt_add_executable(photoqt ${photoqt_SOURCES} windowsicons.rc)
else()
    qt_add_executable(photoqt ${photoqt_SOURCES})
endif()

# ensure that the QTP0001 policy is set to NEW otherwise the QML files will not be found on import (on Qt 6.8+)
if(QT_KNOWN_POLICY_QTP0001)
    qt_policy(SET QTP0001 "NEW")
endif()
# disable warning with this policy not being set (on Qt 6.8+)
if(QT_KNOWN_POLICY_QTP0004)
    qt_policy(SET QTP0004 "OLD")
endif()

# we need to mark the singletons BEFORE adding the qml module
set_source_files_properties(${photoqt_QML_SINGLETONS} PROPERTIES QT_QML_SINGLETON_TYPE TRUE)

# add qml files
qt_add_qml_module(photoqt URI PhotoQt VERSION 1.0 QML_FILES ${photoqt_QML})

###########################

# set the version number
target_compile_definitions(photoqt PRIVATE PQMVERSION="${APPVERSION}")

# set header files as include files
target_include_directories(photoqt PRIVATE "cplusplus/header")
target_include_directories(photoqt PRIVATE "cplusplus/header/scripts")
target_include_directories(photoqt PRIVATE "cplusplus/extensions")
target_include_directories(photoqt PRIVATE "cplusplus/images/plugins")

# set some properties for executable
set_target_properties(photoqt PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER photoqt.PhotoQt.org
    MACOSX_BUNDLE_BUNDLE_VERSION "${APPVERSION}"
    MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPVERSION}"
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

# link executable
target_link_libraries(photoqt PRIVATE Qt6::Quick Qt6::Widgets Qt6::Sql Qt6::Core
                                      Qt6::Svg Qt6::Concurrent Qt6::Multimedia
                                      Qt6::PrintSupport Qt6::DBus)

if(_WITH_QTPDF)
    target_link_libraries(photoqt PRIVATE Qt6::Pdf)
endif()

if(NOT _WITH_PUGIXML)
    target_link_libraries(photoqt PRIVATE Qt6::Xml)
endif()

###############################
#### ADDITIONAL QT OPTIONS ####
###############################

# Since Python might be imported we have to avoid using Qt keywords (like 'slots') to avoid naming conflicts
target_compile_definitions(photoqt PRIVATE QT_NO_KEYWORDS)

# we always want to capture debug/log context information
target_compile_definitions(photoqt PRIVATE QT_MESSAGELOGCONTEXT)

if(_WITHOUT_ICU)
    message("** Configured WITHOUT ICU support")
    target_compile_definitions(photoqt PRIVATE PQMWITHOUTICU)
endif()

##############################################
#### COMPOSE THE APPROPRIATE DESKTOP FILE ####
##############################################

include("CMake/ComposeDesktopFile.cmake")
composeDesktopFile()

######################
#### TRANSLATIONS ####
######################

# the compiled translations are automatically embedded as resource in executable
file(GLOB files "lang/*.ts")
qt_add_translations(photoqt TS_FILES ${files} RESOURCE_PREFIX "/lang")

########################
#### CUSTOM OPTIONS ####
########################

SET(STATUS_FORMATS_ENABLED "")
SET(STATUS_FORMATS_DISABLED "")
SET(STATUS_FORMATS_FAILED "")
SET(STATUS_ENABLED "")
SET(STATUS_DISABLED "")
set(STATUS_FAILED "")

if(_WITH_IMAGEMAGICK)
    list(APPEND STATUS_FORMATS_ENABLED "ImageMagick ${ImageMagick_VERSION_STRING}")
    # These checks are necessary to "fix" compiling PhotoQt with both ImageMagick 6 and 7 available
    if(ImageMagick_VERSION_STRING MATCHES "^7")
        string(REPLACE "libMagick++-6." "libMagick++-7." ImageMagick_LIBRARIES "${ImageMagick_LIBRARIES}")
        string(REPLACE "ImageMagick-6" "ImageMagick-7" ImageMagick_INCLUDE_DIRS "${ImageMagick_INCLUDE_DIRS}")
    endif()
    target_compile_definitions(photoqt PRIVATE PQMIMAGEMAGICK)
    target_link_libraries(photoqt PRIVATE ImageMagick::Magick++)
else()
    if(WITH_IMAGEMAGICK)
        list(APPEND STATUS_FORMATS_FAILED "ImageMagick")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "ImageMagick")
    endif()
endif()

if(_WITH_GRAPHICSMAGICK)
    list(APPEND STATUS_FORMATS_ENABLED "Graphicsmagick")
    target_include_directories(photoqt PRIVATE "${MAGICK++_INCLUDE_DIR}")
    target_compile_definitions(photoqt PRIVATE PQMGRAPHICSMAGICK)
    target_link_libraries(photoqt PRIVATE "GraphicsMagick++")
else()
    if(WITH_GRAPHICSMAGICK)
        list(APPEND STATUS_FORMATS_FAILED "GraphicsMagick")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "GraphicsMagick")
    endif()
endif()

if(_WITH_LIBRAW)
    list(APPEND STATUS_FORMATS_ENABLED "LibRaw")
    target_compile_definitions(photoqt PRIVATE PQMRAW)
    target_include_directories(photoqt PRIVATE "${LibRaw_INCLUDE_DIR}")
    target_link_libraries(photoqt PRIVATE ${LibRaw_LIBRARIES})
else()
    if(WITH_LIBRAW)
        list(APPEND STATUS_FORMATS_FAILED "LibRaw")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "LibRaw")
    endif()
endif()

if(_WITH_DEVIL)
    list(APPEND STATUS_FORMATS_ENABLED "DevIL")
    target_compile_definitions(photoqt PRIVATE PQMDEVIL)
    target_link_libraries(photoqt PRIVATE DevIL::IL)
else()
    if(WITH_DEVIL)
        list(APPEND STATUS_FORMATS_FAILED "DevIL")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "DevIL")
    endif()
endif()

if(_WITH_POPPLER)
    list(APPEND STATUS_FORMATS_ENABLED "Poppler ${Poppler_VERSION}")
    target_include_directories(photoqt PRIVATE "${Poppler_INCLUDE_DIRS}")
    target_compile_definitions(photoqt PRIVATE PQMPOPPLER)
    target_link_libraries(photoqt PRIVATE ${Poppler_LIBRARIES})
else()
    if(WITH_POPPLER)
        list(APPEND STATUS_FORMATS_FAILED "Poppler")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "Poppler")
    endif()
endif()

if(_WITH_QTPDF)
    list(APPEND STATUS_FORMATS_ENABLED "QtPDF module")
    target_compile_definitions(photoqt PRIVATE PQMQTPDF)
else()
    if(WITH_QTPDF)
        list(APPEND STATUS_FORMATS_FAILED "QtPDF module")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "QtPDF module")
    endif()
endif()

if(_WITH_LIBARCHIVE)
    list(APPEND STATUS_FORMATS_ENABLED "LibArchive ${LibArchive_VERSION}")
    target_compile_definitions(photoqt PRIVATE PQMLIBARCHIVE)
    target_link_libraries(photoqt PRIVATE LibArchive::LibArchive)
else()
    if(WITH_LIBARCHIVE)
        list(APPEND STATUS_FORMATS_FAILED "LibArchive")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "LibArchive")
    endif()
endif()

if(_WITH_VIDEO_QT)
    list(APPEND STATUS_FORMATS_ENABLED "Qt video module")
    target_compile_definitions(photoqt PRIVATE PQMVIDEOQT)
else()
    if(WITH_VIDEO_QT)
        list(APPEND STATUS_FORMATS_FAILED "Qt video module")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "Qt video module")
    endif()
endif()

if(_WITH_VIDEO_MPV)
    list(APPEND STATUS_FORMATS_ENABLED "libmpv ${Libmpv_VERSION}")
    target_compile_definitions(photoqt PRIVATE PQMVIDEOMPV)
    target_link_libraries(photoqt PRIVATE Libmpv::Libmpv)
else()
    if(WITH_VIDEO_MPV)
        list(APPEND STATUS_FORMATS_FAILED "libmpv")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "libmpv")
    endif()
endif()

if(_WITH_JPEG2000_WORKAROUNDS)
    list(APPEND STATUS_FORMATS_ENABLED "JPEG-2000 workarounds")
    target_compile_definitions(photoqt PRIVATE PQMJPEG2000WORKAROUNDS)
else()
    if(WITH_JPEG2000_WORKAROUNDS)
        list(APPEND STATUS_FORMATS_FAILED "JPEG-2000 workarounds")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "JPEG-2000 workarounds")
    endif()
endif()

if(_WITH_LIBVIPS)
    list(APPEND STATUS_FORMATS_ENABLED "libvips")
    target_include_directories(photoqt PRIVATE "${GLIB_INCLUDE_DIRS}")
    target_compile_definitions(photoqt PRIVATE PQMLIBVIPS)
    target_link_libraries(photoqt PRIVATE "${GLIB_LIBRARIES}" "vips" "gobject-2.0" "vips-cpp")
else()
    if(WITH_LIBVIPS)
        list(APPEND STATUS_FORMATS_FAILED "libvips")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "libvips")
    endif()
endif()

if(_WITH_RESVG)
    list(APPEND STATUS_FORMATS_ENABLED "resvg")
    target_link_libraries(photoqt PRIVATE "resvg")
    target_compile_definitions(photoqt PRIVATE PQMRESVG)
else()
    if(WITH_RESVG)
        list(APPEND STATUS_FORMATS_FAILED "resvg")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "resvg")
    endif()
endif()

if(_WITH_LIBSAI)
    list(APPEND STATUS_FORMATS_ENABLED "libsai")
    target_include_directories(photoqt PRIVATE "${Libsai_INCLUDE_DIR}")
    target_compile_definitions(photoqt PRIVATE PQMLIBSAI)
    target_link_libraries(photoqt PRIVATE "sai")
else()
    if(WITH_LIBSAI)
        list(APPEND STATUS_FORMATS_FAILED "libsai")
    else()
        list(APPEND STATUS_FORMATS_DISABLED "libsai")
    endif()
endif()

if(_WITH_EXTENSIONS_SUPPORT)

    list(APPEND STATUS_ENABLED "Extensions (yaml-cpp)")

    target_compile_definitions(photoqt PRIVATE PQMINSTALLPREFIX="${CMAKE_INSTALL_PREFIX}")
    target_compile_definitions(photoqt PRIVATE PQMBUILDDIR="${CMAKE_BINARY_DIR}")
    target_compile_definitions(photoqt PRIVATE PQMEXTENSIONS)

    # This avoids hardcoding 'lib' as subdir for the shared libraries
    include(GNUInstallDirs)
    target_compile_definitions(photoqt PRIVATE PQMSHAREDLIBDIR="${CMAKE_INSTALL_LIBDIR}")

    if(TARGET yaml-cpp::yaml-cpp)
        target_link_libraries(photoqt PRIVATE yaml-cpp::yaml-cpp)
    else()
        target_link_libraries(photoqt PRIVATE yaml-cpp)
    endif()
else()
    if(WITH_EXTENSIONS_SUPPORT)
        list(APPEND STATUS_FAILED "Extensions (yaml-cpp)")
    else()
        list(APPEND STATUS_DISABLED "Extensions (yaml-cpp)")
    endif()
endif()

if(_WITH_EXTENSIONS_NONSYS_OPENSSL)

    list(APPEND STATUS_ENABLED "Non-system extensions verification (OpenSSL)")

    target_compile_definitions(photoqt PRIVATE PQMEXTENSIONS_NONSYS_OPENSSL)
    if(TARGET OpenSSL::Crypto)
        target_link_libraries(photoqt PRIVATE OpenSSL::Crypto)
        target_link_libraries(photoqt PRIVATE OpenSSL::SSL)
    else()
         target_link_libraries(photoqt PRIVATE ${OPENSSL_LIBRARIES})
    endif()

    if(_WITH_EXTENSIONS_LIBRARY_VERIFICATION)
        target_compile_definitions(photoqt PRIVATE PQMEXTENSIONS_NONSYS_LIBRARYVERIFICATION)
    endif()

else()
    if(WITH_EXTENSIONS_NONSYS_OPENSSL)
        list(APPEND STATUS_FAILED "Non-system extensions verification (OpenSSL)")
    else()
        list(APPEND STATUS_DISABLED "Non-system extensions verification (OpenSSL)")
    endif()
endif()

if(_WITH_EXIV2)
    list(APPEND STATUS_ENABLED "Exiv2 ${exiv2_VERSION}")
    target_compile_definitions(photoqt PRIVATE PQMEXIV2)
    target_link_libraries(photoqt PRIVATE "exiv2lib")
    if(_WITH_EXIV2_ENABLE_BMFF)
        target_compile_definitions(photoqt PRIVATE PQMEXIV2_ENABLE_BMFF)
    endif()
    if(WIN32)
        target_compile_definitions(photoqt PRIVATE NOMINMAX)
    endif()
    # if exiv2 0.27.x is used some c++ features removed in c++17 need to be re-enabled
    if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
        if(${exiv2_VERSION} MATCHES "^0\.27\.")
            message("** Enabling C++ features removed in C++17 for Exiv2 0.27.x")
            message("** Please update Exiv2 to at least 0.28.x!")
            target_compile_definitions(photoqt PRIVATE _HAS_AUTO_PTR_ETC=1)
        endif()
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        if(${exiv2_VERSION} MATCHES "^0\.27\.")
            message("** Enabling C++ features removed in C++17 for Exiv2 0.27.x")
            message("** Please update Exiv2 to at least 0.28.x!")
            add_definitions(-fpermissive)
        endif()
    endif()
else()
    if(WITH_EXIV2)
        list(APPEND STATUS_FAILED "Exiv2")
    else()
        list(APPEND STATUS_DISABLED "Exiv2")
    endif()
endif()

if(_WITH_PUGIXML)
    list(APPEND STATUS_ENABLED "pugixml")
    target_compile_definitions(photoqt PRIVATE PQMPUGIXML)
    target_link_libraries(photoqt PRIVATE pugixml::pugixml)
else()
    if(WITH_PUGIXML)
        list(APPEND STATUS_FAILED "pugixml")
    else()
        list(APPEND STATUS_DISABLED "pugixml")
    endif()
endif()

if(_WITH_FFMPEGTHUMBNAILER)
    list(APPEND STATUS_ENABLED "ffmpegthumbnailer API")
    target_compile_definitions(photoqt PRIVATE PQMFFMPEGTHUMBNAILER)
    target_link_libraries(photoqt PRIVATE ffmpegthumbnailer)
else()
    if(WITH_FFMPEGTHUMBNAILER)
        list(APPEND STATUS_FAILED "ffmpegthumbnailer API")
    else()
        list(APPEND STATUS_DISABLED "ffmpegthumbnailer API")
    endif()
endif()

if(_WITH_ZXING)
    list(APPEND STATUS_ENABLED "ZXing ${ZXing_VERSION}")
    if(EXISTS ${ZXINGQTINC})
        target_compile_definitions(photoqt PRIVATE PQMZXINGQT)
    else()
        target_compile_definitions(photoqt PRIVATE PQMZXING)
    endif()
    target_link_libraries(photoqt PRIVATE ZXing::ZXing)
else()
    if(WITH_ZXING)
        list(APPEND STATUS_FAILED "ZXing")
    else()
        list(APPEND STATUS_DISABLED "ZXing")
    endif()
endif()

if(_WITH_CHROMECAST)
    execute_process(COMMAND ${Python3_EXECUTABLE} -c "import pychromecast" RESULT_VARIABLE EXIT_CODE OUTPUT_QUIET TIMEOUT 60)
    if(NOT ${EXIT_CODE} EQUAL 0)
        if(_WITH_CHROMECAST_PIPINSTALL)
            # try installing it with pip
            message(">> Attempt to install pychromecast locally using pip...")
            execute_process(COMMAND ${Python3_EXECUTABLE} -m pip install pychromecast)
            execute_process(COMMAND ${Python3_EXECUTABLE} -c "import pychromecast" RESULT_VARIABLE EXIT_CODE OUTPUT_QUIET TIMEOUT 60)
            if(NOT ${EXIT_CODE} EQUAL 0)
                message("** Unable to locate Python3 module pychromecast. Please first install it before re-enabling Chromecast support.")
                SET(_WITH_CHROMECAST OFF)
            else()
                message(">> Success!")
            endif()
        else()
            message("** Unable to import PyChromecast, make sure it is installed before re-enabling Chromecast support.")
            message("** Enabling the WITH_CHROMECAST_PIPINSTALL option allows CMake to try to install it locally using pip.")
            SET(_WITH_CHROMECAST OFF)
        endif()
    endif()
    # it might have been disabled in the checks above
    if(_WITH_CHROMECAST)
        list(APPEND STATUS_ENABLED "Chromecast (Python ${Python3_VERSION})")
        target_compile_definitions(photoqt PRIVATE PQMCHROMECAST)
        target_include_directories(photoqt PRIVATE "${Python3_INCLUDE_DIRS}")
        target_link_libraries(photoqt PRIVATE ${Python3_LIBRARIES})
    endif()
else()
    if(WITH_CHROMECAST)
        list(APPEND STATUS_FAILED "Chromecast (Python)")
    else()
        list(APPEND STATUS_DISABLED "Chromecast (Python)")
    endif()
endif()

if(_WITH_LOCATION)
    list(APPEND STATUS_ENABLED "QtLocation/QtPosition")
    target_compile_definitions(photoqt PRIVATE PQMLOCATION)
else()
    if(WITH_LOCATION)
        list(APPEND STATUS_FAILED "QtLocation/QtPosition")
    else()
        list(APPEND STATUS_DISABLED "QtLocation/QtPosition")
    endif()
endif()

if(_WITH_LCMS2)
    list(APPEND STATUS_ENABLED "LCMS2 ${LCMS2_VERSION}")
    target_include_directories(photoqt PRIVATE "${LCMS2_INCLUDE_DIR}")
    target_compile_definitions(photoqt PRIVATE PQMLCMS2)
    target_link_libraries(photoqt PRIVATE ${LCMS2_LIBRARIES})
else()
    if(WITH_LCMS2)
        list(APPEND STATUS_FAILED "LCMS2")
    else()
        list(APPEND STATUS_DISABLED "LCMS2")
    endif()
endif()

if(_WITH_MOTIONPHOTO)
    list(APPEND STATUS_ENABLED "Motion photos and Apple live photos")
    target_compile_definitions(photoqt PRIVATE PQMMOTIONPHOTO)
else()
    if(WITH_MOTIONPHOTO)
        list(APPEND STATUS_FAILED "Motion photos and Apple live photos")
    else()
        list(APPEND STATUS_DISABLED "Motion photos and Apple live photos")
    endif()
endif()

if(_WITH_PHOTOSPHERE)
    list(APPEND STATUS_ENABLED "Photo spheres")
    target_compile_definitions(photoqt PRIVATE PQMPHOTOSPHERE)
    if(_WITH_PHOTOSPHERE_QRHI)
        target_link_libraries(photoqt PRIVATE Qt6::GuiPrivate)
        target_compile_definitions(photoqt PRIVATE PQMPHOTOSPHEREQRHI)
    endif()
else()
    if(WITH_PHOTOSPHERE)
        list(APPEND STATUS_FAILED "Photo spheres")
    else()
        list(APPEND STATUS_DISABLED "Photo spheres")
    endif()
endif()

if(_WITH_FLATPAKBUILD)
    list(APPEND STATUS_ENABLED "Flatpak workarounds")
    target_compile_definitions(photoqt PRIVATE PQMFLATPAKBUILD)
    target_include_directories(photoqt PRIVATE "${GLIB_INCLUDE_DIRS}")
    target_link_libraries(photoqt PRIVATE "${GLIB_LIBRARIES}" "gobject-2.0" "gio-2.0")
else()
    if(WITH_FLATPAKBUILD)
        list(APPEND STATUS_FAILED "Flatpak workarounds")
    else()
        list(APPEND STATUS_DISABLED "Flatpak workarounds")
    endif()
endif()

if(_WITH_APPIMAGEBUILD)
    list(APPEND STATUS_ENABLED "AppImage workarounds")
    target_compile_definitions(photoqt PRIVATE PQMAPPIMAGEBUILD)
else()
    if(WITH_APPIMAGEBUILD)
        list(APPEND STATUS_FAILED "AppImage workarounds")
    else()
        list(APPEND STATUS_DISABLED "AppImage workarounds")
    endif()
endif()

if(_WITH_PORTABLETWEAKS)
    list(APPEND STATUS_ENABLED "Portable tweaks (do not use unless you know what you are doing!)")
    target_compile_definitions(photoqt PRIVATE PQMPORTABLETWEAKS)
else()
    if(WITH_PORTABLETWEAKS)
        list(APPEND STATUS_FAILED "Portable tweaks (leave disabled unless you know what you are doing!)")
    else()
        list(APPEND STATUS_DISABLED "Portable tweaks (leave disabled unless you know what you are doing!)")
    endif()
endif()

if(_WITH_WAYLANDSPECIFIC)
    list(APPEND STATUS_ENABLED "Wayland-specific code")
    target_compile_definitions(photoqt PRIVATE PQMWAYLANDSPECIFIC)
    target_link_libraries(photoqt PRIVATE Wayland::Client)
else()
    if(WITH_WAYLANDSPECIFIC)
        list(APPEND STATUS_FAILED "Wayland-specific code")
    else()
        list(APPEND STATUS_DISABLED "Wayland-specific code")
    endif()
endif()

message("")
message("** The following options are enabled for this build:")
message("")
foreach(opt IN LISTS STATUS_FORMATS_ENABLED)
    message("    - ${opt}")
endforeach()
message("")
foreach(opt IN LISTS STATUS_ENABLED)
    message("    - ${opt}")
endforeach()
message("")

message("")
message("")
message("** The following options are DISABLED for this build:")
message("")
foreach(opt IN LISTS STATUS_FORMATS_DISABLED)
    message("    - ${opt}")
endforeach()
message("")
foreach(opt IN LISTS STATUS_DISABLED)
    message("    - ${opt}")
endforeach()
message("")

list(LENGTH STATUS_FAILED failedlength)
if(failedlength GREATER 0)
    message("")
    message("")
    message("** The following options FAILED to be ENABLED for this build:")
    message("")
    foreach(opt IN LISTS STATUS_FAILED)
        message("    - ${opt}")
    endforeach()
    message("")
endif()


if(_WITH_EXTENSIONS_SUPPORT)
    message("")
    message("##############################################################################################")
    message("##############################################################################################")
    message("")
    message("** Note that the extensions are not built with PhotoQt and need to be built separately.")
    message("** For more information check the extensions repository: https://gitlab.com/lspies/photoqt-extensions")
    message("")
    message("##############################################################################################")
    message("##############################################################################################")
    message("")
endif()

#############################
#### ENABLE UNIT TESTING ####
#############################

if(_WITH_TESTING)
    enable_testing()
    add_subdirectory(testing)
endif()


#######################
#### INSTALL FILES ####
#######################

if(UNIX)

    # Install executable
    install(
        TARGETS photoqt
        DESTINATION ${CMAKE_INSTALL_BINDIR}
    )

    # Install desktop file
    install(
        FILES org.photoqt.PhotoQt.desktop
        DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
    )

    # And install all the icons
    install(
        FILES icons/16x16/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/16x16/apps/
    )
    install(
        FILES icons/32x32/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/32x32/apps/
    )
    install(
        FILES icons/48x48/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/48x48/apps/
    )
    install(
        FILES icons/64x64/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/64x64/apps/
    )
    install(
        FILES icons/128x128/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/128x128/apps/
    )
    install(
        FILES icons/256x256/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps/
    )
    install(
        FILES icons/512x512/org.photoqt.PhotoQt.png
        DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/512x512/apps/
    )
    # the max allowed icon size for flathub is 512x512
    if(NOT _WITH_FLATPAKBUILD)
        install(
            FILES icons/1024x1024/org.photoqt.PhotoQt.png
            DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/1024x1024/apps/
        )
    endif()
    install(
        FILES org.photoqt.PhotoQt.metainfo.xml
        DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo/
    )

else()

    # automatically install all dependencies
    install(TARGETS photoqt
        RUNTIME_DEPENDENCIES
        DIRECTORIES "${IMAGEMAGICK_ROOT_DIR}" "${QT_ROOT_DIR}/bin"
        PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-"
        POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
        BUNDLE  DESTINATION .
        RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}
    )

    # call windeployqt
    if(DEFINED WINDEPLOYQT_EXECUTABLE AND DEFINED EXTENSIONS_ROOT_DIR)
        install(CODE "execute_process(COMMAND \"${WINDEPLOYQT_EXECUTABLE}\" --qmldir ${CMAKE_SOURCE_DIR}/qml/  --qmldir \"${EXTENSIONS_ROOT_DIR}\" --release ${CMAKE_INSTALL_PREFIX}/photoqt.exe)")
    else()
        message(" ** Need variables WINDEPLOYQT_EXECUTABLE and EXTENSIONS_ROOT_DIR to call windeployqt directly")
    endif()

endif()


##########################
#### UNINSTALL TARGET ####
##########################

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
