git: 537bc57baaf8 - main - graphics/zeno: migrate to Qt6

From: Yuri Victorovich <yuri_at_FreeBSD.org>
Date: Sun, 18 Oct 2026 08:49:48 UTC
The branch main has been updated by yuri:

URL: https://cgit.FreeBSD.org/ports/commit/?id=537bc57baaf862c43f3af0daf991fdc7ad995524

commit 537bc57baaf862c43f3af0daf991fdc7ad995524
Author:     Martin Filla <freebsd@sysctl.cz>
AuthorDate: 2026-10-18 04:59:07 +0000
Commit:     Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2026-10-18 08:49:45 +0000

    graphics/zeno: migrate to Qt6
    
    PR:             299456
    Signed-off-by:  Martin Filla <freebsd@sysctl.cz>
---
 graphics/zeno/Makefile                             |  46 ++++++---
 .../zeno/files/patch-ui_autotest_CMakeLists.txt    |  17 ++++
 .../zeno/files/patch-ui_zenoedit_CMakeLists.txt    |  39 ++++++++
 .../patch-ui_zenoedit_dialog_zcheckupdatedlg.cpp   |  17 ++++
 ...-ui_zenoedit_dialog_zmaterialinfosettingdlg.cpp |  32 ++++++
 ...ch-ui_zenoedit_dialog_zmathpresetsubgrapdlg.cpp |  17 ++++
 .../patch-ui_zenoedit_dock_docktabcontent.cpp      |  24 +++++
 .../patch-ui_zenoedit_dock_zenodocktitlewidget.cpp |  11 +++
 .../files/patch-ui_zenoedit_launch_optixmain.cpp   |  11 +++
 ...patch-ui_zenoedit_nodesview_zenowelcomepage.cpp |  20 ++++
 .../patch-ui_zenoedit_nodesys_commandnode.cpp      |  11 +++
 .../files/patch-ui_zenoedit_nodesys_groupnode.cpp  |  11 +++
 ...patch-ui_zenoedit_nodesys_zenosubgraphscene.cpp |  20 ++++
 .../patch-ui_zenoedit_nodesys_zenosubgraphview.cpp |  20 ++++
 ...-ui_zenoedit_panel_zenoblackboardpropwidget.cpp |  12 +++
 ...ch-ui_zenoedit_panel_zenocommandparamspanel.cpp |  11 +++
 .../patch-ui_zenoedit_panel_zenoproppanel.cpp      |  11 +++
 .../patch-ui_zenoedit_panel_zenospreadsheet.cpp    |  11 +++
 .../files/patch-ui_zenoedit_panel_zlogpanel.cpp    |  19 ++++
 .../zeno/files/patch-ui_zenoedit_recordmain.cpp    |   9 ++
 .../patch-ui_zenoedit_viewport_cameracontrol.cpp   |  82 ++++++++++++++++
 .../patch-ui_zenoedit_viewport_displaywidget.cpp   |  34 +++++++
 .../patch-ui_zenoedit_viewport_optixviewport.cpp   |  29 ++++++
 .../patch-ui_zenoedit_viewport_viewportwidget.cpp  |  79 +++++++++++++++
 .../patch-ui_zenoedit_viewport_viewportwidget.h    |  32 ++++++
 .../patch-ui_zenoedit_viewport_zoptixviewport.cpp  |  29 ++++++
 .../files/patch-ui_zenoedit_zenoapplication.cpp    |  15 ++-
 .../files/patch-ui_zenoedit_zenomainwindow.cpp     |  49 +++++++++-
 graphics/zeno/files/patch-ui_zenoio_CMakeLists.txt |  22 +++++
 .../zeno/files/patch-ui_zenomodel_CMakeLists.txt   |  17 ++++
 .../files/patch-ui_zenomodel_include_modeldata.h   |  24 +++++
 .../patch-ui_zenomodel_src_globalcontrolmgr.cpp    |  11 +++
 .../zeno/files/patch-ui_zenomodel_src_uihelper.cpp |  58 +++++++++++
 graphics/zeno/files/patch-ui_zenoui_CMakeLists.txt |  33 ++++---
 .../patch-ui_zenoui_ColorEditor_ColorEditor.cpp    | 107 +++++++++++++++++++++
 ...zenoui_comctrl_dialog_curvemap_curvemapview.cpp |  20 ++++
 ...i_zenoui_comctrl_dialog_curvemap_curvemapview.h |  10 ++
 ..._zenoui_comctrl_dialog_curvemap_curvenodeitem.h |  11 +++
 ...-ui_zenoui_comctrl_dialog_zenoheatmapeditor.cpp |  11 +++
 ...h-ui_zenoui_comctrl_dialog_zframelessdialog.cpp |  11 +++
 .../patch-ui_zenoui_comctrl_gv_zenoparamwidget.cpp |  29 ++++++
 ...atch-ui_zenoui_comctrl_gv_zgraphicstextitem.cpp |  23 +++++
 .../patch-ui_zenoui_comctrl_gv_zitemfactory.cpp    |  12 +++
 .../files/patch-ui_zenoui_comctrl_testwidget.cpp   |  11 +++
 .../files/patch-ui_zenoui_comctrl_zcheckboxbar.cpp |  11 +++
 .../files/patch-ui_zenoui_comctrl_zcheckboxbar.h   |  11 +++
 .../patch-ui_zenoui_comctrl_zdocktabwidget.cpp     |  11 +++
 .../files/patch-ui_zenoui_comctrl_zdocktabwidget.h |  11 +++
 .../patch-ui_zenoui_comctrl_zenocheckbutton.cpp    |  11 +++
 .../patch-ui_zenoui_comctrl_zenocheckbutton.h      |  11 +++
 .../files/patch-ui_zenoui_comctrl_ziconbutton.cpp  |  11 +++
 .../files/patch-ui_zenoui_comctrl_ziconbutton.h    |  11 +++
 .../patch-ui_zenoui_comctrl_zicontoolbutton.cpp    |  11 +++
 .../patch-ui_zenoui_comctrl_zicontoolbutton.h      |  11 +++
 .../zeno/files/patch-ui_zenoui_comctrl_zlabel.cpp  |  20 ++++
 .../zeno/files/patch-ui_zenoui_comctrl_zlabel.h    |  20 ++++
 .../files/patch-ui_zenoui_comctrl_zlineedit.cpp    |  11 +++
 .../files/patch-ui_zenoui_comctrl_znumslider.cpp   |  11 +++
 .../files/patch-ui_zenoui_comctrl_zpopupwidget.cpp |  11 +++
 .../patch-ui_zenoui_comctrl_zspinboxslider.cpp     |  11 +++
 .../files/patch-ui_zenoui_comctrl_ztoolbutton.cpp  |  11 +++
 .../files/patch-ui_zenoui_comctrl_ztoolbutton.h    |  11 +++
 .../patch-ui_zenoui_comctrl_zwidgetfactory.cpp     |  12 +++
 .../zeno/files/patch-ui_zenoui_nodesys_nodegrid.h  |  11 +++
 .../patch-ui_zenoui_nodesys_nodesys__common.h      |  11 +++
 .../files/patch-ui_zenoui_nodesys_zenosvgitem.h    |  11 +++
 .../zeno/files/patch-ui_zenoui_style_zenostyle.cpp |  18 ++++
 67 files changed, 1379 insertions(+), 28 deletions(-)

diff --git a/graphics/zeno/Makefile b/graphics/zeno/Makefile
index 62c3c550ebe8..6acc62b2d28d 100644
--- a/graphics/zeno/Makefile
+++ b/graphics/zeno/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	zeno
 DISTVERSION=	2024.10.1
-PORTREVISION=	5
+PORTREVISION=	6
 CATEGORIES=	graphics
 
 MAINTAINER=	freebsd@sysctl.cz
@@ -13,23 +13,31 @@ LICENSE_FILE=	${WRKSRC}/LICENSE
 BUILD_DEPENDS=	boost-libs>=1.85.0:devel/boost-libs \
 		c-blosc2>0:archivers/c-blosc2 \
 		onetbb>0:devel/onetbb \
-		openmpi>0:net/openmpi
+		openmpi>0:net/openmpi \
+		${_QWT_LIB}:x11-toolkits/qwt6@qt6
 
 LIB_DEPENDS=	libboost_atomic.so:devel/boost-libs \
 		libboost_chrono.so:devel/boost-libs \
 		libboost_thread.so:devel/boost-libs \
 		libcryptopp.so:security/cryptopp \
-		libminizip.so:archivers/minizip \
-		libqwt.so:x11-toolkits/qwt6@qt5
+		libminizip.so:archivers/minizip
+RUN_DEPENDS=	${_QWT_LIB}:x11-toolkits/qwt6@qt6
 
-USES=		cmake compiler:c++17-lang eigen:3 localbase:ldflags pkgconfig \
-		qt:5
+USES=		cmake compiler:c++17-lang eigen:3 gl localbase:ldflags pkgconfig \
+		qt:6
+USE_GL=		gl opengl
 USE_LDCONFIG=	yes
-USE_QT=		core gui network opengl svg widgets buildtools:build qmake:build
+USE_QT=		base svg
 
 USE_GITHUB=	yes
 GH_ACCOUNT=	zenustech
 
+# The bundled Qwt is a prebuilt static library for Qt 5, use the Qt 6 flavor
+# of x11-toolkits/qwt6 instead.  Both flavors install libqwt.so, so depend on
+# the Qt 6 one by path: LIB_DEPENDS would be satisfied by qwt6-qt5 as well.
+_QWT_LIB=	${LOCALBASE}/${QT_LIBDIR_REL}/libqwt.so
+CMAKE_ARGS=	-DQWT_INCLUDE_DIR:PATH=${LOCALBASE}/${QT_INCDIR_REL}/qwt6 \
+		-DQWT_LIBRARY:FILEPATH=${_QWT_LIB}
 CMAKE_ON=	ZENO_BUILD_EDITOR ZENO_BUILD_SHARED ZENO_IPC_USE_TCP \
 		ZENO_MULTIPROCESS ZENO_NO_WARNING ZENO_USE_CCACHE \
 		ZENO_SYSTEM_OPENVDB
@@ -45,7 +53,7 @@ CMAKE_OFF=	ZENO_BUILD_DESIGNER ZENO_BUILD_PLAYER ZENO_INSTALL_TARGET \
 
 # Every extension below is a set of nodes compiled into libzeno.so, so these
 # options only change what the editor offers - the package always installs the
-# same three files.  Extensions that stay off and why:
+# same files.  Extensions that stay off and why:
 #   zenvdb, FastFLIP	# need the openvdb submodule, add it to GH_TUPLE first
 #   Euler		# needs zenvdb, and compiling it killed gcc
 #   SampleModel		# error: '_pgmptr' was not declared in this scope
@@ -187,9 +195,15 @@ CGMESHTOOLS_IMPLIES=		CGMESH
 FLIPTOOLS_CMAKE_BOOL=		ZENO_WITH_TOOL_FLIPtools
 HERCULESTOOLS_CMAKE_BOOL=	ZENO_WITH_TOOL_HerculesTools
 
+DESKTOP_ENTRIES=	"ZENO" "Node based simulation and rendering engine" \
+			"zeno" "zenoedit" "Graphics;3DGraphics;" false
+
+ICON_SIZES=	64 128 256
+
 PLIST_FILES=	bin/autotest \
 		bin/zenoedit \
-		lib/libzeno.so
+		lib/libzeno.so \
+		${ICON_SIZES:@s@share/icons/hicolor/${s}x${s}/apps/zeno.png@}
 
 BULLET_FORK=	${WRKSRC}/projects/Rigid/bullet3
 
@@ -198,9 +212,11 @@ post-extract-RIGID-on:
 		src/BulletDynamics src/BulletSoftBody src/LinearMath src/clew \
 		src/*.cpp src/*.h
 
+BULLET_INCLUDE=	\#include "(\.\./)+(LinearMath|BulletCollision|BulletDynamics|Bullet3Common|btBullet)
+
 post-patch-RIGID-on:
-	@${FIND} ${BULLET_FORK}/src -name '*.[ch]*' -exec ${REINPLACE_CMD} -E \
-		's@#include "(\.\./)+(LinearMath|BulletCollision|BulletDynamics|Bullet3Common|btBullet)@#include "\2@' {} +
+	@${FIND} ${BULLET_FORK}/src -name '*.[ch]*' -exec ${GREP} -lE '${BULLET_INCLUDE}' {} + | \
+		${XARGS} ${REINPLACE_CMD} -E 's@${BULLET_INCLUDE}@#include "\2@'
 
 pre-configure-RIGID-on:
 	@if ${GREP} -q BT_USE_DOUBLE_PRECISION ${LOCALBASE}/libdata/pkgconfig/bullet.pc; then \
@@ -208,12 +224,14 @@ pre-configure-RIGID-on:
 		${FALSE}; \
 	fi
 
-pre-configure:
-	${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|g' ${WRKSRC}/ui/zenoui/CMakeLists.txt
-
 do-install:
 	${INSTALL_PROGRAM} ${BUILD_WRKSRC}/bin/autotest ${STAGEDIR}${PREFIX}/bin
 	${INSTALL_PROGRAM} ${BUILD_WRKSRC}/bin/zenoedit ${STAGEDIR}${PREFIX}/bin
 	${INSTALL_LIB} ${BUILD_WRKSRC}/bin/libzeno.so ${STAGEDIR}${PREFIX}/lib
+.for s in ${ICON_SIZES}
+	@${MKDIR} ${STAGEDIR}${PREFIX}/share/icons/hicolor/${s}x${s}/apps
+	${INSTALL_DATA} ${WRKSRC}/ui/zenoedit/res/icons/ZENO-logo${s}.png \
+		${STAGEDIR}${PREFIX}/share/icons/hicolor/${s}x${s}/apps/zeno.png
+.endfor
 
 .include <bsd.port.mk>
diff --git a/graphics/zeno/files/patch-ui_autotest_CMakeLists.txt b/graphics/zeno/files/patch-ui_autotest_CMakeLists.txt
new file mode 100644
index 000000000000..41eb3aa7d2c8
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_autotest_CMakeLists.txt
@@ -0,0 +1,17 @@
+--- ui/autotest/CMakeLists.txt.orig	2024-09-30 13:46:54 UTC
++++ ui/autotest/CMakeLists.txt
+@@ -1,6 +1,6 @@
+ file(GLOB_RECURSE source CONFIGURE_DEPENDS *.h *.cpp *.ui)
+ 
+-find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
++find_package(Qt6 COMPONENTS Widgets OpenGL REQUIRED)
+ 
+ add_executable(autotest ${source}) 
+ 
+@@ -11,5 +11,5 @@ set_property(TARGET autotest PROPERTY AU
+ set_property(TARGET autotest PROPERTY AUTORCC ON)
+ 
+ target_link_libraries(autotest PUBLIC zenomodel zenoio zeno)
+-target_link_libraries(autotest PRIVATE Qt5::Widgets Qt5::OpenGL)
++target_link_libraries(autotest PRIVATE Qt6::Widgets Qt6::OpenGL)
+ target_include_directories(autotest PRIVATE . .. ../zenoui ../include)
diff --git a/graphics/zeno/files/patch-ui_zenoedit_CMakeLists.txt b/graphics/zeno/files/patch-ui_zenoedit_CMakeLists.txt
new file mode 100644
index 000000000000..9ee4262d991e
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_CMakeLists.txt
@@ -0,0 +1,39 @@
+--- ui/zenoedit/CMakeLists.txt.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/CMakeLists.txt
+@@ -1,6 +1,6 @@
+-find_package(Qt5 COMPONENTS Widgets OpenGL Network REQUIRED)
++find_package(Qt6 COMPONENTS Widgets OpenGL OpenGLWidgets Network REQUIRED)
+ 
+-message(STATUS "Found Qt5 version ${Qt5_VERSION}: ${Qt5_DIR}")
++message(STATUS "Found Qt6 version ${Qt6_VERSION}: ${Qt6_DIR}")
+ 
+ #if (ZENO_WITH_PYTHON3)
+ #    find_package(Python3 COMPONENTS Development REQUIRED)
+@@ -21,8 +21,8 @@ FOREACH(item ${resource})
+     ENDIF(item IN_LIST bigresource)
+ ENDFOREACH(item)
+ 
+-qt5_add_big_resources(source ${bigresource})  # cihou msvc: fatal error C1060: compiler is out of heap space
+-qt5_add_resources(source ${resource})
++qt6_add_big_resources(source ${bigresource})  # cihou msvc: fatal error C1060: compiler is out of heap space
++qt6_add_resources(source ${resource})
+ 
+ if (ZENO_WIN32_RC)
+     enable_language("RC")
+@@ -57,7 +57,7 @@ if (NOT ZENO_MULTIPROCESS OR NOT ZENO_IP
+     find_package(Threads REQUIRED)
+     target_link_libraries(zenoedit PRIVATE Threads::Threads)
+ endif()
+-target_link_libraries(zenoedit PRIVATE Qt5::Widgets Qt5::OpenGL Qt5::Network)
++target_link_libraries(zenoedit PRIVATE Qt6::Widgets Qt6::OpenGL Qt6::OpenGLWidgets Qt6::Network)
+ 
+ if (WIN32)
+     target_link_libraries(zenoedit PRIVATE Dbghelp Version)
+@@ -66,7 +66,6 @@ endif()
+ target_link_libraries(zenoedit PRIVATE zenoui zenoio zenomodel zenovis)
+ target_link_libraries(zenoedit PRIVATE zeno)
+ target_include_directories(zenoedit PRIVATE . .. ../zenoui ../include)
+-target_include_directories(zenoedit PRIVATE ${Qt5Widgets_PRIVATE_INCLUDE_DIRS})
+ if(ZENO_LIVESYNC)
+     find_package(Crow CONFIG REQUIRED)
+     target_link_libraries(zenoedit PRIVATE Crow::Crow)
diff --git a/graphics/zeno/files/patch-ui_zenoedit_dialog_zcheckupdatedlg.cpp b/graphics/zeno/files/patch-ui_zenoedit_dialog_zcheckupdatedlg.cpp
new file mode 100644
index 000000000000..79901767bff8
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_dialog_zcheckupdatedlg.cpp
@@ -0,0 +1,17 @@
+--- ui/zenoedit/dialog/zcheckupdatedlg.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/dialog/zcheckupdatedlg.cpp
+@@ -138,10 +138,11 @@ void ZCheckUpdateDlg::getCudaVersion()
+     connect(process, &QProcess::readyReadStandardOutput, this, [=] {
+         QString output = process->readAllStandardOutput();
+         //Cuda compilation tools, release 12.1
+-        QRegExp rx("Cuda compilation tools, release (\\d+)\\.(\\d+)");
+-        if (rx.indexIn(output) != -1)
++        static const QRegularExpression rx("Cuda compilation tools, release (\\d+)\\.(\\d+)");
++        QRegularExpressionMatch match = rx.match(output);
++        if (match.hasMatch())
+         {
+-            auto caps = rx.capturedTexts();
++            auto caps = match.capturedTexts();
+             int ver;
+             if (caps.length() == 3) {
+                 ver = caps[1].toInt();
diff --git a/graphics/zeno/files/patch-ui_zenoedit_dialog_zmaterialinfosettingdlg.cpp b/graphics/zeno/files/patch-ui_zenoedit_dialog_zmaterialinfosettingdlg.cpp
new file mode 100644
index 000000000000..a5c64b95a203
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_dialog_zmaterialinfosettingdlg.cpp
@@ -0,0 +1,32 @@
+--- ui/zenoedit/dialog/zmaterialinfosettingdlg.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/dialog/zmaterialinfosettingdlg.cpp
+@@ -220,13 +220,13 @@ void ZMaterialInfoSettingDlg::updateMatc
+             pItem->appendRow(pChildItem);
+             pChildItem->setData(paramName, Qt::UserRole);
+             ZComboBox* pComboBox = new ZComboBox(this);
+-            QList<QString> lst = map[name].toList();
++            QList<QString> lst = map[name].values();
+             lst.prepend(paramName);
+             pComboBox->addItems(lst);
+             pComboBox->setCurrentText(paramName);
+             QWidget* pWidget = new QWidget(this);
+             QHBoxLayout* pLayout = new QHBoxLayout(pWidget);
+-            pLayout->setMargin(0);
++            pLayout->setContentsMargins(0, 0, 0, 0);
+             pLayout->addStretch();
+             pLayout->addWidget(pComboBox);
+             ui->m_matchTreeView->setIndexWidget(pChildItem->index(), pWidget);
+@@ -294,10 +294,10 @@ void ZMaterialInfoSettingDlg::onOKClicke
+         int row1 = 0;
+ 
+         QJsonObject obj;
+-        while (parent.child(row1, 0).isValid())
++        while (m_pModel->index(row1, 0, parent).isValid())
+         {
+-            QString text = parent.child(row1, 0).data(Qt::UserRole).toString();
+-            QString jsonKey = parent.child(row1, 0).data().toString();
++            QString text = m_pModel->index(row1, 0, parent).data(Qt::UserRole).toString();
++            QString jsonKey = m_pModel->index(row1, 0, parent).data().toString();
+             obj[jsonKey] = text;
+             row1++;
+         }
diff --git a/graphics/zeno/files/patch-ui_zenoedit_dialog_zmathpresetsubgrapdlg.cpp b/graphics/zeno/files/patch-ui_zenoedit_dialog_zmathpresetsubgrapdlg.cpp
new file mode 100644
index 000000000000..d06e2d71bdc7
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_dialog_zmathpresetsubgrapdlg.cpp
@@ -0,0 +1,17 @@
+--- ui/zenoedit/dialog/zmathpresetsubgrapdlg.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/dialog/zmathpresetsubgrapdlg.cpp
+@@ -80,12 +80,12 @@ void ZMatchPresetSubgraphDlg::onRowInser
+     {
+         QWidget* pWidget = new QWidget(this);
+         QHBoxLayout* pLayout = new QHBoxLayout(pWidget);
+-        pLayout->setMargin(0);
++        pLayout->setContentsMargins(0, 0, 0, 0);
+         QString param = idx.data(Qt::DisplayRole).toString();
+         pLayout->addStretch();
+ 
+         ZComboBox* pComboBox = new ZComboBox(this);
+-        QList<QString> lst = parent.data(Qt::UserRole).value<QSet<QString> >().toList();
++        QList<QString> lst = parent.data(Qt::UserRole).value<QSet<QString> >().values();
+         lst.prepend(param);
+         pComboBox->addItems(lst);
+         pComboBox->setCurrentText(param);
diff --git a/graphics/zeno/files/patch-ui_zenoedit_dock_docktabcontent.cpp b/graphics/zeno/files/patch-ui_zenoedit_dock_docktabcontent.cpp
new file mode 100644
index 000000000000..9327e54dc13d
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_dock_docktabcontent.cpp
@@ -0,0 +1,24 @@
+--- ui/zenoedit/dock/docktabcontent.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/dock/docktabcontent.cpp
+@@ -116,7 +116,7 @@ ZTextIconButton::ZTextIconButton(const Q
+     m_pButton->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
+     m_pLablel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+     QHBoxLayout* pLayout = new QHBoxLayout(this);
+-    pLayout->setMargin(0);
++    pLayout->setContentsMargins(0, 0, 0, 0);
+     pLayout->addWidget(m_pLablel);
+     pLayout->addWidget(m_pButton);
+     connect(m_pButton, &QPushButton::clicked, this, &ZTextIconButton::clicked);
+@@ -366,10 +366,8 @@ void DockContent_Editor::initToolbar(QHB
+ 
+     Callback_EditFinished funcZoomEdited = [=](QVariant newValue) {
+         const QString& percent = newValue.toString();
+-        QRegExp rx("(\\d+)\\%");
+-        rx.indexIn(percent);
+-        auto caps = rx.capturedTexts();
+-        qreal scale = caps[1].toFloat() / 100.;
++        static const QRegularExpression rx("(\\d+)\\%");
++        qreal scale = rx.match(percent).captured(1).toFloat() / 100.;
+         QAction act("zoom");
+         act.setProperty("ActionType", ZenoMainWindow::ACTION_ZOOM);
+         if (m_pEditor)
diff --git a/graphics/zeno/files/patch-ui_zenoedit_dock_zenodocktitlewidget.cpp b/graphics/zeno/files/patch-ui_zenoedit_dock_zenodocktitlewidget.cpp
new file mode 100644
index 000000000000..dc18652684bf
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_dock_zenodocktitlewidget.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/dock/zenodocktitlewidget.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/dock/zenodocktitlewidget.cpp
+@@ -52,7 +52,7 @@ void ZenoDockTitleWidget::setupUi()
+ 
+ 	pHLayout->addWidget(pDockOptionsBtn);
+ 	pHLayout->setContentsMargins(0, 0, 0, 0);
+-	pHLayout->setMargin(0);
++	pHLayout->setContentsMargins(0, 0, 0, 0);
+ 
+ 	pLayout->addLayout(pHLayout);
+ 
diff --git a/graphics/zeno/files/patch-ui_zenoedit_launch_optixmain.cpp b/graphics/zeno/files/patch-ui_zenoedit_launch_optixmain.cpp
new file mode 100644
index 000000000000..162f9ab0c39d
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_launch_optixmain.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/launch/optixmain.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/launch/optixmain.cpp
+@@ -44,7 +44,7 @@ int optix_main(const QCoreApplication& a
+ 
+     zeno::set_log_stream(std::clog);
+ 
+-    ZenoMainWindow tempWindow(nullptr, 0, PANEL_OPTIX_VIEW);
++    ZenoMainWindow tempWindow(nullptr, Qt::WindowFlags(), PANEL_OPTIX_VIEW);
+     tempWindow.showMaximized();
+     tempWindow.optixClientRun(port, cachedir, cachenum, sFrame, eFrame, finishedFrames, sessionId);
+     return app.exec();
diff --git a/graphics/zeno/files/patch-ui_zenoedit_nodesview_zenowelcomepage.cpp b/graphics/zeno/files/patch-ui_zenoedit_nodesview_zenowelcomepage.cpp
new file mode 100644
index 000000000000..a148844d83db
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_nodesview_zenowelcomepage.cpp
@@ -0,0 +1,20 @@
+--- ui/zenoedit/nodesview/zenowelcomepage.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/nodesview/zenowelcomepage.cpp
+@@ -6,7 +6,7 @@
+ #include "zenomainwindow.h"
+ #include "settings/zsettings.h"
+ #include <zenoui/style/zenostyle.h>
+-#include <QtSvg/QSvgWidget>
++#include <QtSvgWidgets/QSvgWidget>
+ #include "startup/zstartup.h"
+ 
+ 
+@@ -16,7 +16,7 @@ ZenoWelcomePage::ZenoWelcomePage(QWidget
+ 	m_ui = new Ui::WelcomePage;
+ 	m_ui->setupUi(this);
+     QPalette palette = this->palette();
+-    palette.setColor(QPalette::Background, QColor("#2d3239"));
++    palette.setColor(QPalette::Window, QColor("#2d3239"));
+     setPalette(palette);
+ 
+     QSize iconSize(ZenoStyle::dpiScaled(24), ZenoStyle::dpiScaled(24));
diff --git a/graphics/zeno/files/patch-ui_zenoedit_nodesys_commandnode.cpp b/graphics/zeno/files/patch-ui_zenoedit_nodesys_commandnode.cpp
new file mode 100644
index 000000000000..b2df70bf1796
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_nodesys_commandnode.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/nodesys/commandnode.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/nodesys/commandnode.cpp
+@@ -72,7 +72,7 @@ void CommandNode::onExecuteClicked()
+     QModelIndex commandsIdx = pModel->paramIndex(subgIdx, this->index(), "commands", true);
+     ZASSERT_EXIT(commandsIdx.isValid());
+     QString commands = commandsIdx.data(ROLE_PARAM_VALUE).toString();
+-    QStringList cmds = commands.split("\n", QString::SkipEmptyParts);
++    QStringList cmds = commands.split("\n", Qt::SkipEmptyParts);
+     for (QString cmd : cmds) {
+         //api examples:
+         // NewGraph("graphName")
diff --git a/graphics/zeno/files/patch-ui_zenoedit_nodesys_groupnode.cpp b/graphics/zeno/files/patch-ui_zenoedit_nodesys_groupnode.cpp
new file mode 100644
index 000000000000..e5b869c87028
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_nodesys_groupnode.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/nodesys/groupnode.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/nodesys/groupnode.cpp
+@@ -96,7 +96,7 @@ void GroupTextItem::paint(QPainter *pain
+     QString text = m_text;
+     qreal width = ZenoStyle::scaleWidth(4);
+     QRectF textRect = boundingRect().adjusted(width, 0, -width, 0);
+-    if (fontMetrics.width(text) > textRect.width()) {
++    if (fontMetrics.horizontalAdvance(text) > textRect.width()) {
+         text = fontMetrics.elidedText(text, Qt::ElideRight, textRect.width());
+     }
+     painter->drawText(textRect, Qt::AlignVCenter, text);
diff --git a/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphscene.cpp b/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphscene.cpp
new file mode 100644
index 000000000000..c9fbc0708e2f
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphscene.cpp
@@ -0,0 +1,20 @@
+--- ui/zenoedit/nodesys/zenosubgraphscene.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/nodesys/zenosubgraphscene.cpp
+@@ -946,7 +946,7 @@ void ZenoSubGraphScene::mouseMoveEvent(Q
+ 
+ void ZenoSubGraphScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+ {
+-    if (m_tempLink && event->button() != Qt::MidButton && event->button() != Qt::RightButton)
++    if (m_tempLink && event->button() != Qt::MiddleButton && event->button() != Qt::RightButton)
+     {
+         onTempLinkClosed();
+         removeItem(m_tempLink);
+@@ -1119,7 +1119,7 @@ void ZenoSubGraphScene::updateKeyFrame()
+     for (const QModelIndex &index : selectNodesIndice()) {
+         keys << index.data(ROLE_KEYFRAMES).value<QVector<int>>();
+     }
+-    qSort(keys.begin(), keys.end());
++    std::sort(keys.begin(), keys.end());
+     keys.erase(std::unique(keys.begin(), keys.end()), keys.end());
+     zenoApp->getMainWindow()->timeline()->updateKeyFrames(keys);
+ }
diff --git a/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphview.cpp b/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphview.cpp
new file mode 100644
index 000000000000..8a02e9e125bd
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_nodesys_zenosubgraphview.cpp
@@ -0,0 +1,20 @@
+--- ui/zenoedit/nodesys/zenosubgraphview.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/nodesys/zenosubgraphview.cpp
+@@ -348,7 +348,7 @@ void _ZenoSubGraphView::showEvent(QShowE
+ 
+ void _ZenoSubGraphView::mousePressEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton)
++    if (event->button() == Qt::MiddleButton)
+     {
+         _last_mouse_pos = event->pos();
+         setDragMode(QGraphicsView::NoDrag);
+@@ -387,7 +387,7 @@ void _ZenoSubGraphView::mouseMoveEvent(Q
+ void _ZenoSubGraphView::mouseReleaseEvent(QMouseEvent* event)
+ {
+     QGraphicsView::mouseReleaseEvent(event);
+-    if (event->button() == Qt::MidButton)
++    if (event->button() == Qt::MiddleButton)
+     {
+         m_dragMove = false;
+         setDragMode(QGraphicsView::NoDrag);
diff --git a/graphics/zeno/files/patch-ui_zenoedit_panel_zenoblackboardpropwidget.cpp b/graphics/zeno/files/patch-ui_zenoedit_panel_zenoblackboardpropwidget.cpp
new file mode 100644
index 000000000000..4d13248a23a8
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_panel_zenoblackboardpropwidget.cpp
@@ -0,0 +1,12 @@
+--- ui/zenoedit/panel/zenoblackboardpropwidget.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/panel/zenoblackboardpropwidget.cpp
+@@ -22,8 +22,7 @@ ZenoBlackboardPropWidget::ZenoBlackboard
+     pGroupLayout->setSpacing(10);
+     PARAMS_INFO params = m_idx.data(ROLE_PARAMS_NO_DESC).value<PARAMS_INFO>();
+     BLACKBOARD_INFO info = params["blackboard"].value.value<BLACKBOARD_INFO>();
+-    UI_VECTYPE colorVec(3);
+-    info.background.getRgbF(&colorVec[0], &colorVec[1], &colorVec[2]);
++    UI_VECTYPE colorVec{info.background.redF(), info.background.greenF(), info.background.blueF()};
+     insertRow("background", PARAM_CONTROL::CONTROL_COLOR_VEC3F, QVariant::fromValue(colorVec), 0, pGroupLayout);
+     insertRow("title", PARAM_CONTROL::CONTROL_MULTILINE_STRING, info.title, 1, pGroupLayout);
+     //insertRow("content", PARAM_CONTROL::CONTROL_MULTILINE_STRING, info.content, 2, pGroupLayout);
diff --git a/graphics/zeno/files/patch-ui_zenoedit_panel_zenocommandparamspanel.cpp b/graphics/zeno/files/patch-ui_zenoedit_panel_zenocommandparamspanel.cpp
new file mode 100644
index 000000000000..33ddbc363645
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_panel_zenocommandparamspanel.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/panel/zenocommandparamspanel.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/panel/zenocommandparamspanel.cpp
+@@ -59,7 +59,7 @@ void ZenoCommandParamsPanel::initUi()
+     pHLayout->addWidget(m_pExportButton);
+     pLayout->addLayout(pHLayout);
+     pLayout->addWidget(m_pTableWidget);
+-    pLayout->setMargin(0);
++    pLayout->setContentsMargins(0, 0, 0, 0);
+ }
+ 
+ void ZenoCommandParamsPanel::initConnection()
diff --git a/graphics/zeno/files/patch-ui_zenoedit_panel_zenoproppanel.cpp b/graphics/zeno/files/patch-ui_zenoedit_panel_zenoproppanel.cpp
new file mode 100644
index 000000000000..314fa0d58feb
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_panel_zenoproppanel.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/panel/zenoproppanel.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/panel/zenoproppanel.cpp
+@@ -852,7 +852,7 @@ void ZenoPropPanel::getDelfCurveData(CUR
+ 
+ void ZenoPropPanel::updateHandler(CURVE_DATA &curve) {
+     if (curve.points.size() > 1) {
+-        qSort(curve.points.begin(), curve.points.end(),
++        std::sort(curve.points.begin(), curve.points.end(),
+               [](const CURVE_POINT &p1, const CURVE_POINT &p2) { return p1.point.x() < p2.point.x(); });
+         float preX = curve.points.at(0).point.x();
+         for (int i = 1; i < curve.points.size(); i++) {
diff --git a/graphics/zeno/files/patch-ui_zenoedit_panel_zenospreadsheet.cpp b/graphics/zeno/files/patch-ui_zenoedit_panel_zenospreadsheet.cpp
new file mode 100644
index 000000000000..ff8579a98292
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_panel_zenospreadsheet.cpp
@@ -0,0 +1,11 @@
+--- ui/zenoedit/panel/zenospreadsheet.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/panel/zenospreadsheet.cpp
+@@ -197,7 +197,7 @@ ZenoSpreadsheet::ZenoSpreadsheet(QWidget
+ 
+             node_sync.updateNodeInputString(new_node_location.value(), "key", prim_attr_view->model()->headerData(index, Qt::Vertical).toString().toStdString());
+             const QModelIndex& idx = prim_attr_view->model()->index(index, 0);
+-            const QStringList& vecLst = idx.data(Qt::DisplayRole).toString().split(",", QString::SkipEmptyParts);
++            const QStringList& vecLst = idx.data(Qt::DisplayRole).toString().split(",", Qt::SkipEmptyParts);
+ 
+             zeno::zany object = dataModel->userDataByIndex(idx);
+             if (zeno::objectIsLiterial<float>(object)) {
diff --git a/graphics/zeno/files/patch-ui_zenoedit_panel_zlogpanel.cpp b/graphics/zeno/files/patch-ui_zenoedit_panel_zlogpanel.cpp
new file mode 100644
index 000000000000..7610cfafe99b
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_panel_zlogpanel.cpp
@@ -0,0 +1,19 @@
+--- ui/zenoedit/panel/zlogpanel.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/panel/zlogpanel.cpp
+@@ -149,12 +149,13 @@ void LogItemDelegate::initTextLayout(
+ QVector<QTextLayout::FormatRange> LogItemDelegate::_getNodeIdentRgs(const QString& content) const
+ {
+     QVector<QTextLayout::FormatRange> selections;
+-    QRegExp rx("[0-9a-z]+\\-[^/\\s`'\"\\],:]+");
++    static const QRegularExpression rx("[0-9a-z]+\\-[^/\\s`'\"\\],:]+");
++    QRegularExpressionMatch match;
+     QString currText = content;
+ 
+     int index = -1;
+-    while ((index = rx.indexIn(currText, index + 1)) >= 0) {
+-        int capLen = rx.cap(0).length();
++    while ((index = currText.indexOf(rx, index + 1, &match)) >= 0) {
++        int capLen = match.capturedLength(0);
+         QString strIdent = currText.mid(index, capLen);
+ 
+         QTextLayout::FormatRange frg;
diff --git a/graphics/zeno/files/patch-ui_zenoedit_recordmain.cpp b/graphics/zeno/files/patch-ui_zenoedit_recordmain.cpp
index 4ae1a1eb7582..3401adb65a4c 100644
--- a/graphics/zeno/files/patch-ui_zenoedit_recordmain.cpp
+++ b/graphics/zeno/files/patch-ui_zenoedit_recordmain.cpp
@@ -8,3 +8,12 @@
  
  
  //--record true --zsg "C:\zeno-master\render_param.zsg" --cachePath "C:\tmp" --sframe 0 --frame 10 --sample 1 --optix 0 --path "C:\recordpath" --pixel 4500x3500 --aov 0 --needDenoise 0
+@@ -203,7 +204,7 @@ int record_main(const QCoreApplication&
+     }
+ 
+     if (!param.bOptix) {
+-        ZenoMainWindow tempWindow(nullptr, 0, !param.bOptix ? PANEL_GL_VIEW : PANEL_EMPTY);
++        ZenoMainWindow tempWindow(nullptr, Qt::WindowFlags(), !param.bOptix ? PANEL_GL_VIEW : PANEL_EMPTY);
+         tempWindow.hide();
+         tempWindow.solidRunRender(param, launchparam);
+         //idle
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_cameracontrol.cpp b/graphics/zeno/files/patch-ui_zenoedit_viewport_cameracontrol.cpp
new file mode 100644
index 000000000000..d154adb97035
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_cameracontrol.cpp
@@ -0,0 +1,82 @@
+--- ui/zenoedit/viewport/cameracontrol.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/cameracontrol.cpp
+@@ -105,7 +105,7 @@ void CameraControl::fakeMousePressEvent(
+     if (event->button() == Qt::MiddleButton) {
+         middle_button_pressed = true;
+         if (zeno::getSession().userData().get2<bool>("viewport-depth-aware-navigation", true)) {
+-            m_hit_posWS = scene->renderMan->getEngine()->getClickedPos(event->x(), event->y());
++            m_hit_posWS = scene->renderMan->getEngine()->getClickedPos(event->position().x(), event->position().y());
+             if (m_hit_posWS.has_value()) {
+                 scene->camera->setPivot(m_hit_posWS.value());
+             }
+@@ -119,7 +119,7 @@ void CameraControl::fakeMousePressEvent(
+     settings.getViewShortCut(ShortCut_RotatingView, button);
+     bool bTransform = false;
+     auto front = scene->camera->get_lodfront();
+-    auto dir = screenPosToRayWS(event->x() / res().x(), event->y() / res().y());
++    auto dir = screenPosToRayWS(event->position().x() / res().x(), event->position().y() / res().y());
+     if (m_transformer)
+     {
+         if (event->buttons() & Qt::LeftButton && !scene->selected.empty() && m_transformer->isTransformMode() &&
+@@ -249,7 +249,7 @@ void CameraControl::fakeMouseMoveEvent(Q
+         bTransform = m_transformer->isTransforming();
+         // check if hover a handler
+         auto front = scene->camera->get_lodfront();
+-        auto dir = screenPosToRayWS(event->x() / res().x(), event->y() / res().y());
++        auto dir = screenPosToRayWS(event->position().x() / res().x(), event->position().y() / res().y());
+         if (!scene->selected.empty() && !(event->buttons() & Qt::LeftButton)) {
+             m_transformer->hoveredAnyHandler(getPos(), dir, front);
+         }
+@@ -271,7 +271,7 @@ void CameraControl::fakeMouseMoveEvent(Q
+     else if (!bTransform && ctrl_pressed && (event->buttons() & Qt::MiddleButton)) {
+         // rot roll
+         float step = 1.0f;
+-        float ratio = QApplication::desktop()->devicePixelRatio();
++        float ratio = qApp->devicePixelRatio();
+         float dy = ypos - m_lastMidButtonPos.y();
+         dy *= ratio / m_res[1] * step;
+         {
+@@ -282,7 +282,7 @@ void CameraControl::fakeMouseMoveEvent(Q
+         m_lastMidButtonPos = QPointF(xpos, ypos);
+     }
+     else if (!bTransform && (event->buttons() & (rotateButton | moveButton))) {
+-        float ratio = QApplication::desktop()->devicePixelRatio();
++        float ratio = qApp->devicePixelRatio();
+         float dx = xpos - m_lastMidButtonPos.x(), dy = ypos - m_lastMidButtonPos.y();
+         dx *= ratio / m_res[0];
+         dy *= ratio / m_res[1];
+@@ -291,7 +291,7 @@ void CameraControl::fakeMouseMoveEvent(Q
+         if ((moveKey == modifiers) && (event->buttons() & moveButton)) {
+             // translate
+             if (m_hit_posWS.has_value()) {
+-                auto ray = screenPosToRayWS(event->x() / res().x(), event->y() / res().y());
++                auto ray = screenPosToRayWS(event->position().x() / res().x(), event->position().y() / res().y());
+                 auto new_pos = intersectRayPlane(m_hit_posWS.value(), ray * (-1.0f), getPos(), getViewDir());
+                 if (new_pos.has_value()) {
+                     auto diff = new_pos.value() - getPos();
+@@ -432,14 +432,14 @@ void CameraControl::fakeWheelEvent(QWhee
+             if (zeno::getSession().userData().get2<bool>("viewport-depth-aware-navigation", true)) {
+                 auto session = m_zenovis->getSession();
+                 auto scene = session->get_scene();
+-                auto hit_posWS = scene->renderMan->getEngine()->getClickedPos(event->x(), event->y());
++                auto hit_posWS = scene->renderMan->getEngine()->getClickedPos(event->position().x(), event->position().y());
+                 if (hit_posWS.has_value()) {
+                     auto pivot = hit_posWS.value();
+                     auto new_pos = (pos - pivot) * scale + pivot;
+                     setPos(new_pos);
+                 }
+                 else {
+-                    auto posOnFloorWS = screenHitOnFloorWS(event->x() / res().x(), event->y() / res().y());
++                    auto posOnFloorWS = screenHitOnFloorWS(event->position().x() / res().x(), event->position().y() / res().y());
+                     auto pivot = posOnFloorWS;
+                     if (dot((pivot - pos), getViewDir()) > 0) {
+                         auto translate = (pivot - pos) * (1 - scale);
+@@ -450,7 +450,7 @@ void CameraControl::fakeWheelEvent(QWhee
+                         setPos(new_pos);
+                     }
+                     else {
+-                        auto translate = screenPosToRayWS(event->x() / res().x(), event->y() / res().y()) * getPos().y * (1 - scale);
++                        auto translate = screenPosToRayWS(event->position().x() / res().x(), event->position().y() / res().y()) * getPos().y * (1 - scale);
+                         if (getPos().y < 0) {
+                             translate *= -1;
+                         }
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_displaywidget.cpp b/graphics/zeno/files/patch-ui_zenoedit_viewport_displaywidget.cpp
new file mode 100644
index 000000000000..97d6edcec938
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_displaywidget.cpp
@@ -0,0 +1,34 @@
+--- ui/zenoedit/viewport/displaywidget.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/displaywidget.cpp
+@@ -141,7 +141,7 @@ void DisplayWidget::resizeViewport(QSize
+ {
+     if (m_bGLView) {
+         m_glView->resizeGL(sz.width(), sz.height());
+-        m_glView->updateGL();
++        m_glView->update();
+     } else {
+         //todo: for optix view
+     }
+@@ -1026,7 +1026,7 @@ void DisplayWidget::sendTaskToServer(con
+     if (!path.startsWith("O:") && !path.startsWith("M:") && !path.startsWith("P:"))
+     {
+         //copy zsg
+-        QString destFileDir = "O:/sendToServer/" + info.taskName + QString::number(QDateTime::currentDateTime().toTime_t());
++        QString destFileDir = "O:/sendToServer/" + info.taskName + QString::number(QDateTime::currentDateTime().toSecsSinceEpoch());
+         QFileInfo fileInfo(path);
+         QString fileName = fileInfo.fileName();
+         QDir dir(destFileDir);
+@@ -1208,9 +1208,10 @@ bool DisplayWidget::onRecord_cmd(const V
+             QByteArray content = recordcmd->readLine();
+             if (content.startsWith("[record]")) {
+                 if (content.indexOf("frame") != -1) {
+-                    QRegExp rx("frame (\\d+)");
+-                    if (rx.indexIn(content) != -1) {
+-                        QStringList caps = rx.capturedTexts();
++                    static const QRegularExpression rx("frame (\\d+)");
++                    QRegularExpressionMatch match = rx.match(QString::fromUtf8(content));
++                    if (match.hasMatch()) {
++                        QStringList caps = match.capturedTexts();
+                         ZASSERT_EXIT(caps.size() == 2);
+                         int frame_ = caps[1].toInt();
+                         dlgProc.onFrameFinished(frame_);
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_optixviewport.cpp b/graphics/zeno/files/patch-ui_zenoedit_viewport_optixviewport.cpp
new file mode 100644
index 000000000000..089e43866264
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_optixviewport.cpp
@@ -0,0 +1,29 @@
+--- ui/zenoedit/viewport/optixviewport.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/optixviewport.cpp
+@@ -606,7 +606,7 @@ void ZOptixViewport::resizeEvent(QResize
+ 
+ void ZOptixViewport::mousePressEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = true;
+         setSimpleRenderOption();
+     }
+@@ -617,7 +617,7 @@ void ZOptixViewport::mousePressEvent(QMo
+ 
+ void ZOptixViewport::mouseReleaseEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = false;
+     }
+     _base::mouseReleaseEvent(event);
+@@ -627,7 +627,7 @@ void ZOptixViewport::mouseReleaseEvent(Q
+ 
+ void ZOptixViewport::mouseMoveEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = true;
+     }
+     setSimpleRenderOption();
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.cpp b/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.cpp
new file mode 100644
index 000000000000..19b7e9ec4fdf
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.cpp
@@ -0,0 +1,79 @@
+--- ui/zenoedit/viewport/viewportwidget.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/viewportwidget.cpp
+@@ -34,7 +34,7 @@ using std::unordered_map;
+ 
+ 
+ ViewportWidget::ViewportWidget(QWidget* parent)
+-    : QGLWidget(parent)
++    : QOpenGLWidget(parent)
+     , m_camera(nullptr)
+     , updateLightOnce(true)
+     , m_pauseRenderDally(new QTimer)
+@@ -47,11 +47,11 @@ ViewportWidget::ViewportWidget(QWidget*
+     m_picker = std::make_shared<zeno::Picker>(this);
+     m_fakeTrans = std::make_shared<zeno::FakeTransformer>(this);
+ 
+-    QGLFormat fmt;
++    QSurfaceFormat fmt;
+     int nsamples = 16;  // TODO: adjust in a zhouhang-panel
+     fmt.setSamples(nsamples);
+     fmt.setVersion(3, 2);
+-    fmt.setProfile(QGLFormat::CoreProfile);
++    fmt.setProfile(QSurfaceFormat::CoreProfile);
+     setFormat(fmt);
+ 
+     // https://blog.csdn.net/zhujiangm/article/details/90760744
+@@ -113,7 +113,9 @@ void ViewportWidget::setViewWidgetInfo(D
+ 
+ void ViewportWidget::glDrawForCommandLine()
+ {
+-    QGLWidget::glDraw();
++    // QOpenGLWidget has no glDraw(), grabFramebuffer() renders the frame
++    // synchronously and, unlike repaint(), also when the window is hidden
++    grabFramebuffer();
+ }
+ 
+ ViewportWidget::~ViewportWidget()
+@@ -144,9 +146,23 @@ void ViewportWidget::cleanUpView()
+ 
+ namespace {
+ struct OpenGLProcAddressHelper {
+-    inline static QGLContext *ctx;
++    inline static QOpenGLContext *ctx;
++    inline static void (QOPENGLF_APIENTRYP bindFramebuffer)(GLenum target, GLuint framebuffer);
++
++    // QOpenGLWidget renders into its own framebuffer object instead of the
++    // window framebuffer, so binding framebuffer 0 in zenovis has to go to
++    // that object, the same way QOpenGLFunctions::glBindFramebuffer() does it
++    static void QOPENGLF_APIENTRY bindDefaultFramebuffer(GLenum target, GLuint framebuffer) {
++        if (framebuffer == 0)
++            framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
++        bindFramebuffer(target, framebuffer);
++    }
+ 
+     static void *getProcAddress(const char *name) {
++        if (qstrcmp(name, "glBindFramebuffer") == 0) {
++            bindFramebuffer = reinterpret_cast<decltype(bindFramebuffer)>(ctx->getProcAddress(name));
++            return (void *)bindDefaultFramebuffer;
++        }
+         return (void *)ctx->getProcAddress(name);
+     }
+ };
+@@ -286,7 +302,7 @@ void ViewportWidget::wheelEvent(QWheelEv
+ }
+ 
+ void ViewportWidget::mouseReleaseEvent(QMouseEvent *event) {
+-    if(event->button() == Qt::MidButton){
++    if(event->button() == Qt::MiddleButton){
+         m_bMovingCamera = false;
+     }
+     _base::mouseReleaseEvent(event);
+@@ -419,7 +435,7 @@ void ViewportWidget::keyReleaseEvent(QKe
+     }
+ }
+ 
+-void ViewportWidget::enterEvent(QEvent *event) {
++void ViewportWidget::enterEvent(QEnterEvent* event) {
+     setFocus();
+     QWidget::enterEvent(event);
+ }
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.h b/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.h
new file mode 100644
index 000000000000..e298bbb3e091
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_viewportwidget.h
@@ -0,0 +1,32 @@
+--- ui/zenoedit/viewport/viewportwidget.h.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/viewportwidget.h
+@@ -3,6 +3,7 @@
+ 
+ #include <QtWidgets>
+ #include <QtOpenGL>
++#include <QOpenGLWidget>
+ #include "common.h"
+ #include "recordvideomgr.h"
+ #include "dock/docktabcontent.h"
+@@ -18,10 +19,10 @@ class ViewportWidget;
+ class Picker;
+ class CameraControl;
+ 
+-class ViewportWidget : public QGLWidget
++class ViewportWidget : public QOpenGLWidget
+ {
+     Q_OBJECT
+-    typedef QGLWidget _base;
++    typedef QOpenGLWidget _base;
+ public:
+     ViewportWidget(QWidget* parent = nullptr);
+     ~ViewportWidget();
+@@ -63,7 +64,7 @@ protected:
+     void mouseReleaseEvent(QMouseEvent* event) override;
+     void mouseMoveEvent(QMouseEvent* event) override;
+     void mouseDoubleClickEvent(QMouseEvent* event) override;
+-    void enterEvent(QEvent * event) override;
++    void enterEvent(QEnterEvent* event) override;
+     void wheelEvent(QWheelEvent* event) override;
+     void keyPressEvent(QKeyEvent* event) override;
+     void keyReleaseEvent(QKeyEvent* event) override;
diff --git a/graphics/zeno/files/patch-ui_zenoedit_viewport_zoptixviewport.cpp b/graphics/zeno/files/patch-ui_zenoedit_viewport_zoptixviewport.cpp
new file mode 100644
index 000000000000..8de7dfaa175d
--- /dev/null
+++ b/graphics/zeno/files/patch-ui_zenoedit_viewport_zoptixviewport.cpp
@@ -0,0 +1,29 @@
+--- ui/zenoedit/viewport/zoptixviewport.cpp.orig	2024-09-30 13:46:54 UTC
++++ ui/zenoedit/viewport/zoptixviewport.cpp
+@@ -197,7 +197,7 @@ void ZOptixProcViewport::resizeEvent(QRe
+ 
+ void ZOptixProcViewport::mousePressEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = true;
+         setSimpleRenderOption();
+         pauseWorkerAndResume();
+@@ -209,7 +209,7 @@ void ZOptixProcViewport::mousePressEvent
+ 
+ void ZOptixProcViewport::mouseReleaseEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = false;
+         m_worker->work();
+     }
+@@ -220,7 +220,7 @@ void ZOptixProcViewport::mouseReleaseEve
+ 
+ void ZOptixProcViewport::mouseMoveEvent(QMouseEvent* event)
+ {
+-    if (event->button() == Qt::MidButton) {
++    if (event->button() == Qt::MiddleButton) {
+         m_bMovingCamera = true;
+         pauseWorkerAndResume();
+     }
diff --git a/graphics/zeno/files/patch-ui_zenoedit_zenoapplication.cpp b/graphics/zeno/files/patch-ui_zenoedit_zenoapplication.cpp
index 6baf22722bb2..e9ba840d14a7 100644
--- a/graphics/zeno/files/patch-ui_zenoedit_zenoapplication.cpp
+++ b/graphics/zeno/files/patch-ui_zenoedit_zenoapplication.cpp
@@ -1,6 +1,6 @@
 --- ui/zenoedit/zenoapplication.cpp.orig	2024-09-30 13:46:54 UTC
 +++ ui/zenoedit/zenoapplication.cpp
-@@ -13,9 +13,9 @@ ZenoApplication::ZenoApplication(int &argc, char **arg
+@@ -13,9 +13,9 @@
  
  ZenoApplication::ZenoApplication(int &argc, char **argv)
      : QApplication(argc, argv)
@@ -12,7 +12,18 @@
      , m_bUIApp(true)
  {
      initMetaTypes();
-@@ -175,7 +175,7 @@ QStandardItemModel* ZenoApplication::logModel() const
+@@ -90,8 +90,8 @@ QString ZenoApplication::readQss(const Q
+ 
+ void ZenoApplication::initMetaTypes() 
+ {
+-    QMetaType::registerEqualsComparator<UI_VECTYPE>();
+-    QMetaType::registerEqualsComparator<CURVES_DATA>();
++    // Qt 6 registers the equality comparators of UI_VECTYPE and CURVES_DATA
++    // on its own, QMetaType::registerEqualsComparator() is gone
+ }
+ 
+ void ZenoApplication::initStyleSheets()
+@@ -175,7 +175,7 @@ QStandardItemModel* ZenoApplication::log
      return graphsManagment()->logModel();
  }
  
diff --git a/graphics/zeno/files/patch-ui_zenoedit_zenomainwindow.cpp b/graphics/zeno/files/patch-ui_zenoedit_zenomainwindow.cpp
index 74587c14370c..473a3fa1938c 100644
*** 998 LINES SKIPPED ***