From e9e944f77a2a58d0556f88d4504e569ff37feece Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 08:51:54 +1000 Subject: [PATCH 1/7] ifcviewer: include MetalSurface_mac.h before its use (fix macOS build) createWgpuSurface() calls wgpu_macos_attach_metal_layer() in the Q_OS_MAC branch at the top of the file, but the only #include of MetalSurface_mac.h sat ~450 lines below the call site, so macOS builds failed with 'use of undeclared identifier'. The header self-guards on __APPLE__, so move the include up into the early platform block next to ; the lone call site is the sole consumer, so the late include was dead. Co-Authored-By: Claude Opus 4.8 --- src/ifcviewer/ViewportWindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ifcviewer/ViewportWindow.cpp b/src/ifcviewer/ViewportWindow.cpp index c1acab8bbc..6e70280173 100644 --- a/src/ifcviewer/ViewportWindow.cpp +++ b/src/ifcviewer/ViewportWindow.cpp @@ -45,6 +45,10 @@ #define NOMCX #define NOSERVICE #include +#elif defined(Q_OS_MAC) +// Cocoa bridge declared here, implemented in the adjacent .mm file. Must be +// visible before createWgpuSurface() below calls wgpu_macos_attach_metal_layer. +#include "MetalSurface_mac.h" #endif #include @@ -832,10 +836,6 @@ bool ViewportWindow::initWgpu() { # define WIN32_LEAN_AND_MEAN # endif # include -#elif defined(Q_OS_MAC) -// Cocoa bridge declared in MetalSurface_mac.h, implemented in the -// adjacent .mm file. Keeps Objective-C out of this pure-C++ TU. -# include "MetalSurface_mac.h" #endif // Private bool createSurface() removed in #84-l — its body is now From 014baab7089099c417deddf398ac8cab8572f9b4 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 09:07:02 +1000 Subject: [PATCH 2/7] ci: provision Rocky jobs to build+package BonsaiViewer & Rust connector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two gaps left when BonsaiViewer and its Rust connector were newly added to the Rocky CI jobs (May–Jun), neither previously exercised there: 1. Rust: the autodesk connector was rewritten from a PyInstaller Python app to a Rust crate, so packaging/build.py now runs 'cargo build --release'. Neither Rocky workflow installed a toolchain. Add rustup (stable, matching the dedicated dtolnay/rust-toolchain@stable workflow) to both x86 and ARM. 2. ARM glibc: aqt's official Qt6 ARM binaries link glibc 2.38, which Rocky 9 (glibc 2.34) can't load — moc fails, breaking IfcViewer_autogen. Move the ARM job to Rocky 10 (glibc 2.39). The legacy arm64v8/rockylinux image stopped at 9, so use rockylinux/rockylinux:10 (multi-arch, has arm64). Rocky 10 defaults to Python 3.12 and drops python3.11, so the script-runner references move python3.11 -> python3 (system Python only runs helper scripts; ifcopenshell is built against uv's Python). Bump the ccache key to rockylinux10. x86 stays on Rocky 9 to keep its lower glibc floor for end users. The rockylinux9-arm64 build-outputs deps branch is kept as-is: Rocky 9 deps are forward-compatible on Rocky 10, and no rocky10 branch exists yet. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build_rocky.yml | 9 +++++++++ .github/workflows/build_rocky_arm.yml | 23 ++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_rocky.yml b/.github/workflows/build_rocky.yml index a5b2524b21..4a9e5807fb 100644 --- a/.github/workflows/build_rocky.yml +++ b/.github/workflows/build_rocky.yml @@ -30,6 +30,15 @@ jobs: git config --global --add safe.directory '*' python3.11 -c "import tkinter; print('Tk', tkinter.TkVersion)" + - name: Install Rust + # The bonsaiviewer-autodesk connector is a Rust crate; the "Package + # .zip archives" step below runs `cargo build --release` via + # packaging/build.py. Match the dedicated connector workflow's stable + # toolchain (dtolnay/rust-toolchain@stable). + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + - name: Install aws cli run: | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" diff --git a/.github/workflows/build_rocky_arm.yml b/.github/workflows/build_rocky_arm.yml index 618af9c9e8..e895ec3dbf 100644 --- a/.github/workflows/build_rocky_arm.yml +++ b/.github/workflows/build_rocky_arm.yml @@ -6,7 +6,11 @@ on: jobs: build_ifcopenshell: runs-on: ubuntu-22.04-arm - container: arm64v8/rockylinux:9 + # Rocky 10 (glibc 2.39) — aqt's official Qt6 ARM binaries are built + # against glibc 2.38, which Rocky 9 (glibc 2.34) can't run (moc fails to + # load). The legacy arm64v8/rockylinux Docker image stopped at 9; Rocky 10 + # is published under the rockylinux/rockylinux namespace. + container: rockylinux/rockylinux:10 steps: - name: Set up uv @@ -25,10 +29,19 @@ jobs: sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ findutils xz byacc patchelf libxkbcommon-devel \ - python3.11 python3.11-pip python3.11-tkinter + python3-tkinter python3 -m pip install typing_extensions aqtinstall git config --global --add safe.directory '*' - python3.11 -c "import tkinter; print('Tk', tkinter.TkVersion)" + python3 -c "import tkinter; print('Tk', tkinter.TkVersion)" + + - name: Install Rust + # The bonsaiviewer-autodesk connector is a Rust crate; the "Package + # .zip archives" step below runs `cargo build --release` via + # packaging/build.py. Match the dedicated connector workflow's stable + # toolchain (dtolnay/rust-toolchain@stable). + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Install aws cli run: | @@ -60,7 +73,7 @@ jobs: - name: ccache uses: hendrikmuhs/ccache-action@v1.2.23 with: - key: ubuntu-22.04-${{ runner.arch }}-rockylinux9 + key: ubuntu-22.04-${{ runner.arch }}-rockylinux10 - name: Run Build Script shell: bash @@ -101,7 +114,7 @@ jobs: # connector.json into dist/autodesk/. Same on-disk shape as the # old PyInstaller flow so the symlink + zip steps below # continue to work unchanged. - python3.11 src/bonsaiviewer-autodesk/packaging/build.py + python3 src/bonsaiviewer-autodesk/packaging/build.py autodesk_connector_dir="$PWD/src/bonsaiviewer-autodesk/dist/autodesk" test -d "$autodesk_connector_dir" From b72daf13301889d014a15e3623cb61713bc0956b Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 09:21:42 +1000 Subject: [PATCH 3/7] ci(arm): set PATH in the Rocky 10 container so run steps find sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The community rockylinux/rockylinux:10 image omits PATH from its image config, unlike the old Docker Official arm64v8/rockylinux:9. GitHub Actions derives each run step's PATH from that config, so with no PATH the shell exec (docker exec ... sh -e {0}) fails with exit 127, 'exec: sh: not found' — it broke before any build logic ran. Restore a standard PATH via the container env; the runner still layers GITHUB_PATH additions (uv, cargo) on top. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build_rocky_arm.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_rocky_arm.yml b/.github/workflows/build_rocky_arm.yml index e895ec3dbf..edb850579f 100644 --- a/.github/workflows/build_rocky_arm.yml +++ b/.github/workflows/build_rocky_arm.yml @@ -10,7 +10,15 @@ jobs: # against glibc 2.38, which Rocky 9 (glibc 2.34) can't run (moc fails to # load). The legacy arm64v8/rockylinux Docker image stopped at 9; Rocky 10 # is published under the rockylinux/rockylinux namespace. - container: rockylinux/rockylinux:10 + container: + image: rockylinux/rockylinux:10 + # The community rockylinux image omits PATH from its config (the old + # Docker Official arm64v8/rockylinux set it), so GitHub Actions `run:` + # steps fail with `exec: "sh": not found` — docker exec has no /usr/bin + # to resolve the shell. Restore a standard PATH; GITHUB_PATH prepends + # (uv, cargo) are still layered on top by the runner. + env: + PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin steps: - name: Set up uv From 0908a5b5a34bb848b65a989806ad2aa261742ff3 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 09:31:46 +1000 Subject: [PATCH 4/7] ci: install dbus-devel for the Rust connector's keyring backend cargo build of bonsaiviewer-autodesk pulls dbus-secret-service (the Linux OS-keyring backend for credential storage) -> dbus -> libdbus-sys, whose build.rs needs dbus-1.pc via pkg-config. GitHub's ubuntu runners ship libdbus-1-dev, so the dedicated connector workflow never needed it; the minimal Rocky container doesn't. Add dbus-devel to both Rocky jobs (pkg-config is already present). This was the last step after a fully successful C++ build + cargo compile. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build_rocky.yml | 3 ++- .github/workflows/build_rocky_arm.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_rocky.yml b/.github/workflows/build_rocky.yml index 4a9e5807fb..2c9ed0158b 100644 --- a/.github/workflows/build_rocky.yml +++ b/.github/workflows/build_rocky.yml @@ -25,7 +25,8 @@ jobs: sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ findutils xz byacc patchelf libxkbcommon-devel \ - python3.11 python3.11-pip python3.11-tkinter + python3.11 python3.11-pip python3.11-tkinter \ + dbus-devel python3 -m pip install typing_extensions aqtinstall git config --global --add safe.directory '*' python3.11 -c "import tkinter; print('Tk', tkinter.TkVersion)" diff --git a/.github/workflows/build_rocky_arm.yml b/.github/workflows/build_rocky_arm.yml index edb850579f..f026372afa 100644 --- a/.github/workflows/build_rocky_arm.yml +++ b/.github/workflows/build_rocky_arm.yml @@ -37,7 +37,7 @@ jobs: sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ findutils xz byacc patchelf libxkbcommon-devel \ - python3-tkinter + python3-tkinter dbus-devel python3 -m pip install typing_extensions aqtinstall git config --global --add safe.directory '*' python3 -c "import tkinter; print('Tk', tkinter.TkVersion)" From 21ba06cd9490a15da9455e12461ed2ab470166f4 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 09:49:46 +1000 Subject: [PATCH 5/7] ci: install FLTK's X11/pango/cairo + static libstdc++ for the connector link With dbus-devel added, the connector's Rust code compiles fully and reaches the final link, which fails: the bundled FLTK GUI toolkit needs the X11 extension, pango and cairo shared libs, plus libsupc++.a. ld reports every unresolved -l at once, so this is the complete set: -lXext -lXinerama -lXcursor -lXrender -lXfixes -lXft -lpango-1.0 -lpangoxft-1.0 -lpangocairo-1.0 -lcairo -lsupc++ The X/pango/cairo -devel packages are in AppStream; libstdc++-static (libsupc++.a) is in CRB, so enable it for the transaction. GitHub's ubuntu runners ship all of this, which is why the dedicated connector workflow never needed it. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build_rocky.yml | 9 +++++++-- .github/workflows/build_rocky_arm.yml | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_rocky.yml b/.github/workflows/build_rocky.yml index 2c9ed0158b..2841ad6e34 100644 --- a/.github/workflows/build_rocky.yml +++ b/.github/workflows/build_rocky.yml @@ -20,13 +20,18 @@ jobs: run: | dnf update -y dnf install -y epel-release - dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \ + # --enablerepo=crb: libstdc++-static (libsupc++.a, needed by the + # bundled FLTK link) lives in Rocky's CodeReady Builder repo, which + # is disabled by default. + dnf install -y --enablerepo=crb gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ findutils xz byacc patchelf libxkbcommon-devel \ python3.11 python3.11-pip python3.11-tkinter \ - dbus-devel + dbus-devel \ + libXext-devel libXinerama-devel libXcursor-devel libXrender-devel \ + libXfixes-devel libXft-devel pango-devel cairo-devel libstdc++-static python3 -m pip install typing_extensions aqtinstall git config --global --add safe.directory '*' python3.11 -c "import tkinter; print('Tk', tkinter.TkVersion)" diff --git a/.github/workflows/build_rocky_arm.yml b/.github/workflows/build_rocky_arm.yml index f026372afa..9d6b5b9754 100644 --- a/.github/workflows/build_rocky_arm.yml +++ b/.github/workflows/build_rocky_arm.yml @@ -32,12 +32,17 @@ jobs: run: | dnf update -y dnf install -y epel-release - dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \ + # --enablerepo=crb: libstdc++-static (libsupc++.a, needed by the + # bundled FLTK link) lives in Rocky's CodeReady Builder repo, which + # is disabled by default. + dnf install -y --enablerepo=crb gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ findutils xz byacc patchelf libxkbcommon-devel \ - python3-tkinter dbus-devel + python3-tkinter dbus-devel \ + libXext-devel libXinerama-devel libXcursor-devel libXrender-devel \ + libXfixes-devel libXft-devel pango-devel cairo-devel libstdc++-static python3 -m pip install typing_extensions aqtinstall git config --global --add safe.directory '*' python3 -c "import tkinter; print('Tk', tkinter.TkVersion)" From a63bb999c129952dfdfa1575e7526896b5c31d3a Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 11:33:37 +1000 Subject: [PATCH 6/7] models: rename a model's display name from the panel context menu Adds a 'Rename' action to the model (non-group) context menu, mirroring renameGroup: prompts via QInputDialog, trims, and calls setModelDisplayName + notifyFederationChanged. The Federation already emits modelChanged, so the panel item text updates in place. Co-Authored-By: Claude Opus 4.8 --- src/bonsaiviewer/modules/models/Commands.cpp | 16 ++++++++++++++++ src/bonsaiviewer/modules/models/Commands.h | 1 + src/bonsaiviewer/modules/models/Panel.cpp | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/src/bonsaiviewer/modules/models/Commands.cpp b/src/bonsaiviewer/modules/models/Commands.cpp index 4ae98e4176..ca75273200 100644 --- a/src/bonsaiviewer/modules/models/Commands.cpp +++ b/src/bonsaiviewer/modules/models/Commands.cpp @@ -187,6 +187,22 @@ void renameGroup(SessionState& session, QWidget& host, const QString& group_id) session.setStatusMessage("Models", "Group renamed"); } +void renameModel(SessionState& session, QWidget& host, const QString& model_id) { + const Federation::Model* model = session.federation()->findById(model_id); + if (!model) return; + + bool ok = false; + const QString name = QInputDialog::getText( + &host, "Rename Model", "Model name:", QLineEdit::Normal, model->display_name, &ok); + if (!ok) return; + const QString trimmed = name.trimmed(); + if (trimmed.isEmpty()) return; + + session.federation()->setModelDisplayName(model_id, trimmed); + session.notifyFederationChanged(); + session.setStatusMessage("Models", "Model renamed"); +} + void moveGroup(SessionState& session, const QString& id, const QString& parent_group_id) { session.federation()->setGroupParent(id, parent_group_id); session.notifyFederationChanged(); diff --git a/src/bonsaiviewer/modules/models/Commands.h b/src/bonsaiviewer/modules/models/Commands.h index 78672e713e..15be7e77ed 100644 --- a/src/bonsaiviewer/modules/models/Commands.h +++ b/src/bonsaiviewer/modules/models/Commands.h @@ -55,6 +55,7 @@ namespace bonsaiviewer::modules::models::commands { void toggleVisibility(SessionState& session, ItemKind kind, const QString& id); void addGroup(SessionState& session, QWidget& host, const QString& parent_group_id); void renameGroup(SessionState& session, QWidget& host, const QString& group_id); +void renameModel(SessionState& session, QWidget& host, const QString& model_id); void moveGroup(SessionState& session, const QString& id, const QString& parent_group_id); void moveModels(SessionState& session, const QStringList& ids, const QString& parent_group_id); void removeGroup(SessionState& session, QWidget& host, const QString& group_id); diff --git a/src/bonsaiviewer/modules/models/Panel.cpp b/src/bonsaiviewer/modules/models/Panel.cpp index 509abf6fac..f6874acc9a 100644 --- a/src/bonsaiviewer/modules/models/Panel.cpp +++ b/src/bonsaiviewer/modules/models/Panel.cpp @@ -321,6 +321,12 @@ ModelsPanel::ModelsPanel(bonsaiviewer::SessionState* session_state, parent_group_id = idOf(parent_index); } + QAction* rename = menu.addAction( + components::icons::makeSvgIcon(":/icons/cube.svg"), "Rename"); + connect(rename, &QAction::triggered, this, [this, id]() { + commands::renameModel(*session_state_, *this, id); + }); + QAction* add_group = menu.addAction( components::icons::makeSvgIcon(":/icons/folder-plus.svg"), "New Group"); connect(add_group, &QAction::triggered, this, [this, parent_group_id]() { From 402591e71c23821b3ea8012bf1601c37a2e1975f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 10 Jul 2026 12:53:32 +1000 Subject: [PATCH 7/7] ci: restore --shared on the Rocky builds (undo datamodel-merge regression) The datamodel-v1.0 merge (cf05bbd1b) overwrote build_rocky.yml with a version that switched python3 -> uv run but dropped the --shared flag that a91b1da28 ("Reduce Rocky package size") had added. build_osx.yml kept it (ddee88bed). Without --shared, nix/build-all.py builds IfcOpenShell as static libs, so each of the ~40 plug-in .so files (schemas x8, kernels, mappings, serializers, writers) statically embeds a full copy of libIfcParse + libIfcGeom. The data-model rewrite made those base libs much larger, so the duplication ballooned the Linux packages (~2-3x). With --shared the plug-ins dynamically reference the shared libIfcParse/libIfcGeom instead. Restores the same size reduction macOS already has. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build_rocky.yml | 2 +- .github/workflows/build_rocky_arm.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_rocky.yml b/.github/workflows/build_rocky.yml index 2841ad6e34..f36f68ebe4 100644 --- a/.github/workflows/build_rocky.yml +++ b/.github/workflows/build_rocky.yml @@ -81,7 +81,7 @@ jobs: shell: bash run: | set -o pipefail - CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release BUILD_BONSAIVIEWER=ON uv run --with typing_extensions --with aqtinstall ./nix/build-all.py -v --diskcleanup 2>&1 | tee build.log + CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release BUILD_BONSAIVIEWER=ON uv run --with typing_extensions --with aqtinstall ./nix/build-all.py -v --diskcleanup --shared 2>&1 | tee build.log - name: Upload Build Logs if: always() diff --git a/.github/workflows/build_rocky_arm.yml b/.github/workflows/build_rocky_arm.yml index 9d6b5b9754..2fe804505b 100644 --- a/.github/workflows/build_rocky_arm.yml +++ b/.github/workflows/build_rocky_arm.yml @@ -92,7 +92,7 @@ jobs: shell: bash run: | set -o pipefail - CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release BUILD_BONSAIVIEWER=ON uv run --with typing_extensions --with aqtinstall ./nix/build-all.py -v --diskcleanup 2>&1 | tee build.log + CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release BUILD_BONSAIVIEWER=ON uv run --with typing_extensions --with aqtinstall ./nix/build-all.py -v --diskcleanup --shared 2>&1 | tee build.log - name: Upload Build Logs if: always()