Created
January 5, 2024 11:14
-
-
Save torarnv/1f9c0ffbc4d6f085116e212cb1292375 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 8a808da0623287a9ba41519b3dd6403538f33c28 | |
Author: Tor Arne Vestbø <tor.arne.vestbo@qt.io> | |
Date: Wed Jan 3 19:08:02 2024 +0100 | |
macOS: Reset save dialog extension when resetting file name filter | |
We map QFileDialog name filters to NSSavePanel.allowedFileTypes, for | |
example turning "Text Files (*.txt)" into allowedFileTypes = @[@"txt"]. | |
In this case, the NSSavePanel will automatically add the extension to | |
the user's file name, if they just type "foo". | |
When a filter allows all files, we reset the allowedFileTypes to nil, | |
but this does not reset the automatically added extension, so if the | |
user switches from one filter (*.txt) to another (*.*), the file name | |
will still have a .txt extension. | |
This is problematic when the save panel's file name field does not | |
show the extension to the user, which can happen automatically if | |
the user types an initial file name without an extension, overriding | |
what we've asked by setting extensionHidden=NO. When that happens, | |
the user is shown "foo", but the actual file name is "foo.txt". | |
To mitigate this confusing situation we do a round-trip via the | |
UTTypeDirectory content type, which is a valid type without any | |
extension. This forces the save panel to remove any extensions | |
added automatically by previous filters. | |
Pick-to: 6.7 | |
Change-Id: Ia17a8c2734eff656116ef77a9813113a5076e9cc | |
diff --git a/cmake/QtFrameworkHelpers.cmake b/cmake/QtFrameworkHelpers.cmake | |
index c546dcd5b87..c15f74e5422 100644 | |
--- a/cmake/QtFrameworkHelpers.cmake | |
+++ b/cmake/QtFrameworkHelpers.cmake | |
@@ -37,6 +37,7 @@ macro(qt_find_apple_system_frameworks) | |
qt_internal_find_apple_system_framework(FWContacts Contacts) | |
qt_internal_find_apple_system_framework(FWEventKit EventKit) | |
qt_internal_find_apple_system_framework(FWHealthKit HealthKit) | |
+ qt_internal_find_apple_system_framework(FWUniformTypeIdentifiers UniformTypeIdentifiers) | |
endif() | |
endmacro() | |
diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt | |
index af8434daaa5..92e681d8fb7 100644 | |
--- a/src/plugins/platforms/cocoa/CMakeLists.txt | |
+++ b/src/plugins/platforms/cocoa/CMakeLists.txt | |
@@ -56,6 +56,7 @@ qt_internal_add_plugin(QCocoaIntegrationPlugin | |
${FWIOSurface} | |
${FWMetal} | |
${FWQuartzCore} | |
+ ${FWUniformTypeIdentifiers} | |
Qt::Core | |
Qt::CorePrivate | |
Qt::Gui | |
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | |
index 15ec46a453c..842bc336c24 100644 | |
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | |
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | |
@@ -27,6 +27,8 @@ | |
#include <qpa/qplatformtheme.h> | |
#include <qpa/qplatformnativeinterface.h> | |
+#include <UniformTypeIdentifiers/UniformTypeIdentifiers.h> | |
+ | |
QT_USE_NAMESPACE | |
using namespace Qt::StringLiterals; | |
@@ -355,6 +357,24 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; | |
m_panel.allowedFileTypes = [self computeAllowedFileTypes]; | |
+ // Setting allowedFileTypes to nil is not enough to reset any | |
+ // automatically added extension based on a previous filter. | |
+ // This is problematic because extensions can in some cases | |
+ // be hidden from the user, resulting in confusion when the | |
+ // resulting file name doesn't match the current empty filter. | |
+ // We work around this by temporarily resetting the allowed | |
+ // content type to one without an extension, which forces | |
+ // the save panel to update and remove the extension. | |
+ const bool nameFieldHasExtension = m_panel.nameFieldStringValue.pathExtension.length > 0; | |
+ if (!m_panel.allowedFileTypes && !nameFieldHasExtension && !openpanel_cast(m_panel)) { | |
+ if (!UTTypeDirectory.preferredFilenameExtension) { | |
+ m_panel.allowedContentTypes = @[ UTTypeDirectory ]; | |
+ m_panel.allowedFileTypes = nil; | |
+ } else { | |
+ qWarning() << "UTTypeDirectory unexpectedly reported an extension"; | |
+ } | |
+ } | |
+ | |
m_panel.showsHiddenFiles = m_options->filter().testFlag(QDir::Hidden); | |
if (m_panel.visible) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment