macOS: Show extensions in file dialog when filtering on multi-part extension

File extensions with multiple parts, such as as ".tar.gz" are not natively
supported on macOS. Asking NSSavePanel to only allow file types with such
extensions confuses it severely, so we work around it by reducing the
native file name filter to the last component of the extension.

In this situation, we explicitly tell the NSSavePanel to show the full
filename, including the extension, so that the user can more easily
see what the final file name will be.

However, as part of 7f8a80ebf87cccb57da316202e5350eb5eca9d5d we ended
up changing the logic to count the number of possible extensions for
a given file type filter, not the number of parts in the extension.

The logic has now been restored, but moved to init, so that it applies
even if the initial filter is not a multi-part extension.

Task-number: QTBUG-109877
Pick-to: 6.5 6.2
Change-Id: I244cea1cc2977f8adf7e359ea7116bbfad0e1059
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit fd817c28a03f8b6743ea678c9edf3f8f047db627)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit b814f73fb6d837e7743620521d9d91dd624ccb3f)
This commit is contained in:
Tor Arne Vestbø 2023-12-15 16:24:51 +01:00 committed by Qt Cherry-pick Bot
parent 4f57f76a96
commit cab9a6166b

View File

@ -83,6 +83,28 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
QString selectedVisualNameFilter = m_options->initiallySelectedNameFilter();
m_selectedNameFilter = [self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter];
// Explicitly show extensions if we detect a filter
// that has a multi-part extension. This prevents
// confusing situations where the user clicks e.g.
// 'foo.tar.gz' and 'foo.tar' is populated in the
// file name box, but when then clicking save macOS
// will warn that the file needs to end in .gz,
// due to thinking the user tried to save the file
// as a 'tar' file instead. Unfortunately this
// property can only be set before the panel is
// shown, so we can't toggle it on and off based
// on the active filter.
m_panel.extensionHidden = [&]{
for (const auto &nameFilter : m_nameFilterDropDownList) {
const auto extensions = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
for (const auto &extension : extensions) {
if (extension.count('.') > 1)
return false;
}
}
return true;
}();
const QFileInfo sel(selectFile);
if (sel.isDir() && !sel.isBundle()){
m_panel.directoryURL = [NSURL fileURLWithPath:sel.absoluteFilePath().toNSString()];
@ -333,20 +355,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
m_panel.allowedFileTypes = [self computeAllowedFileTypes];
// Explicitly show extensions if we detect a filter
// that has a multi-part extension. This prevents
// confusing situations where the user clicks e.g.
// 'foo.tar.gz' and 'foo.tar' is populated in the
// file name box, but when then clicking save macOS
// will warn that the file needs to end in .gz,
// due to thinking the user tried to save the file
// as a 'tar' file instead. Unfortunately this
// property can only be set before the panel is
// shown, so it will not have any effect when
// switching filters in an already opened dialog.
if (m_panel.allowedFileTypes.count > 2)
m_panel.extensionHidden = NO;
m_panel.showsHiddenFiles = m_options->filter().testFlag(QDir::Hidden);
if (m_panel.visible)