macOS: Use single truth to track file dialog current directory

Unfortunately we can not rely on the file dialog panel for this,
via the directoryURL property, as that property has not yet been
updated during a panel:directoryDidChange: callback, resulting in
the directory reported to the user being the previous directory.

Since we already have to store the current directory for the case
where we haven't yet created the file dialog panel we re-use this
variable as the single place to store the current directory.

It's not clear whether we still need to normalize the strings
we get from the NSSavePanel, but the code has been left in,
even if the old callback code didn't normalize the path that
we then emitted as directoryEntered().

Fixes: QTBUG-119371
Change-Id: I379a47053302e73d5e06a2b941f40365c17390d5
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit a81395f2c604c84cd0e6f18165c766419f26b7ba)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 4075ffa498634c38771290275a3162df2c5c5e5b)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 9a380017370a624c34ec9a7a944052433244fae7)
(cherry picked from commit 45dd975f679ef81e5334c0c01610eeeac41c186b)
This commit is contained in:
Tor Arne Vestbø 2023-12-09 19:06:01 +01:00
parent dc10bfa2ff
commit 8df8ea3a2e
2 changed files with 22 additions and 24 deletions

View File

@ -74,6 +74,7 @@ public:
public: // for QNSOpenSavePanelDelegate public: // for QNSOpenSavePanelDelegate
void panelClosed(NSInteger result); void panelClosed(NSInteger result);
void panelDirectoryDidChange(NSString *path);
private: private:
void createNSOpenSavePanelDelegate(); void createNSOpenSavePanelDelegate();

View File

@ -87,8 +87,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
NSPopUpButton *m_popupButton; NSPopUpButton *m_popupButton;
NSTextField *m_textField; NSTextField *m_textField;
QCocoaFileDialogHelper *m_helper; QCocoaFileDialogHelper *m_helper;
NSString *m_currentDirectory;
SharedPointerFileDialogOptions m_options; SharedPointerFileDialogOptions m_options;
QString *m_currentSelection; QString *m_currentSelection;
QStringList *m_nameFilterDropDownList; QStringList *m_nameFilterDropDownList;
@ -118,10 +116,10 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
QFileInfo sel(selectFile); QFileInfo sel(selectFile);
if (sel.isDir() && !sel.isBundle()){ if (sel.isDir() && !sel.isBundle()){
m_currentDirectory = [sel.absoluteFilePath().toNSString() retain]; m_panel.directoryURL = [NSURL fileURLWithPath:sel.absoluteFilePath().toNSString()];
m_currentSelection = new QString; m_currentSelection = new QString;
} else { } else {
m_currentDirectory = [sel.absolutePath().toNSString() retain]; m_panel.directoryURL = [NSURL fileURLWithPath:sel.absolutePath().toNSString()];
m_currentSelection = new QString(sel.absoluteFilePath()); m_currentSelection = new QString(sel.absoluteFilePath());
} }
@ -131,7 +129,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
m_panel.accessoryView = m_nameFilterDropDownList->size() > 1 ? m_accessoryView : nil; m_panel.accessoryView = m_nameFilterDropDownList->size() > 1 ? m_accessoryView : nil;
// -setAccessoryView: can result in -panel:directoryDidChange: // -setAccessoryView: can result in -panel:directoryDidChange:
// resetting our m_currentDirectory, set the delegate // resetting our current directory. Set the delegate
// here to make sure it gets the correct value. // here to make sure it gets the correct value.
m_panel.delegate = self; m_panel.delegate = self;
@ -156,7 +154,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
[m_accessoryView release]; [m_accessoryView release];
m_panel.delegate = nil; m_panel.delegate = nil;
[m_panel release]; [m_panel release];
[m_currentDirectory release];
[super dealloc]; [super dealloc];
} }
@ -168,7 +165,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave) bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:m_panel shouldEnableURL:url]; || [self panel:m_panel shouldEnableURL:url];
m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @""; m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
[self updateProperties]; [self updateProperties];
@ -417,17 +413,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
if (!m_helper) if (!m_helper)
return; return;
if (!path || [path isEqual:NSNull.null] || !path.length) m_helper->panelDirectoryDidChange(path);
return;
if ([path isEqualToString:m_currentDirectory])
return;
[m_currentDirectory release];
m_currentDirectory = [path retain];
// ### fixme: priv->setLastVisitedDirectory(newDir);
emit m_helper->directoryEntered(QUrl::fromLocalFile(QString::fromNSString(m_currentDirectory)));
} }
/* /*
@ -554,21 +540,32 @@ void QCocoaFileDialogHelper::panelClosed(NSInteger result)
void QCocoaFileDialogHelper::setDirectory(const QUrl &directory) void QCocoaFileDialogHelper::setDirectory(const QUrl &directory)
{ {
m_directory = directory;
if (m_delegate) if (m_delegate)
m_delegate->m_panel.directoryURL = [NSURL fileURLWithPath:directory.toLocalFile().toNSString()]; m_delegate->m_panel.directoryURL = [NSURL fileURLWithPath:directory.toLocalFile().toNSString()];
else
m_directory = directory;
} }
QUrl QCocoaFileDialogHelper::directory() const QUrl QCocoaFileDialogHelper::directory() const
{ {
if (m_delegate) {
QString path = QString::fromNSString(m_delegate->m_panel.directoryURL.path).normalized(QString::NormalizationForm_C);
return QUrl::fromLocalFile(path);
}
return m_directory; return m_directory;
} }
void QCocoaFileDialogHelper::panelDirectoryDidChange(NSString *path)
{
if (!path || [path isEqual:NSNull.null] || !path.length)
return;
const auto oldDirectory = m_directory;
m_directory = QUrl::fromLocalFile(
QString::fromNSString(path).normalized(QString::NormalizationForm_C));
if (m_directory != oldDirectory) {
// FIXME: Plumb old directory back to QFileDialog's lastVisitedDir?
emit directoryEntered(m_directory);
}
}
void QCocoaFileDialogHelper::selectFile(const QUrl &filename) void QCocoaFileDialogHelper::selectFile(const QUrl &filename)
{ {
QString filePath = filename.toLocalFile(); QString filePath = filename.toLocalFile();