1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-30 23:49:28 +02:00

Bug 2371 - Crash when change Export dialog filters

This commit is contained in:
Leland Lucius 2020-03-25 13:20:02 -05:00
parent d5197fa773
commit 222f2aa8f9
2 changed files with 70 additions and 91 deletions

View File

@ -61,7 +61,6 @@ public:
virtual int ShowModal();
#if wxOSX_USE_COCOA
virtual void ShowWindowModal();
virtual void ModalFinishedCallback(void* panel, int resultCode);
#endif
@ -75,7 +74,7 @@ public:
void DoViewResized(void* object);
void DoSendFolderChangedEvent(void* panel, const wxString& path);
void DoSendSelectionChangedEvent(void* panel);
wxString DoCaptureFilename(void* panel, const wxString& name);
void DoCaptureFilename(void* panel, const wxString& name);
#endif
protected:

View File

@ -11,6 +11,7 @@
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#define OSFILENAME(X) ((char *) (const char *)(X).fn_str())
// ============================================================================
// declarations
// ============================================================================
@ -50,11 +51,7 @@
// implementation
// ============================================================================
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
#define wxOSX_10_6_AND_LATER( x ) x
#endif
@interface OSPanelDelegate : NSObject wxOSX_10_6_AND_LATER(<NSOpenSavePanelDelegate>)
@interface OSPanelDelegate : NSObject <NSOpenSavePanelDelegate>
{
FileDialog* _dialog;
}
@ -62,8 +59,9 @@
- (FileDialog*) fileDialog;
- (void) setFileDialog:(FileDialog*) dialog;
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
- (void)panelSelectionDidChange:(id)sender AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url;
- (void)panelSelectionDidChange:(id)sender;
- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag;
- (void)viewResized:(NSNotification *)notification;
@ -77,8 +75,10 @@
- (id) init
{
self = [super init];
_dialog = NULL;
if ( self = [super init] )
{
_dialog = NULL;
}
return self;
}
@ -103,9 +103,19 @@
{
_dialog->DoSendSelectionChangedEvent(sender);
}
- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag;
{
if (okFlag == YES)
{
_dialog->DoCaptureFilename(sender, wxCFStringRef::AsStringWithNormalizationFormC(filename));
}
return filename;
}
@end
IMPLEMENT_CLASS(FileDialog, FileDialogBase)
wxIMPLEMENT_CLASS(FileDialog, FileDialogBase)
FileDialog::FileDialog()
: FileDialogBase()
@ -194,12 +204,8 @@ NSArray* GetTypesFromExtension( const wxString extensiongroup, wxArrayString& ex
extensions.Add(extension.Lower());
wxCFStringRef cfext(extension);
[types addObject: (NSString*)cfext.AsNSString() ];
#if 0
// add support for classic fileType / creator here
wxUint32 fileType, creator;
// extension -> mactypes
#endif
}
[types autorelease];
return types;
}
@ -263,70 +269,6 @@ NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArr
return types;
}
void FileDialog::ShowWindowModal()
{
wxCFStringRef cf( m_message );
wxCFStringRef dir( m_dir );
wxCFStringRef file( m_fileName );
m_path = wxEmptyString;
m_fileNames.Clear();
m_paths.Clear();
wxNonOwnedWindow* parentWindow = NULL;
m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
if (GetParent())
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions ) ;
if ( HasFlag(wxFD_SAVE) )
{
NSSavePanel* sPanel = [NSSavePanel savePanel];
SetupExtraControls(sPanel);
// makes things more convenient:
[sPanel setCanCreateDirectories:YES];
[sPanel setMessage:cf.AsNSString()];
// if we should be able to descend into pacakges we must somehow
// be able to pass this in
[sPanel setTreatsFilePackagesAsDirectories:NO];
[sPanel setCanSelectHiddenExtension:YES];
[sPanel setAllowedFileTypes:types];
[sPanel setAllowsOtherFileTypes:NO];
NSWindow* nativeParent = parentWindow->GetWXWindow();
[sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
modalForWindow: nativeParent modalDelegate: nil // m_sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
else
{
NSOpenPanel* oPanel = [NSOpenPanel openPanel];
SetupExtraControls(oPanel);
[oPanel setTreatsFilePackagesAsDirectories:NO];
[oPanel setCanChooseDirectories:NO];
[oPanel setResolvesAliases:YES];
[oPanel setCanChooseFiles:YES];
[oPanel setMessage:cf.AsNSString()];
[oPanel setAllowsMultipleSelection: (HasFlag(wxFD_MULTIPLE) ? YES : NO )];
NSWindow* nativeParent = parentWindow->GetWXWindow();
[oPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
types: types modalForWindow: nativeParent
modalDelegate: nil // m_sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
}
void FileDialog::DoOnFilterSelected(int index)
{
if (index == wxNOT_FOUND)
@ -377,6 +319,7 @@ void FileDialog::DoSendSelectionChangedEvent(void* panel)
m_path = wxCFStringRef::AsStringWithNormalizationFormC( path );
m_fileName = wxFileNameFromPath( m_path );
m_dir = wxPathOnly( m_path );
m_fileNames.Clear();
m_fileNames.Add( m_fileName );
}
else
@ -409,6 +352,23 @@ void FileDialog::DoSendSelectionChangedEvent(void* panel)
GetEventHandler()->ProcessEvent( event );
}
void FileDialog::DoCaptureFilename(void* panel, const wxString & name)
{
// Bug 2371:
// This is here solely to get around a crash when accessing the URL after
// the dialog ends. If multiple filters are passed in and the initial filter
// has an "*" or "*.*" entry (nothing filtered) and the users switches to
// another filter that does have specific extensions, a crash will occur if
// the file previously existed and the URL method is used after the dialog
// returns.
//
// So, to get around it, we just capture the filename prior to the dialog
// ending.
m_fileName = name;
return;
}
void FileDialog::SetupExtraControls(WXWindow nativeWindow)
{
NSSavePanel* panel = (NSSavePanel*) nativeWindow;
@ -456,7 +416,7 @@ void FileDialog::SetupExtraControls(WXWindow nativeWindow)
if ( m_firstFileTypeFilter >= 0 )
m_filterChoice->SetSelection( m_firstFileTypeFilter );
}
m_filterChoice->Connect( wxEVT_CHOICE, wxCommandEventHandler( FileDialog::OnFilterSelected ), NULL, this );
m_filterChoice->Bind(wxEVT_CHOICE, &FileDialog::OnFilterSelected, this);
horizontalSizer->Add( m_filterChoice, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
verticalSizer->Add( horizontalSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
@ -502,7 +462,7 @@ int FileDialog::ShowModal()
wxCFStringRef dir( m_dir );
wxCFStringRef file( m_fileName );
m_path = wxEmptyString;
m_path.clear();
m_fileNames.Clear();
m_paths.Clear();
@ -566,6 +526,8 @@ int FileDialog::ShowModal()
}
}
OSXBeginModalDialog();
if ( HasFlag(wxFD_SAVE) )
{
NSSavePanel* sPanel = [NSSavePanel savePanel];
@ -640,9 +602,10 @@ int FileDialog::ShowModal()
DoOnFilterSelected(m_firstFileTypeFilter);
}
returnCode = [sPanel runModalForDirectory: m_dir.IsEmpty() ? nil : dir.AsNSString() file:file.AsNSString() ];
[sPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString()]];
[sPanel setNameFieldStringValue:file.AsNSString()];
returnCode = [sPanel runModal];
ModalFinishedCallback(sPanel, returnCode);
if (wxTheClipboard->IsSupported(wxDF_TEXT))
[NSEvent removeMonitor:handler];
}
@ -659,7 +622,18 @@ int FileDialog::ShowModal()
[oPanel setMessage:cf.AsNSString()];
[oPanel setAllowsMultipleSelection: (HasFlag(wxFD_MULTIPLE) ? YES : NO )];
[oPanel setAllowedFileTypes:types];
// Note that the test here is intentionally different from the one
// above, in the wxFD_SAVE case: we need to call DoOnFilterSelected()
// even for m_firstFileTypeFilter == 0, i.e. when using the default
// filter.
if ( m_firstFileTypeFilter >= 0 )
{
DoOnFilterSelected(m_firstFileTypeFilter);
}
else
{
[oPanel setAllowedFileTypes: (m_delegate == nil ? types : nil)];
}
if ( !m_dir.IsEmpty() )
[oPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString()
isDirectory:YES]];
@ -673,6 +647,8 @@ int FileDialog::ShowModal()
ModalFinishedCallback(oPanel, returnCode);
}
OSXEndModalDialog();
return GetReturnCode();
}
@ -689,9 +665,7 @@ void FileDialog::ModalFinishedCallback(void* panel, int returnCode)
{
result = wxID_OK;
m_path = wxCFStringRef::AsStringWithNormalizationFormC([sPanel filename]);
m_fileName = wxFileNameFromPath(m_path);
m_dir = wxPathOnly( m_path );
m_path = m_dir + wxT("/") + m_fileName;
if (m_filterChoice)
{
m_filterIndex = m_filterChoice->GetSelection();
@ -706,10 +680,16 @@ void FileDialog::ModalFinishedCallback(void* panel, int returnCode)
{
panel = oPanel;
result = wxID_OK;
NSArray* filenames = [oPanel filenames];
if (m_filterChoice)
{
m_filterIndex = m_filterChoice->GetSelection();
}
NSArray* filenames = [oPanel URLs];
for ( size_t i = 0 ; i < [filenames count] ; ++ i )
{
wxString fnstr = wxCFStringRef::AsStringWithNormalizationFormC([filenames objectAtIndex:i]);
wxString fnstr = wxCFStringRef::AsStringWithNormalizationFormC([[filenames objectAtIndex:i] path]);
m_paths.Add( fnstr );
m_fileNames.Add( wxFileNameFromPath(fnstr) );
if ( i == 0 )