macOS: Reduce duplicated code for showing file dialogs
The initialization was duplicated across the different modes. We now do the setup once, in a shared showPanel:withParent function. This also simplifies and removes the need to store the return code. Change-Id: I3c4da48cfef92bcc59c76cffa15b40150de1a9e1 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
1724fccb01
commit
3d341ae882
@ -73,7 +73,7 @@ public:
|
|||||||
QString selectedNameFilter() const override;
|
QString selectedNameFilter() const override;
|
||||||
|
|
||||||
public: // for QNSOpenSavePanelDelegate
|
public: // for QNSOpenSavePanelDelegate
|
||||||
void panelClosed(bool accepted);
|
void panelClosed(NSInteger result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createNSOpenSavePanelDelegate();
|
void createNSOpenSavePanelDelegate();
|
||||||
|
@ -80,8 +80,6 @@ static NSOpenPanel *openpanel_cast(NSSavePanel *panel)
|
|||||||
|
|
||||||
typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
|
typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
|
||||||
|
|
||||||
static const int kReturnCodeNotSet = -1;
|
|
||||||
|
|
||||||
@implementation QNSOpenSavePanelDelegate {
|
@implementation QNSOpenSavePanelDelegate {
|
||||||
@public
|
@public
|
||||||
NSSavePanel *m_panel;
|
NSSavePanel *m_panel;
|
||||||
@ -91,8 +89,6 @@ static const int kReturnCodeNotSet = -1;
|
|||||||
QCocoaFileDialogHelper *m_helper;
|
QCocoaFileDialogHelper *m_helper;
|
||||||
NSString *m_currentDirectory;
|
NSString *m_currentDirectory;
|
||||||
|
|
||||||
int m_returnCode;
|
|
||||||
|
|
||||||
SharedPointerFileDialogOptions m_options;
|
SharedPointerFileDialogOptions m_options;
|
||||||
QString *m_currentSelection;
|
QString *m_currentSelection;
|
||||||
QStringList *m_nameFilterDropDownList;
|
QStringList *m_nameFilterDropDownList;
|
||||||
@ -114,7 +110,6 @@ static const int kReturnCodeNotSet = -1;
|
|||||||
m_panel.canSelectHiddenExtension = YES;
|
m_panel.canSelectHiddenExtension = YES;
|
||||||
m_panel.level = NSModalPanelWindowLevel;
|
m_panel.level = NSModalPanelWindowLevel;
|
||||||
|
|
||||||
m_returnCode = kReturnCodeNotSet;
|
|
||||||
m_helper = helper;
|
m_helper = helper;
|
||||||
|
|
||||||
m_nameFilterDropDownList = new QStringList(m_options->nameFilters());
|
m_nameFilterDropDownList = new QStringList(m_options->nameFilters());
|
||||||
@ -165,6 +160,54 @@ static const int kReturnCodeNotSet = -1;
|
|||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (bool)showPanel:(Qt::WindowModality) windowModality withParent:(QWindow *)parent
|
||||||
|
{
|
||||||
|
QFileInfo info(*m_currentSelection);
|
||||||
|
NSString *filepath = info.filePath().toNSString();
|
||||||
|
NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
|
||||||
|
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|
||||||
|
|| [self panel:m_panel shouldEnableURL:url];
|
||||||
|
|
||||||
|
m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
|
||||||
|
m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
|
||||||
|
|
||||||
|
[self updateProperties];
|
||||||
|
|
||||||
|
auto completionHandler = ^(NSInteger result) { m_helper->panelClosed(result); };
|
||||||
|
|
||||||
|
if (windowModality == Qt::WindowModal && parent) {
|
||||||
|
NSView *view = reinterpret_cast<NSView*>(parent->winId());
|
||||||
|
[m_panel beginSheetModalForWindow:view.window completionHandler:completionHandler];
|
||||||
|
} else if (windowModality == Qt::ApplicationModal) {
|
||||||
|
return true; // Defer until exec()
|
||||||
|
} else {
|
||||||
|
[m_panel beginWithCompletionHandler:completionHandler];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)runApplicationModalPanel
|
||||||
|
{
|
||||||
|
// Note: If NSApp is not running (which is the case if e.g a top-most
|
||||||
|
// QEventLoop has been interrupted, and the second-most event loop has not
|
||||||
|
// yet been reactivated (regardless if [NSApp run] is still on the stack)),
|
||||||
|
// showing a native modal dialog will fail.
|
||||||
|
|
||||||
|
QMacAutoReleasePool pool;
|
||||||
|
|
||||||
|
// Call processEvents in case the event dispatcher has been interrupted, and needs to do
|
||||||
|
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
|
||||||
|
// close down during the cleanup.
|
||||||
|
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
|
||||||
|
|
||||||
|
// Make sure we don't interrupt the runModal call below.
|
||||||
|
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
|
||||||
|
|
||||||
|
auto result = [m_panel runModal];
|
||||||
|
m_helper->panelClosed(result);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)closePanel
|
- (void)closePanel
|
||||||
{
|
{
|
||||||
*m_currentSelection = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
|
*m_currentSelection = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
|
||||||
@ -177,68 +220,6 @@ static const int kReturnCodeNotSet = -1;
|
|||||||
[m_panel close];
|
[m_panel close];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showModelessPanel
|
|
||||||
{
|
|
||||||
QFileInfo info(*m_currentSelection);
|
|
||||||
NSString *filepath = info.filePath().toNSString();
|
|
||||||
NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
|
|
||||||
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|
|
||||||
|| [self panel:m_panel shouldEnableURL:url];
|
|
||||||
|
|
||||||
[self updateProperties];
|
|
||||||
m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
|
|
||||||
|
|
||||||
[m_panel beginWithCompletionHandler:^(NSInteger result){
|
|
||||||
m_returnCode = result;
|
|
||||||
m_helper->panelClosed(result == NSModalResponseOK);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)runApplicationModalPanel
|
|
||||||
{
|
|
||||||
QFileInfo info(*m_currentSelection);
|
|
||||||
NSString *filepath = info.filePath().toNSString();
|
|
||||||
NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
|
|
||||||
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|
|
||||||
|| [self panel:m_panel shouldEnableURL:url];
|
|
||||||
|
|
||||||
m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
|
|
||||||
m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
|
|
||||||
|
|
||||||
// Call processEvents in case the event dispatcher has been interrupted, and needs to do
|
|
||||||
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
|
|
||||||
// close down during the cleanup.
|
|
||||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
|
|
||||||
|
|
||||||
// Make sure we don't interrupt the runModal call below.
|
|
||||||
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
|
|
||||||
|
|
||||||
m_returnCode = [m_panel runModal];
|
|
||||||
|
|
||||||
QAbstractEventDispatcher::instance()->interrupt();
|
|
||||||
return (m_returnCode == NSModalResponseOK);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)showWindowModalSheet:(QWindow *)parent
|
|
||||||
{
|
|
||||||
QFileInfo info(*m_currentSelection);
|
|
||||||
NSString *filepath = info.filePath().toNSString();
|
|
||||||
NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
|
|
||||||
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|
|
||||||
|| [self panel:m_panel shouldEnableURL:url];
|
|
||||||
|
|
||||||
[self updateProperties];
|
|
||||||
m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
|
|
||||||
|
|
||||||
m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
|
|
||||||
NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent));
|
|
||||||
|
|
||||||
[m_panel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){
|
|
||||||
m_returnCode = result;
|
|
||||||
m_helper->panelClosed(result == NSModalResponseOK);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)isHiddenFileAtURL:(NSURL *)url
|
- (BOOL)isHiddenFileAtURL:(NSURL *)url
|
||||||
{
|
{
|
||||||
BOOL hidden = NO;
|
BOOL hidden = NO;
|
||||||
@ -549,9 +530,9 @@ QCocoaFileDialogHelper::~QCocoaFileDialogHelper()
|
|||||||
m_delegate = nil;
|
m_delegate = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCocoaFileDialogHelper::panelClosed(bool accepted)
|
void QCocoaFileDialogHelper::panelClosed(NSInteger result)
|
||||||
{
|
{
|
||||||
if (accepted)
|
if (result == NSModalResponseOK)
|
||||||
emit accept();
|
emit accept();
|
||||||
else
|
else
|
||||||
emit reject();
|
emit reject();
|
||||||
@ -647,17 +628,8 @@ bool QCocoaFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
|
|||||||
}
|
}
|
||||||
|
|
||||||
createNSOpenSavePanelDelegate();
|
createNSOpenSavePanelDelegate();
|
||||||
if (!m_delegate)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (windowModality == Qt::WindowModal && parent)
|
return [m_delegate showPanel:windowModality withParent:parent];
|
||||||
[m_delegate showWindowModalSheet:parent];
|
|
||||||
else if (windowModality == Qt::ApplicationModal)
|
|
||||||
return true; // Defer until exec()
|
|
||||||
else
|
|
||||||
[m_delegate showModelessPanel];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
|
void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
|
||||||
@ -691,17 +663,7 @@ void QCocoaFileDialogHelper::exec()
|
|||||||
m_eventLoop = nullptr;
|
m_eventLoop = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// ApplicationModal, so show and block using native APIs
|
// ApplicationModal, so show and block using native APIs
|
||||||
|
[m_delegate runApplicationModalPanel];
|
||||||
// Note: If NSApp is not running (which is the case if e.g a top-most
|
|
||||||
// QEventLoop has been interrupted, and the second-most event loop has not
|
|
||||||
// yet been reactivated (regardless if [NSApp run] is still on the stack)),
|
|
||||||
// showing a native modal dialog will fail.
|
|
||||||
|
|
||||||
QMacAutoReleasePool pool;
|
|
||||||
if ([m_delegate runApplicationModalPanel])
|
|
||||||
emit accept();
|
|
||||||
else
|
|
||||||
emit reject();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user