From dfcc9bfb7cbffb9689221d14fbe5e89b587d98f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20A=2E=20Alto=C3=A9=20Falqueto?= Date: Wed, 8 Jul 2026 10:45:59 -0300 Subject: [PATCH] Fixed #33341, #33559: robustify Linux PDF export against file dialog quirks Two independent fixes for PDF export failing/crashing on Linux: - src/app/main.cpp: only force QT_QPA_PLATFORMTHEME=gtk3 when the user hasn't already set it. gtk3 was forced unconditionally to fix keyboard input in the legacy Qt file dialog (#13113), but this also silently overrode any theme the user configured (e.g. "xdgdesktopportal" for proper portal/sandboxed dialog support), which is a likely contributor to file dialogs not respecting the user's desktop environment. The default (gtk3) is unchanged for users who don't set this variable, so #13113 is not reintroduced. QT_QPA_PLATFORM=xcb is left untouched, since it fixes unrelated Wayland issues (VST crashes #28446, panel docking #28352). - src/project/internal/exportprojectscenario.cpp: after the file dialog returns a save path, force the expected export suffix if the path doesn't already have one of the format's known suffixes. On some Linux native/portal dialogs the extension isn't auto-appended when the user doesn't type one, which previously left exportScores() unable to find a writer for the path, causing the export to silently fail. A companion fix in muse_framework (musescore/muse_framework#139) makes the underlying file dialog request a default suffix directly, which addresses the same root cause at the source for the single-format case; this commit adds a safety net that's independent of dialog backend. Resolves: #33341 Resolves: #33559 --- src/app/main.cpp | 6 +++++- src/project/internal/exportprojectscenario.cpp | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 32651d643063d..5b767c32c83f3 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -100,7 +100,11 @@ int main(int argc, char** argv) } #ifdef Q_OS_LINUX - if (qEnvironmentVariable("MU_QT_QPA_PLATFORM") != "offscreen") { + // NOTE: gtk3 is forced by default because it fixed keyboard input in file dialogs (#13113). + // Respect an explicitly configured theme (e.g. "xdgdesktopportal") instead of overriding it, + // so desktop environments that rely on the portal for native/sandboxed dialogs keep working. + if (qEnvironmentVariable("MU_QT_QPA_PLATFORM") != "offscreen" + && !qEnvironmentVariableIsSet("QT_QPA_PLATFORMTHEME")) { qputenv("QT_QPA_PLATFORMTHEME", "gtk3"); } diff --git a/src/project/internal/exportprojectscenario.cpp b/src/project/internal/exportprojectscenario.cpp index 74fcc4c0253a7..2d64b098c480a 100644 --- a/src/project/internal/exportprojectscenario.cpp +++ b/src/project/internal/exportprojectscenario.cpp @@ -99,6 +99,20 @@ RetVal ExportProjectScenario::askExportPath(const INotationPtr RetVal exportPath; exportPath.val = interactive()->selectSavingFileSync(muse::trc("project/export", "Export"), defaultPath, exportType.filter(), isCreatingOnlyOneFile); + + if (!exportPath.val.empty()) { + // Some Linux file dialogs don't auto-append the extension the user didn't type, + // which would otherwise leave us without a writer for this path in exportScores(). + std::string actualSuffix = io::suffix(exportPath.val); + bool hasKnownSuffix = std::find_if(exportType.suffixes.cbegin(), exportType.suffixes.cend(), [&actualSuffix](const QString& s) { + return s.toStdString() == actualSuffix; + }) != exportType.suffixes.cend(); + + if (!hasKnownSuffix) { + exportPath.val = exportPath.val.appendingSuffix(exportType.suffixes.front().toStdString()); + } + } + exportPath.ret = !exportPath.val.empty(); return exportPath;