[qgle] migrate to Qt6
Hello.
I prepared (rude) patch to use Qt6. Below the patch itself and here the source.
From aef6ec9848619e2d2f32726165862976a1fc2594 Mon Sep 17 00:00:00 2001
From: Vladimir Lomov <[email protected]>
Date: Mon, 24 Jun 2024 13:17:17 +0800
Subject: [PATCH 3/3] Migrate GUI to Qt6
Signed-off-by: Vladimir Lomov <[email protected]>
---
src/gui/3dviewer.cpp | 17 +++++++++--------
src/gui/3dviewer.h | 4 ++--
src/gui/CMakeLists.txt | 18 +++++++++++-------
src/gui/about.cpp | 2 +-
src/gui/dialogues.cpp | 9 +++++----
src/gui/mainwindow.cpp | 4 ++--
src/gui/objectblocks.cpp | 3 ++-
src/gui/qgle_statics.cpp | 17 ++++++++++-------
src/gui/qgle_statics.h | 1 +
src/gui/qgs.cpp | 6 +++---
src/gui/serverthread.cpp | 3 ++-
11 files changed, 48 insertions(+), 36 deletions(-)
diff --git a/src/gui/3dviewer.cpp b/src/gui/3dviewer.cpp
index 6132418..25eec7f 100644
--- a/src/gui/3dviewer.cpp
+++ b/src/gui/3dviewer.cpp
@@ -21,6 +21,7 @@
#include <QtGui>
#include <QtOpenGL>
+#include <QOpenGLWidget>
#include "3dviewer.h"
#include "../config.h"
#include "../gle/cutils.h"
@@ -38,7 +39,7 @@
#include <math.h>
QGLE3DWidget::QGLE3DWidget(QWidget *parent, GLEInterface* iface)
- : QGLWidget(parent)
+ : QOpenGLWidget(parent)
{
gleInterface = iface;
object = 0;
@@ -72,34 +73,34 @@ QSize QGLE3DWidget::sizeHint() const
void QGLE3DWidget::zoom(double zoom) {
proj.zoom(zoom);
- updateGL();
+ update();
}
void QGLE3DWidget::rotate(double angle, bool horiz) {
proj.rotate(angle, horiz);
- updateGL();
+ update();
}
void QGLE3DWidget::reference(const GLEPoint3D& p) {
proj.reference(p);
- updateGL();
+ update();
}
void QGLE3DWidget::adjustV(double angle) {
proj.adjustV(angle);
- updateGL();
+ update();
}
void QGLE3DWidget::perspectiveAngle(double delta) {
perspAngle += delta;
if (perspAngle < 5) perspAngle = 5;
if (perspAngle > 85) perspAngle = 85;
- updateGL();
+ update();
}
void QGLE3DWidget::initializeGL()
{
- qglClearColor(Qt::white);
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); /// Alternatively: QColorConstants::Svg::white
object = makeObject();
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
@@ -151,7 +152,7 @@ void QGLE3DWidget::mouseMoveEvent(QMouseEvent *event)
if (event->buttons() & Qt::LeftButton) {
proj.rotate(-dx*0.1, true);
proj.rotate(dy*0.1, false);
- updateGL();
+ update();
}
lastPos = event->pos();
}
diff --git a/src/gui/3dviewer.h b/src/gui/3dviewer.h
index 07f0c0f..c17ec6b 100644
--- a/src/gui/3dviewer.h
+++ b/src/gui/3dviewer.h
@@ -23,10 +23,10 @@
#define _3DVIEWER_H
#include <QDialog>
-#include <QGLWidget>
+#include <QOpenGLWidget>
#include "mainwindow.h"
- class QGLE3DWidget : public QGLWidget
+ class QGLE3DWidget : public QOpenGLWidget
{
Q_OBJECT
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index c5abd42..905f7b1 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,18 +1,20 @@
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#
-# -- Qt5 set Qt5_DIR
+# -- Qt6 set Qt5_DIR
#
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
-find_package(Qt5 COMPONENTS
+find_package(Qt6 COMPONENTS
Widgets
Network
DBus
Gui
OpenGL
+ OpenGLWidgets
+ Core5Compat
REQUIRED)
add_executable(qgle WIN32 MACOSX_BUNDLE
@@ -70,11 +72,13 @@ list(APPEND QGLE_LIBRARIES
${PNG_LIBRARIES}
${PIXMAN_LIBRARIES}
TIFF::TIFF
- Qt::Core
- Qt::Gui
- Qt::Network
- Qt::Widgets
- Qt::OpenGL
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Network
+ Qt6::Widgets
+ Qt6::OpenGL
+ Qt6::OpenGLWidgets
+ Qt6::Core5Compat
${CAIRO_LIBRARIES}
${CMAKE_DL_LIBS}
)
diff --git a/src/gui/about.cpp b/src/gui/about.cpp
index d21b090..9dfcc7c 100644
--- a/src/gui/about.cpp
+++ b/src/gui/about.cpp
@@ -162,7 +162,7 @@ QWidget* AboutBox::createLicensePanel()
// Get the text and put it in the label
label->setPlainText(licenseFileTxt.c_str());
QFontMetrics fm(font);
- m_minWidth = fm.width("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+ m_minWidth = fm.horizontalAdvance("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
} else {
label->setPlainText(tr("File not found: '%1'").arg(fileName));
}
diff --git a/src/gui/dialogues.cpp b/src/gui/dialogues.cpp
index ef0fef8..d0f14b8 100644
--- a/src/gui/dialogues.cpp
+++ b/src/gui/dialogues.cpp
@@ -20,6 +20,8 @@
***********************************************************************************/
#include <QtGui>
+#include <QScreen>
+#include <QRegExp>
#include "qgle_statics.h"
#include "dialogues.h"
@@ -355,8 +357,7 @@ SoftwareLocateDialogue::SoftwareLocateDialogue(GLEMainWindow *parent, GLEInterfa
layout->addLayout(top);
layout->addLayout(buttonLayout);
setLayout(layout);
- QDesktopWidget* desk = QApplication::desktop();
- QRect size = desk->screenGeometry(this);
+ QRect size = QGuiApplication::primaryScreen()->geometry();
resize(size.width()/2, size.height()/2);
connect(&output, SIGNAL(print(const QString)), this, SLOT(print(const QString)));
getGLEInterface()->setOutputStream(&output);
@@ -640,7 +641,7 @@ void CrashRecoverDialogue::viewReport()
buttonLayout->addWidget(okButton);
layout->addLayout(buttonLayout);
viewReportDial.setLayout(layout);
- QRect size = QApplication::desktop()->screenGeometry(&viewReportDial);
+ QRect size = QGuiApplication::primaryScreen()->geometry();
viewReportDial.resize(size.width()/2, size.height()/2);
viewReportDial.exec();
}
@@ -680,7 +681,7 @@ void CrashRecoverDialogue::requestFinished(int id, bool error)
buttonLayout->addWidget(okButton);
layout->addLayout(buttonLayout);
mydial.setLayout(layout);
- QRect size = QApplication::desktop()->screenGeometry(&mydial);
+ QRect size = QGuiApplication::primaryScreen()->geometry();
mydial.resize(size.width()/3, size.height()/3);
mydial.exec();
close();
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 6fd5e52..d489801 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -1985,7 +1985,7 @@ void GLEMainWindow::openGhostScriptLogDialogue()
buttonLayout->addWidget(okButton);
layout->addLayout(buttonLayout);
gsLogDialog.setLayout(layout);
- QRect size = QApplication::desktop()->screenGeometry(&gsLogDialog);
+ QRect size = QGuiApplication::primaryScreen()->geometry();
gsLogDialog.resize(size.width()/2, size.height()/2);
gsLogDialog.exec();
}
@@ -1995,7 +1995,7 @@ void GLEMainWindow::openEvaluator()
if (evaluatorDialog == NULL)
{
evaluatorDialog = new EvaluatorDialog(this);
- QRect size = QApplication::desktop()->screenGeometry(evaluatorDialog);
+ QRect size = QGuiApplication::primaryScreen()->geometry();
evaluatorDialog->resize(size.width()/3, size.height()/2);
}
evaluatorDialog->show();
diff --git a/src/gui/objectblocks.cpp b/src/gui/objectblocks.cpp
index 3559e69..15ee27f 100644
--- a/src/gui/objectblocks.cpp
+++ b/src/gui/objectblocks.cpp
@@ -19,6 +19,7 @@
* Also add information on how to contact you by electronic and paper mail. *
***********************************************************************************/
+#include <QVariant>
#include "mainwindow.h"
#include "objectblocks.h"
@@ -53,7 +54,7 @@ void GLEObjectBlocksList::updateFile(QStandardItem *parent, GLESourceFile* file)
for (int i = 0; i < file->getNbObjectDOConstructors(); i++) {
GLEObjectDOConstructor* cons = file->getObjectDOConstructor(i);
QStandardItem* child = new QStandardItem(QString::fromUtf8(cons->getName().c_str()).toLower());
- child->setData(qVariantFromValue((void*)cons));
+ child->setData(QVariant::fromValue((void*)cons));
item->appendRow(child);
consList.add(cons);
}
diff --git a/src/gui/qgle_statics.cpp b/src/gui/qgle_statics.cpp
index b7a98ab..443744c 100644
--- a/src/gui/qgle_statics.cpp
+++ b/src/gui/qgle_statics.cpp
@@ -20,6 +20,8 @@
***********************************************************************************/
#include <QtGui>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
#include "qgle_statics.h"
#include "qgle_definitions.h"
#include "drawingobject.h"
@@ -48,14 +50,15 @@ QString QGLE::prettyDate(QString datestr)
// provided date
QDate dt = QDate::fromString(datestr, "dd/MM/yyyy");
QString prettyString = dt.toString("d MMMM yyyy");
- QRegExp rx("^(\\d?)(\\d)(?= )");
+ QRegularExpression rx("^(\\d?)(\\d)(?= )");
QString suffix;
- if(rx.indexIn(prettyString) > -1)
+ QRegularExpressionMatch match = rx.match(prettyString);
+ if(match.hasMatch())
{
- if (rx.capturedTexts()[1].toInt() == 1)
+ if (match.captured(1).toInt() == 1)
suffix = "th";
else
- switch(rx.capturedTexts()[2].toInt())
+ switch(match.captured(2).toInt())
{
case 1:
suffix = "st";
@@ -69,7 +72,7 @@ QString QGLE::prettyDate(QString datestr)
default:
suffix = "th";
}
- prettyString.replace(rx, rx.capturedTexts()[0] + suffix);
+ prettyString.replace(rx, match.captured(0) + suffix);
}
return(prettyString);
@@ -378,7 +381,7 @@ int QGLE::computeAutoScaleDPIFromPts(const QSize& bitmapSize, int inset, double
QString QGLE::GetExeName()
{
- QString result = QString::null;
+ QString result;
#ifdef Q_OS_WIN32
char name[1024];
DWORD res = GetModuleFileNameA(NULL, name, 1023);
@@ -388,7 +391,7 @@ QString QGLE::GetExeName()
result = name;
}
#elif defined(Q_OS_HURD) || defined Q_OS_LINUX
- return(QFileInfo("/proc/self/exe").readLink());
+ return(QFileInfo("/proc/self/exe").readSymLink());
#else
return(QApplication::applicationFilePath());
#endif
diff --git a/src/gui/qgle_statics.h b/src/gui/qgle_statics.h
index 8e9ed94..eab7d7c 100644
--- a/src/gui/qgle_statics.h
+++ b/src/gui/qgle_statics.h
@@ -23,6 +23,7 @@
#define __QGLE_STATICS_H
#include <QtWidgets>
+#include <QRegExp>
#include "../gle/gle-interface/gle-interface.h"
//! Class providing static helper functions for the main code
diff --git a/src/gui/qgs.cpp b/src/gui/qgs.cpp
index b7a6904..5df0280 100644
--- a/src/gui/qgs.cpp
+++ b/src/gui/qgs.cpp
@@ -197,7 +197,7 @@ GSInterpreterLib::GSInterpreterLib() :
m_width(0),
m_height(0),
m_dpi(100.0),
- m_media(QString::null),
+ m_media(QString()),
m_Gwidth(0),
m_Gheight(0),
m_imageChar(0),
@@ -284,7 +284,7 @@ bool GSInterpreterLib::start(bool setStdio)
call = m_gs->gsapi_init_with_args(ghostScriptInstance, m_argsCCount, m_argsChar);
if (call && !handleExit(call)) return false;
QString set;
- set.sprintf("<< /Orientation %d >> setpagedevice .locksafe",m_orientation);
+ set.asprintf("<< /Orientation %d >> setpagedevice .locksafe",m_orientation);
QByteArray strdata = set.toLatin1();
m_gs->gsapi_run_string_with_length(ghostScriptInstance, strdata.constData(), set.length(), 0, &call);
m_running = handleExit (call);
@@ -707,7 +707,7 @@ void GSInterpreterLib::argsToChar()
}
}
internalArgs << "-sDEVICE=display";
- internalArgs << QString().sprintf("-dDisplayFormat=%d", format);
+ internalArgs << QString().asprintf("-dDisplayFormat=%d", format);
}
int t=internalArgs.count();
diff --git a/src/gui/serverthread.cpp b/src/gui/serverthread.cpp
index 38eda09..2fa4f19 100644
--- a/src/gui/serverthread.cpp
+++ b/src/gui/serverthread.cpp
@@ -22,6 +22,7 @@
#include <QtCore>
#include <QtNetwork>
#include <QtDebug>
+#include <QRegularExpression>
#include "qgs.h"
#include "serverthread.h"
@@ -134,7 +135,7 @@ void GLEServerThread::run()
}
// Break it up into separate lines
- QStringList parts = gleCommand.split(QRegExp("[\\r\\n]+"));
+ QStringList parts = gleCommand.split(QRegularExpression("[\\r\\n]+"));
QString part, glefname;
// Find the bits we're interested in
--
2.45.2
Wow, fantastic! Thanks for the effort. I think the best way to handle this is to create a branch for qt6 then merge these changes in. Also I will need time to get qt6 installed on my machine so I can build against it.
Any progress about this? Many Linux distros (including Gentoo which I use) are eager to get rid of Qt5.
Stalled at the moment. I was hoping someone would submit a pull request that includes all these patches... ;-)
Hello. I think the suggested patch should be tested, but I use gle occasionally and prefer to use the command line interface. Still, I have a colleague that uses qgle though on Windows. It would be nice if there was the prebuild test package with Qt6.
I agree
Some news about my patch.
- When I open
cos2t.glein the qgle, I get the following error:
GPL Ghostscript 10.04.0 (2024-09-18)
Copyright (C) 2024 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Unrecoverable error: stackunderflow in --%s_proc_read_continue--
Operand stack:
--nostringval--
Ghostscript error: -17 stackunderflow
Also, the image has wrong colors (distorted). On windows with gle 4.3.5 and gs 10.04 everything is fine.
- After I changed the patch a bit and applied the following patch
From 6f00cf4aefa6e2645d0f354c07abb050246fcc23 Mon Sep 17 00:00:00 2001
From: Vladimir Lomov <[email protected]>
Date: Mon, 10 Mar 2025 11:42:58 +0800
Subject: [PATCH 4/4] Debug qgs issue
Signed-off-by: Vladimir Lomov <[email protected]>
---
src/gui/qgs.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/gui/qgs.cpp b/src/gui/qgs.cpp
index 4d6e80c..a6f8214 100644
--- a/src/gui/qgs.cpp
+++ b/src/gui/qgs.cpp
@@ -709,6 +709,7 @@ void GSInterpreterLib::argsToChar()
}
internalArgs << "-sDEVICE=display";
internalArgs << QString("-dDisplayFormat=%1").arg(format);
+ qDebug() << "[DEBUG] display format: " << format;
}
int t=internalArgs.count();
@@ -721,6 +722,11 @@ void GSInterpreterLib::argsToChar()
m_argsChar=args;
m_argsCCount=t;
+ for(const auto& i: internalArgs)
+ {
+ qDebug() << "[DEBUG] " << i;
+ }
+
}
bool GSInterpreterLib::hasError()
--
2.48.1
I get in terminal
[DEBUG] display format: 67716
[DEBUG] "-dMaxBitmap=10000000"
[DEBUG] "-dSAFER"
[DEBUG] "-dBATCH"
[DEBUG] "-dNOPAUSE"
[DEBUG] "-dNOPAGEPROMPT"
[DEBUG] "-r337.5"
[DEBUG] "-g807x807"
[DEBUG] "-dDisplayResolution=337.5"
[DEBUG] "-dTextAlphaBits=4"
[DEBUG] "-dGraphicsAlphaBits=4"
[DEBUG] "-sDEVICE=display"
[DEBUG] "-dDisplayFormat=67716"
Now there is no error message, but the image colors are still wrong. I don't know if these settings are correct, so I stopped here.
Ok, scratch that
the image colors are wrong
because I found the reason for the color "breakage". I use Hyprland (wayland compositor), so most of QT6 applications use Wayland too. Also, the windows are configured to be somewhat transparent (even more so when a window is inactive). However, when I run qgle via XWayland (QT_QPA_PLATFORM=xcb qgle), there is no error message (with the new patch) and the colors are fine.
Still, there is something weird with the image when using pure Wayland output. I'll check what qgle displays in the KDE (wayland) environment.
I tested qgle in KDE (wayland) with both QT_QPA_PLATFORM=wayland and QT_QPA_PLATFORM=xcb. The former gives an almost invisible image (I think it depends on the image size and the test file itself), the latter is Ok. I suspect that there is an issue with how Qt renders the image depending on the platform, but I'm not an expert here.
Similar issues with faded images were reported on the macOS - but with QT5. I am not expert either - thanks for the efforts.
Qt5 is now declared deprecated in Gentoo
At this point in time, Linux distributions are already tracking which packages are blocking Qt5 cleanup. Real Qt Company OSS support stopped back in 2020, when public availability of LTS releases started to be delayed for 1 year, stable branch repository access got closed down (with 5.15 branch repository receiving any new LTS tag one year after commercial release) and only Qt6-relevant bugs are being fixed (then backported) since then. The final release happened on 2025-05-19, which means a) we will not get it until 2026-06-19, b) any bugs discovered since last May will not be fixed and c) no bugs since 2020-12-08 that haven't also been affecting Qt6 were fixed at all.
At least Gentoo, Alpine and Ubuntu are entertaining Qt5 porting trackers by now, for Gentoo, Qt5 revdep cleanups are in full swing already. https://bugs.gentoo.org/show_bug.cgi?id=qt5-removal https://gitlab.alpinelinux.org/alpine/aports/-/issues/17114 https://ubuntu-archive-team.ubuntu.com/transitions/html/qt5-removal.html
GLE is now built using Qt6 starting at version 4.3.8. The patch helped. Thanks! Closing this issue