From f6b672cfb0d10b2bc4a5fcb01d09126b97f8dbd7 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Wed, 12 Aug 2026 18:26:57 +0000
Subject: [PATCH 4/4] Qt4: add WITH_QT4 CMake build path

Adds a WITH_QT4 option (default OFF, so the existing Qt6 build is
unchanged) that switches the build over to Qt4, for platforms where
Qt5/6 aren't available (e.g. macOS PowerPC via MacPorts).

- ProjectDependencies.cmake: find_package(Qt4) instead of Qt6, skipping
  the Qt6-only QPA platform-plugin property lookups (Qt4 predates the
  QPA model, so they don't apply).
- ProjectExternals.cmake: qt-solutions' own CMakeLists.txt
  (CMakeLists_qt-solutions.cmake.in) hardcodes Qt6, so under Qt4 locate
  the prebuilt MacPorts devel/qtsingleapplication-qt4 port instead
  (find_path/find_library against the Qt4 kit's own include/lib dirs)
  and expose it as the same qt-solutions::qtsingleapplication imported
  target used by src/CMakeLists.txt either way.
- src/CMakeLists.txt: link Qt4::QtCore/QtGui/QtNetwork (Widgets and
  StateMachine are bundled into those under Qt4) instead of the Qt6
  targets, and skip the whole bundle/fixup_bundle step, which relies
  on Qt6-only QPA plugin targets and isn't needed for a package-manager
  build that links the system Qt4 frameworks directly (the same model
  the historical qmake-based v1.3 build used).

No JSON usage exists anywhere in this codebase, so qjson4 (also
suggested as a MacPorts dependency) isn't needed.

Note for whoever builds this: CMake's bundled FindQt4 module was
removed from mainline CMake (~3.24+); this path needs an older CMake
that still ships it, or a vendored replacement. Not addressed here
since it's an environment concern, not a code one.

Part of Qt4 buildability work for the macOS PowerPC port.
---
 CMake/Includes/ProjectDependencies.cmake | 37 +++++++++++++++---------
 CMake/Includes/ProjectExternals.cmake    | 28 +++++++++++++++++-
 CMake/Includes/ProjectSettings.cmake     |  2 ++
 src/CMakeLists.txt                       | 31 ++++++++++++++++----
 4 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/CMake/Includes/ProjectDependencies.cmake b/CMake/Includes/ProjectDependencies.cmake
index 8d04a62..e39d548 100644
--- a/CMake/Includes/ProjectDependencies.cmake
+++ b/CMake/Includes/ProjectDependencies.cmake
@@ -3,21 +3,30 @@ set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTORCC ON)
 
-find_package(Qt6 6.0 REQUIRED COMPONENTS Core Gui Widgets Network StateMachine)
-if(MINGW)
-    get_target_property(_qwindows_dll Qt6::QWindowsIntegrationPlugin LOCATION)
-    if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.7")
-        get_target_property(_qwinstyle_dylib Qt6::QModernWindowsStylePlugin LOCATION)
-    elseif(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0")
-        get_target_property(_qwinstyle_dylib Qt6::QWindowsVistaStylePlugin LOCATION)
-    endif()
+if(WITH_QT4)
+    # Qt4 is the last Qt version available on legacy platforms such as
+    # macOS PowerPC (via MacPorts). QStateMachine lives in QtCore there
+    # (it wasn't split into its own module until Qt5), and Qt4 predates
+    # the QPA platform-plugin model entirely, so none of the Qt6
+    # plugin-property lookups below are applicable.
+    find_package(Qt4 4.8 REQUIRED COMPONENTS QtCore QtGui QtNetwork)
+else()
+    find_package(Qt6 6.0 REQUIRED COMPONENTS Core Gui Widgets Network StateMachine)
+    if(MINGW)
+        get_target_property(_qwindows_dll Qt6::QWindowsIntegrationPlugin LOCATION)
+        if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.7")
+            get_target_property(_qwinstyle_dylib Qt6::QModernWindowsStylePlugin LOCATION)
+        elseif(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0")
+            get_target_property(_qwinstyle_dylib Qt6::QWindowsVistaStylePlugin LOCATION)
+        endif()
 
-    get_target_property(_schannel_dll Qt6::QSchannelBackendPlugin LOCATION)
-endif()
-if(APPLE)
-    get_target_property(_qcocoa_dylib Qt6::QCocoaIntegrationPlugin LOCATION)
-    if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0")
-        get_target_property(_qmacstyle_dylib Qt6::QMacStylePlugin LOCATION)
+        get_target_property(_schannel_dll Qt6::QSchannelBackendPlugin LOCATION)
+    endif()
+    if(APPLE)
+        get_target_property(_qcocoa_dylib Qt6::QCocoaIntegrationPlugin LOCATION)
+        if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0")
+            get_target_property(_qmacstyle_dylib Qt6::QMacStylePlugin LOCATION)
+        endif()
     endif()
 endif()
 
diff --git a/CMake/Includes/ProjectExternals.cmake b/CMake/Includes/ProjectExternals.cmake
index c5ed632..4f807e2 100644
--- a/CMake/Includes/ProjectExternals.cmake
+++ b/CMake/Includes/ProjectExternals.cmake
@@ -36,7 +36,33 @@ if(NOT spdlog_FOUND)
     include(ProjectExternals_spdlog)
 endif()
 
-include(ProjectExternals_qt-solutions)
+if(WITH_QT4)
+    # qt-solutions' own CMakeLists.txt (CMakeLists_qt-solutions.cmake.in)
+    # hardcodes Qt6, so under Qt4 use the prebuilt MacPorts
+    # devel/qtsingleapplication-qt4 port instead of building it ourselves.
+    find_path(QTSINGLEAPPLICATION_INCLUDE_DIR
+        NAMES QtSingleApplication
+        PATH_SUFFIXES QtSingleApplication
+        HINTS ${QT_INCLUDE_DIR}
+    )
+    find_library(QTSINGLEAPPLICATION_LIBRARY
+        NAMES QtSingleApplication
+        HINTS ${QT_LIBRARY_DIR}
+    )
+    if(NOT QTSINGLEAPPLICATION_INCLUDE_DIR OR NOT QTSINGLEAPPLICATION_LIBRARY)
+        message(FATAL_ERROR "Could NOT find QtSingleApplication! Install it with e.g. 'port install qtsingleapplication-qt4'")
+    endif()
+    message(STATUS "Library 'QtSingleApplication' found at ${QTSINGLEAPPLICATION_LIBRARY}")
+
+    add_library(qt-solutions::qtsingleapplication STATIC IMPORTED)
+    set_target_properties(qt-solutions::qtsingleapplication PROPERTIES
+        INTERFACE_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}"
+        IMPORTED_LOCATION "${QTSINGLEAPPLICATION_LIBRARY}"
+    )
+    mark_as_advanced(QTSINGLEAPPLICATION_INCLUDE_DIR QTSINGLEAPPLICATION_LIBRARY)
+else()
+    include(ProjectExternals_qt-solutions)
+endif()
 if(MINGW)
     if (NOT CMAKE_CROSSCOMPILING)
         include(ProjectExternals_openconnect)
diff --git a/CMake/Includes/ProjectSettings.cmake b/CMake/Includes/ProjectSettings.cmake
index f94f6b4..0e94801 100644
--- a/CMake/Includes/ProjectSettings.cmake
+++ b/CMake/Includes/ProjectSettings.cmake
@@ -1,5 +1,7 @@
 option(PROJ_GNUTLS_DEBUG "Enable GnuTLS debug mode" OFF)
 
+option(WITH_QT4 "Build against Qt4 instead of Qt6, for legacy platforms (e.g. macOS PowerPC) where Qt5/6 are unavailable" OFF)
+
 option(PROJ_ADMIN_PRIV_ELEVATION "Admin privileges elevation; don't turn it off in production!! (UAC on Windows) " ON)
 
 if(MINGW)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4e0012a..92ba07f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -160,14 +160,25 @@ endif()
 target_link_libraries (${PROJECT_NAME}
     spdlog::spdlog
     qt-solutions::qtsingleapplication
-
-    Qt6::Core
-    Qt6::Gui
-    Qt6::Widgets
-    Qt6::Network
-    Qt6::StateMachine
 )
 
+if(WITH_QT4)
+    # Widgets and StateMachine are bundled into QtGui/QtCore under Qt4.
+    target_link_libraries (${PROJECT_NAME}
+        Qt4::QtCore
+        Qt4::QtGui
+        Qt4::QtNetwork
+    )
+else()
+    target_link_libraries (${PROJECT_NAME}
+        Qt6::Core
+        Qt6::Gui
+        Qt6::Widgets
+        Qt6::Network
+        Qt6::StateMachine
+    )
+endif()
+
 if(UNIX)
     target_link_libraries(${PROJECT_NAME}
         Threads::Threads
@@ -187,6 +198,13 @@ install(TARGETS ${PROJECT_NAME}
 )
 
 # fixup the bundle
+#
+# Not applicable under Qt4: it predates the QPA platform-plugin model
+# entirely, and package-manager builds (e.g. the macOS PowerPC MacPorts
+# port) link against the system-installed Qt4 frameworks directly rather
+# than bundling a self-contained app, same as the historical qmake-based
+# v1.3 build did.
+if(NOT WITH_QT4)
 get_target_property(QT_LIBRARY_DIR Qt6::Core LOCATION)
 get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
 list(APPEND libSearchDirs ${QT_LIBRARY_DIR})
@@ -269,3 +287,4 @@ install(CODE "
     fixup_bundle(\"${APPS}\" \"${additionalLib}\" \"${libSearchDirs}\")
     " DESTINATION . COMPONENT App
 )
+endif() # NOT WITH_QT4
-- 
2.43.0

