From 19b8eaa50d465c5a2b2c7f02c94b088fdd715ff6 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Fri, 7 Aug 2026 01:21:15 +0000
Subject: [PATCH] Support Qt4

Guard the remaining Qt5-only APIs (QT += widgets/concurrent,
QComboBox::currentData(), QWheelEvent::angleDelta(), QGuiApplication::
setApplicationDisplayName()) behind QT_VERSION checks instead of
replacing them unconditionally, and link against the QtMimeTypes
backport (e.g. MacPorts port:qt4-mimetypes) on Qt4.

Add a QFileDevice compat typedef (Qt4's QFile carries the permission
flags/setPermissions() that Qt5 moved onto the new QFileDevice base
class) and the missing QUrl include in imageview.cpp, both needed for
a clean Qt4 build.

Fix color corruption on big-endian PPC: FXX generated all in-memory
previews/thumbnails as BMP before handing them to QImage::fromData().
Qt's BMP reader decodes the raw DIB pixel array with host-endian
assumptions that break on big-endian systems. Switch to PNG, which
(like the TIFF format used by the pre-refactor 1.0.0 codebase) is
explicitly byte-order-defined and already a hard dependency of Cyan
(see tst_cyan.cpp's hasPNG() check).
---
 cyan.pro              |  9 ++++++++-
 src/FXX.cpp           |  8 ++++----
 src/compat.h          | 21 +++++++++++++++++++++
 src/cyan.cpp          |  7 ++++++-
 src/cyan.h            |  1 +
 src/helpdialog.h      |  1 +
 src/imageview.cpp     | 13 ++++++++++++-
 src/imageview.h       |  1 +
 src/main.cpp          |  2 ++
 src/openlayerdialog.h |  1 +
 src/profiledialog.h   |  1 +
 11 files changed, 58 insertions(+), 7 deletions(-)
 create mode 100644 src/compat.h

diff --git a/cyan.pro b/cyan.pro
index 218755a..dec532f 100644
--- a/cyan.pro
+++ b/cyan.pro
@@ -56,7 +56,8 @@ OBJECTS_DIR = $${DESTDIR}/.obj
 MOC_DIR = $${DESTDIR}/.moc
 RCC_DIR = $${DESTDIR}/.qrc
 
-QT += widgets concurrent
+QT += core gui
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent
 TEMPLATE = app
 
 CONFIG += c++11
@@ -78,6 +79,12 @@ isEmpty(PREFIX): PREFIX = /usr/local
 isEmpty(DOCDIR): DOCDIR = $$PREFIX/share/doc
 isEmpty(MANDIR): MANDIR = $$PREFIX/share/man
 
+lessThan(QT_MAJOR_VERSION, 5) {
+    # requires the QtMimeTypes backport library (e.g. MacPorts port:qt4-mimetypes)
+    QMAKE_CXXFLAGS += -I$${PREFIX}/include/QtMimeTypes
+    LIBS += -lQtMimeTypes
+}
+
 DEFINES += CYAN_VERSION=\"\\\"$${VERSION}$${VERSION_TYPE}\\\"\"
 DEFINES += CYAN_GIT=\"\\\"$${GIT}\\\"\"
 QMAKE_TARGET_COMPANY = "$${TARGET}"
diff --git a/src/FXX.cpp b/src/FXX.cpp
index 87c6448..b3e0ab8 100644
--- a/src/FXX.cpp
+++ b/src/FXX.cpp
@@ -119,7 +119,7 @@ FXX::Image FXX::readImage(const std::string &file,
 
         // make a preview
         if (image.depth()>8) { image.depth(8); }
-        image.magick("BMP");
+        image.magick("PNG");
         image.write(&preview);
         unsigned char *preBuffer = reinterpret_cast<unsigned char*>(const_cast<void*>(preview.data()));
         std::vector<unsigned char> preData(preBuffer, preBuffer + preview.length());
@@ -202,7 +202,7 @@ FXX::Image FXX::readImage(Magick::Image image, FXX::Image failsafe, bool getInfo
 
             // make a preview
             if (image.depth()>8) { image.depth(8); }
-            image.magick("BMP");
+            image.magick("PNG");
             image.write(&preview);
             unsigned char *preBuffer = reinterpret_cast<unsigned char*>(const_cast<void*>(preview.data()));
             std::vector<unsigned char> preData(preBuffer, preBuffer + preview.length());
@@ -227,7 +227,7 @@ std::vector<unsigned char> FXX::generateThumb(Magick::Image image, int width, in
     try {
         image.scale(Magick::Geometry(width, height));
         if (image.depth()>8) { image.depth(8); }
-        image.magick("BMP");
+        image.magick("PNG");
         Magick::Blob preview;
         image.write(&preview);
         unsigned char *preBuffer = reinterpret_cast<unsigned char*>(const_cast<void*>(preview.data()));
@@ -326,7 +326,7 @@ FXX::Image FXX::convertImage(FXX::Image input, bool getInfo)
                 image.profile("ICC", monitorProfile);
             }
             if (image.depth()>8) { image.depth(8); }
-            image.magick("BMP");
+            image.magick("PNG");
             image.write(&preview);
             unsigned char *preBuffer = reinterpret_cast<unsigned char*>(const_cast<void*>(preview.data()));
             std::vector<unsigned char> preData(preBuffer, preBuffer + preview.length());
diff --git a/src/compat.h b/src/compat.h
new file mode 100644
index 0000000..9d9a671
--- /dev/null
+++ b/src/compat.h
@@ -0,0 +1,21 @@
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#include <QFile>
+
+#if QT_VERSION < 0x050000
+// Qt4's QFile carries the permission flags/setPermissions() that Qt5 moved
+// onto the new QFileDevice base class.
+typedef QFile QFileDevice;
+#endif
+
+#ifndef Q_NULLPTR
+    #if __cplusplus >= 201103L
+        #define Q_NULLPTR nullptr
+    #else
+        // not NULL to stay consistent with Qt’s convention
+        #define Q_NULLPTR 0
+    #endif
+#endif
+
+#endif // COMPAT_H
diff --git a/src/cyan.cpp b/src/cyan.cpp
index e6d8d1a..3bdc4e0 100644
--- a/src/cyan.cpp
+++ b/src/cyan.cpp
@@ -51,8 +51,13 @@
 #include <QStyleFactory>
 #include <QHeaderView>
 #include <QMimeData>
+#if QT_VERSION < 0x050000
+#include <QtMimeTypes/QMimeDatabase>
+#include <QtMimeTypes/QMimeType>
+#else
 #include <QMimeDatabase>
 #include <QMimeType>
+#endif
 #include <QTreeWidgetItem>
 #include <qtconcurrentrun.h>
 
@@ -1570,7 +1575,7 @@ void Cyan::handleReadWatcher()
         getConvertProfiles();
         QFileInfo fileinfo(QString::fromStdString(image.filename));
         setWindowTitle(fileinfo.fileName());
-        if (!monitorProfile->currentData().toString().isEmpty()) { updateImage(); }
+        if (!monitorProfile->itemData(monitorProfile->currentIndex()).toString().isEmpty()) { updateImage(); }
     } else {
         QMessageBox::warning(this, tr("Image error"),
                              QString::fromStdString(image.error));
diff --git a/src/cyan.h b/src/cyan.h
index e2af39d..11a21e0 100644
--- a/src/cyan.h
+++ b/src/cyan.h
@@ -60,6 +60,7 @@
 #include "imageview.h"
 #include "profiledialog.h"
 #include "FXX.h"
+#include "compat.h"
 
 #define RESOURCE_BYTE 1050000000
 
diff --git a/src/helpdialog.h b/src/helpdialog.h
index 733044f..e754e8d 100644
--- a/src/helpdialog.h
+++ b/src/helpdialog.h
@@ -36,6 +36,7 @@
 #include <QDialog>
 #include <QTextBrowser>
 #include <QString>
+#include "compat.h"
 
 class HelpDialog : public QDialog
 {
diff --git a/src/imageview.cpp b/src/imageview.cpp
index 75c5cee..359591e 100644
--- a/src/imageview.cpp
+++ b/src/imageview.cpp
@@ -32,8 +32,14 @@
 
 #include "imageview.h"
 #include <QMimeData>
+#include <QUrl>
+#if QT_VERSION < 0x050000
+#include <QtMimeTypes/QMimeDatabase>
+#include <QtMimeTypes/QMimeType>
+#else
 #include <QMimeDatabase>
 #include <QMimeType>
+#endif
 #include <QSettings>
 
 ImageView::ImageView(QWidget* parent) : QGraphicsView(parent)
@@ -54,7 +60,12 @@ ImageView::ImageView(QWidget* parent) : QGraphicsView(parent)
 void ImageView::wheelEvent(QWheelEvent* event) {
     setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
     double scaleFactor = 1.15;
-    if(event->angleDelta().y() > 0) { // up
+#if QT_VERSION < 0x050000
+    int delta = event->delta();
+#else
+    int delta = event->angleDelta().y();
+#endif
+    if(delta > 0) { // up
         fit = false;
         scale(scaleFactor, scaleFactor);
         emit myZoom(scaleFactor, scaleFactor);
diff --git a/src/imageview.h b/src/imageview.h
index 29a62aa..1666cd8 100644
--- a/src/imageview.h
+++ b/src/imageview.h
@@ -40,6 +40,7 @@
 #include <QDragMoveEvent>
 #include <QDragLeaveEvent>
 #include <QResizeEvent>
+#include "compat.h"
 
 class ImageView : public QGraphicsView
 {
diff --git a/src/main.cpp b/src/main.cpp
index 480d2b8..4776961 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -43,7 +43,9 @@ int main(int argc, char *argv[])
     QApplication a(argc, argv);
     QCoreApplication::setApplicationName("Cyan");
     QCoreApplication::setOrganizationName("Cyan");
+#if QT_VERSION >= 0x050000
     QGuiApplication::setApplicationDisplayName("Cyan");
+#endif
     QCoreApplication::setOrganizationDomain("net.fxarena");
     QCoreApplication::setApplicationVersion(CYAN_VERSION);
     Cyan w;
diff --git a/src/openlayerdialog.h b/src/openlayerdialog.h
index c9cda39..c3d9a05 100644
--- a/src/openlayerdialog.h
+++ b/src/openlayerdialog.h
@@ -40,6 +40,7 @@
 #include <QLabel>
 #include <QTreeWidgetItem>
 #include "FXX.h"
+#include "compat.h"
 
 class OpenLayerDialog : public QDialog
 {
diff --git a/src/profiledialog.h b/src/profiledialog.h
index 3ec91c9..2b2348b 100644
--- a/src/profiledialog.h
+++ b/src/profiledialog.h
@@ -38,6 +38,7 @@
 #include <QPushButton>
 #include <QString>
 #include "FXX.h"
+#include "compat.h"
 
 class ProfileDialog : public QDialog
 {
-- 
2.43.0

