Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcocoafiledialoghelper.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qglobal.h>
5
6#include <AppKit/AppKit.h>
7
9#include "qcocoahelpers.h"
11
12#include <QtCore/qbuffer.h>
13#include <QtCore/qdebug.h>
14#include <QtCore/qstringlist.h>
15#include <QtCore/qvarlengtharray.h>
16#include <QtCore/qabstracteventdispatcher.h>
17#include <QtCore/qsysinfo.h>
18#include <QtCore/qoperatingsystemversion.h>
19#include <QtCore/qdir.h>
20#include <QtCore/qregularexpression.h>
21#include <QtCore/qpointer.h>
22#include <QtCore/private/qcore_mac_p.h>
23
24#include <QtGui/qguiapplication.h>
25#include <QtGui/private/qguiapplication_p.h>
26
27#include <qpa/qplatformtheme.h>
28#include <qpa/qplatformnativeinterface.h>
29
31
32using namespace Qt::StringLiterals;
33
34static NSString *strippedText(QString s)
35{
36 s.remove("..."_L1);
37 return QPlatformTheme::removeMnemonics(s).trimmed().toNSString();
38}
39
40// NSOpenPanel extends NSSavePanel with some extra APIs
41static NSOpenPanel *openpanel_cast(NSSavePanel *panel)
42{
43 if ([panel isKindOfClass:NSOpenPanel.class])
44 return static_cast<NSOpenPanel*>(panel);
45 else
46 return nil;
47}
48
50
51@implementation QNSOpenSavePanelDelegate {
52 @public
53 NSSavePanel *m_panel;
55 NSPopUpButton *m_popupButton;
56 NSTextField *m_textField;
59
64}
65
66- (instancetype)initWithAcceptMode:(const QString &)selectFile
67 options:(SharedPointerFileDialogOptions)options
68 helper:(QCocoaFileDialogHelper *)helper
69{
70 if ((self = [super init])) {
71 m_options = options;
72
74 m_panel = [[NSOpenPanel openPanel] retain];
75 else
76 m_panel = [[NSSavePanel savePanel] retain];
77
78 m_panel.canSelectHiddenExtension = YES;
79 m_panel.level = NSModalPanelWindowLevel;
80
81 m_helper = helper;
82
84 QString selectedVisualNameFilter = m_options->initiallySelectedNameFilter();
85 m_selectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
86
87 QFileInfo sel(selectFile);
88 if (sel.isDir() && !sel.isBundle()){
89 m_currentDirectory = [sel.absoluteFilePath().toNSString() retain];
91 } else {
92 m_currentDirectory = [sel.absolutePath().toNSString() retain];
93 m_currentSelection = new QString(sel.absoluteFilePath());
94 }
95
96 [self createPopUpButton:selectedVisualNameFilter hideDetails:options->testOption(QFileDialogOptions::HideNameFilterDetails)];
97 [self createTextField];
98 [self createAccessory];
99
100 m_panel.accessoryView = m_nameFilterDropDownList->size() > 1 ? m_accessoryView : nil;
101 // -setAccessoryView: can result in -panel:directoryDidChange:
102 // resetting our m_currentDirectory, set the delegate
103 // here to make sure it gets the correct value.
104 m_panel.delegate = self;
105
106 if (auto *openPanel = openpanel_cast(m_panel))
107 openPanel.accessoryViewDisclosed = YES;
108
109 [self updateProperties];
110 }
111 return self;
112}
113
114- (void)dealloc
115{
118 delete m_currentSelection;
119
120 [m_panel orderOut:m_panel];
121 m_panel.accessoryView = nil;
122 [m_popupButton release];
123 [m_textField release];
124 [m_accessoryView release];
125 m_panel.delegate = nil;
126 [m_panel release];
127 [m_currentDirectory release];
128 [super dealloc];
129}
130
131- (bool)showPanel:(Qt::WindowModality) windowModality withParent:(QWindow *)parent
132{
134 NSString *filepath = info.filePath().toNSString();
135 NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
136 bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
137 || [self panel:m_panel shouldEnableURL:url];
138
139 m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
140 m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
141
142 [self updateProperties];
143
144 auto completionHandler = ^(NSInteger result) { m_helper->panelClosed(result); };
145
146 if (windowModality == Qt::WindowModal && parent) {
147 NSView *view = reinterpret_cast<NSView*>(parent->winId());
148 [m_panel beginSheetModalForWindow:view.window completionHandler:completionHandler];
149 } else if (windowModality == Qt::ApplicationModal) {
150 return true; // Defer until exec()
151 } else {
152 [m_panel beginWithCompletionHandler:completionHandler];
153 }
154
155 return true;
156}
157
158-(void)runApplicationModalPanel
159{
160 // Note: If NSApp is not running (which is the case if e.g a top-most
161 // QEventLoop has been interrupted, and the second-most event loop has not
162 // yet been reactivated (regardless if [NSApp run] is still on the stack)),
163 // showing a native modal dialog will fail.
164 if (!m_helper)
165 return;
166
168
169 // Call processEvents in case the event dispatcher has been interrupted, and needs to do
170 // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
171 // close down during the cleanup.
173
174 // Make sure we don't interrupt the runModal call below.
176
177 auto result = [m_panel runModal];
178 m_helper->panelClosed(result);
179
180 // Wake up the event dispatcher so it can check whether the
181 // current event loop should continue spinning or not.
183}
184
185- (void)closePanel
186{
187 *m_currentSelection = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
188
189 if (m_panel.sheet)
190 [NSApp endSheet:m_panel];
191 else if (NSApp.modalWindow == m_panel)
192 [NSApp stopModal];
193 else
194 [m_panel close];
195}
196
197- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url
198{
199 Q_UNUSED(sender);
200
201 NSString *filename = url.path;
202 if (!filename.length)
203 return NO;
204
205 QFileInfo fileInfo(QString::fromNSString(filename));
206
207 // Always accept directories regardless of their names.
208 // This also includes symlinks and aliases to directories.
209 if (fileInfo.isDir()) {
210 // Unless it's a bundle, and we should treat bundles as files.
211 // FIXME: We'd like to use QFileInfo::isBundle() here, but the
212 // detection in QFileInfo goes deeper than NSWorkspace does
213 // (likely a bug), and as a result causes TCC permission
214 // dialogs to pop up when used.
215 bool treatBundlesAsFiles = !m_panel.treatsFilePackagesAsDirectories;
216 if (!(treatBundlesAsFiles && [NSWorkspace.sharedWorkspace isFilePackageAtPath:filename]))
217 return YES;
218 }
219
220 QString qtFileName = fileInfo.fileName();
221 // No filter means accept everything
222 bool nameMatches = m_selectedNameFilter->isEmpty();
223 // Check if the current file name filter accepts the file:
224 for (int i = 0; !nameMatches && i < m_selectedNameFilter->size(); ++i) {
225 if (QDir::match(m_selectedNameFilter->at(i), qtFileName))
226 nameMatches = true;
227 }
228 if (!nameMatches)
229 return NO;
230
231 QDir::Filters filter = m_options->filter();
232 if ((!(filter & (QDir::Dirs | QDir::AllDirs)) && fileInfo.isDir())
233 || (!(filter & QDir::Files) && (fileInfo.isFile() && !fileInfo.isSymLink()))
234 || ((filter & QDir::NoSymLinks) && fileInfo.isSymLink()))
235 return NO;
236
237 bool filterPermissions = ((filter & QDir::PermissionMask)
239 if (filterPermissions) {
240 if ((!(filter & QDir::Readable) && fileInfo.isReadable())
241 || (!(filter & QDir::Writable) && fileInfo.isWritable())
242 || (!(filter & QDir::Executable) && fileInfo.isExecutable()))
243 return NO;
244 }
245
246 // We control the visibility of hidden files via the showsHiddenFiles
247 // property on the panel, based on QDir::Hidden being set. But the user
248 // can also toggle this via the Command+Shift+. keyboard shortcut,
249 // in which case they have explicitly requested to show hidden files,
250 // and we should enable them even if QDir::Hidden was not set. In
251 // effect, we don't need to filter on QDir::Hidden here.
252
253 return YES;
254}
255
256- (void)setNameFilters:(const QStringList &)filters hideDetails:(BOOL)hideDetails
257{
258 [m_popupButton removeAllItems];
260 if (filters.size() > 0){
261 for (int i = 0; i < filters.size(); ++i) {
262 QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
263 [m_popupButton.menu addItemWithTitle:filter.toNSString() action:nil keyEquivalent:@""];
264 }
265 [m_popupButton selectItemAtIndex:0];
266 m_panel.accessoryView = m_accessoryView;
267 } else {
268 m_panel.accessoryView = nil;
269 }
270
271 [self filterChanged:self];
272}
273
274- (void)filterChanged:(id)sender
275{
276 // This m_delegate function is called when the _name_ filter changes.
277 Q_UNUSED(sender);
278 if (!m_helper)
279 return;
280 QString selection = m_nameFilterDropDownList->value([m_popupButton indexOfSelectedItem]);
281 *m_selectedNameFilter = [self findStrippedFilterWithVisualFilterName:selection];
282 [m_panel validateVisibleColumns];
283 [self updateProperties];
284
286 const int menuIndex = m_popupButton.indexOfSelectedItem;
287 emit m_helper->filterSelected(menuIndex >= 0 && menuIndex < filters.size() ? filters.at(menuIndex) : QString());
288}
289
290- (QList<QUrl>)selectedFiles
291{
292 if (auto *openPanel = openpanel_cast(m_panel)) {
294 for (NSURL *url in openPanel.URLs) {
297 }
298 return result;
299 } else {
301 QString filename = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
302 const QString defaultSuffix = m_options->defaultSuffix();
303 const QFileInfo fileInfo(filename);
304
305 // If neither the user or the NSSavePanel have provided a suffix, use
306 // the default suffix (if it exists).
307 if (fileInfo.suffix().isEmpty() && !defaultSuffix.isEmpty())
308 filename.append('.').append(defaultSuffix);
309
310 result << QUrl::fromLocalFile(filename);
311 return result;
312 }
313}
314
315- (void)updateProperties
316{
318 bool chooseFilesOnly = fileMode == QFileDialogOptions::ExistingFile
320 bool chooseDirsOnly = fileMode == QFileDialogOptions::Directory
323
324 m_panel.title = m_options->windowTitle().toNSString();
325 m_panel.canCreateDirectories = !(m_options->testOption(QFileDialogOptions::ReadOnly));
326
331
332 if (auto *openPanel = openpanel_cast(m_panel)) {
333 openPanel.canChooseFiles = !chooseDirsOnly;
334 openPanel.canChooseDirectories = !chooseFilesOnly;
335 openPanel.allowsMultipleSelection = (fileMode == QFileDialogOptions::ExistingFiles);
336 openPanel.resolvesAliases = !(m_options->testOption(QFileDialogOptions::DontResolveSymlinks));
337 }
338
339 m_popupButton.hidden = chooseDirsOnly; // TODO hide the whole sunken pane instead?
340
341 m_panel.allowedFileTypes = [self computeAllowedFileTypes];
342
343 // Explicitly show extensions if we detect a filter
344 // that has a multi-part extension. This prevents
345 // confusing situations where the user clicks e.g.
346 // 'foo.tar.gz' and 'foo.tar' is populated in the
347 // file name box, but when then clicking save macOS
348 // will warn that the file needs to end in .gz,
349 // due to thinking the user tried to save the file
350 // as a 'tar' file instead. Unfortunately this
351 // property can only be set before the panel is
352 // shown, so it will not have any effect when
353 // switching filters in an already opened dialog.
354 if (m_panel.allowedFileTypes.count > 2)
355 m_panel.extensionHidden = NO;
356
357 m_panel.showsHiddenFiles = m_options->filter().testFlag(QDir::Hidden);
358
359 if (m_panel.visible)
360 [m_panel validateVisibleColumns];
361}
362
363- (void)panelSelectionDidChange:(id)sender
364{
365 Q_UNUSED(sender);
366
367 if (!m_helper)
368 return;
369
370 if (m_panel.visible) {
371 QString selection = QString::fromNSString(m_panel.URL.path);
374 emit m_helper->currentChanged(QUrl::fromLocalFile(selection));
375 }
376 }
377}
378
379- (void)panel:(id)sender directoryDidChange:(NSString *)path
380{
381 Q_UNUSED(sender);
382
383 if (!m_helper)
384 return;
385
386 if (!(path && path.length) || [path isEqualToString:m_currentDirectory])
387 return;
388
389 [m_currentDirectory release];
390 m_currentDirectory = [path retain];
391
392 // ### fixme: priv->setLastVisitedDirectory(newDir);
393 emit m_helper->directoryEntered(QUrl::fromLocalFile(QString::fromNSString(m_currentDirectory)));
394}
395
396/*
397 Computes a list of extensions (e.g. "png", "jpg", "gif")
398 for the current name filter, and updates the save panel.
399
400 If a filter do not conform to the format *.xyz or * or *.*,
401 all files types are allowed.
402
403 Extensions with more than one part (e.g. "tar.gz") are
404 reduced to their final part, as NSSavePanel does not deal
405 well with multi-part extensions.
406*/
407- (NSArray<NSString*>*)computeAllowedFileTypes
408{
410 return nil; // panel:shouldEnableURL: does the file filtering for NSOpenPanel
411
412 QStringList fileTypes;
413 for (const QString &filter : *m_selectedNameFilter) {
414 if (!filter.startsWith("*."_L1))
415 continue;
416
417 if (filter.contains(u'?'))
418 continue;
419
420 if (filter.count(u'*') != 1)
421 continue;
422
423 auto extensions = filter.split('.', Qt::SkipEmptyParts);
424 fileTypes += extensions.last();
425 }
426
427 return fileTypes.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(fileTypes);
428}
429
430- (QString)removeExtensions:(const QString &)filter
431{
433 QRegularExpressionMatch match = regExp.match(filter);
434 if (match.hasMatch())
435 return match.captured(1).trimmed();
436 return filter;
437}
438
439- (void)createTextField
440{
441 NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
442 m_textField = [[NSTextField alloc] initWithFrame:textRect];
443 m_textField.cell.font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeRegular]];
444 m_textField.alignment = NSTextAlignmentRight;
445 m_textField.editable = false;
446 m_textField.selectable = false;
447 m_textField.bordered = false;
448 m_textField.drawsBackground = false;
451}
452
453- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails
454{
455 NSRect popUpRect = { { 100.0, 5.0 }, { 250.0, 25.0 } };
456 m_popupButton = [[NSPopUpButton alloc] initWithFrame:popUpRect pullsDown:NO];
457 m_popupButton.target = self;
458 m_popupButton.action = @selector(filterChanged:);
459
460 if (m_nameFilterDropDownList->size() > 0) {
461 int filterToUse = -1;
462 for (int i = 0; i < m_nameFilterDropDownList->size(); ++i) {
463 QString currentFilter = m_nameFilterDropDownList->at(i);
464 if (selectedFilter == currentFilter ||
465 (filterToUse == -1 && currentFilter.startsWith(selectedFilter)))
466 filterToUse = i;
467 QString filter = hideDetails ? [self removeExtensions:currentFilter] : currentFilter;
468 [m_popupButton.menu addItemWithTitle:filter.toNSString() action:nil keyEquivalent:@""];
469 }
470 if (filterToUse != -1)
471 [m_popupButton selectItemAtIndex:filterToUse];
472 }
473}
474
475- (QStringList) findStrippedFilterWithVisualFilterName:(QString)name
476{
477 for (int i = 0; i < m_nameFilterDropDownList->size(); ++i) {
478 if (m_nameFilterDropDownList->at(i).startsWith(name))
480 }
481 return QStringList();
482}
483
484- (void)createAccessory
485{
486 NSRect accessoryRect = { { 0.0, 0.0 }, { 450.0, 33.0 } };
487 m_accessoryView = [[NSView alloc] initWithFrame:accessoryRect];
488 [m_accessoryView addSubview:m_textField];
489 [m_accessoryView addSubview:m_popupButton];
490}
491
492@end
493
495
497{
498}
499
501{
502 if (!m_delegate)
503 return;
504
506 [m_delegate release];
507 m_delegate = nil;
508}
509
511{
512 if (result == NSModalResponseOK)
513 emit accept();
514 else
515 emit reject();
516}
517
519{
520 if (m_delegate)
521 m_delegate->m_panel.directoryURL = [NSURL fileURLWithPath:directory.toLocalFile().toNSString()];
522 else
523 m_directory = directory;
524}
525
527{
528 if (m_delegate) {
529 QString path = QString::fromNSString(m_delegate->m_panel.directoryURL.path).normalized(QString::NormalizationForm_C);
531 }
532 return m_directory;
533}
534
536{
537 QString filePath = filename.toLocalFile();
538 if (QDir::isRelativePath(filePath))
539 filePath = QFileInfo(directory().toLocalFile(), filePath).filePath();
540
541 // There seems to no way to select a file once the dialog is running.
542 // So do the next best thing, set the file's directory:
544}
545
547{
548 if (m_delegate)
549 return [m_delegate selectedFiles];
550 return QList<QUrl>();
551}
552
554{
555 if (!m_delegate)
556 return;
557
558 [m_delegate updateProperties];
559}
560
562{
563 if (!options())
564 return;
565 const int index = options()->nameFilters().indexOf(filter);
566 if (index != -1) {
567 if (!m_delegate) {
569 return;
570 }
571 [m_delegate->m_popupButton selectItemAtIndex:index];
572 [m_delegate filterChanged:nil];
573 }
574}
575
577{
578 if (!m_delegate)
580 int index = [m_delegate->m_popupButton indexOfSelectedItem];
581 if (index >= options()->nameFilters().count())
582 return QString();
583 return index != -1 ? options()->nameFilters().at(index) : QString();
584}
585
587{
588 if (!m_delegate)
589 return;
590
591 [m_delegate closePanel];
592
593 if (m_eventLoop)
594 m_eventLoop->exit();
595}
596
597bool QCocoaFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
598{
599 if (windowFlags & Qt::WindowStaysOnTopHint) {
600 // The native file dialog tries all it can to stay
601 // on the NSModalPanel level. And it might also show
602 // its own "create directory" dialog that we cannot control.
603 // So we need to use the non-native version in this case...
604 return false;
605 }
606
607 createNSOpenSavePanelDelegate();
608
609 return [m_delegate showPanel:windowModality withParent:parent];
610}
611
612void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
613{
615
618 const QUrl directory = m_directory.isEmpty() ? opts->initialDirectory() : m_directory;
619 const bool selectDir = selectedFiles.isEmpty();
622 initWithAcceptMode:
623 selection
624 options:opts
625 helper:this];
626
627 [static_cast<QNSOpenSavePanelDelegate *>(m_delegate) release];
628 m_delegate = delegate;
629}
630
632{
633 Q_ASSERT(m_delegate);
634
635 if (m_delegate->m_panel.visible) {
636 // WindowModal or NonModal, so already shown above
637 QEventLoop eventLoop;
638 m_eventLoop = &eventLoop;
639 eventLoop.exec(QEventLoop::DialogExec);
640 m_eventLoop = nullptr;
641 } else {
642 // ApplicationModal, so show and block using native APIs
643 [m_delegate runApplicationModalPanel];
644 }
645}
646
648{
649 return true;
650}
651
virtual void wakeUp()=0
\threadsafe
static void clearCurrentThreadCocoaEventDispatcherInterruptFlag()
QList< QUrl > selectedFiles() const override
bool defaultNameFilterDisables() const override
QString selectedNameFilter() const override
QUrl directory() const override
void setDirectory(const QUrl &directory) override
bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override
void selectNameFilter(const QString &filter) override
void selectFile(const QUrl &filename) override
void panelClosed(NSInteger result)
static QAbstractEventDispatcher * eventDispatcher()
Returns a pointer to the event dispatcher object for the main thread.
static bool isRelativePath(const QString &path)
Returns true if path is relative; returns false if it is absolute.
Definition qdir.cpp:2409
@ Executable
Definition qdir.h:30
@ Files
Definition qdir.h:22
@ PermissionMask
Definition qdir.h:31
@ Hidden
Definition qdir.h:34
@ AllDirs
Definition qdir.h:39
@ NoSymLinks
Definition qdir.h:24
@ Readable
Definition qdir.h:28
@ Writable
Definition qdir.h:29
@ Dirs
Definition qdir.h:21
\inmodule QtCore
Definition qeventloop.h:16
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
@ ExcludeSocketNotifiers
Definition qeventloop.h:28
@ ExcludeUserInputEvents
Definition qeventloop.h:27
void exit(int returnCode=0)
Tells the event loop to exit with a return code.
QList< QUrl > initiallySelectedFiles() const
bool isLabelExplicitlySet(DialogLabel label)
QDir::Filters filter() const
QString initiallySelectedNameFilter() const
QString labelText(DialogLabel label) const
AcceptMode acceptMode() const
void setInitiallySelectedNameFilter(const QString &)
QStringList nameFilters() const
bool testOption(FileDialogOption option) const
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString fileName() const
Returns the name of the file, excluding the path.
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
static QStringList cleanFilterList(const QString &filter)
const QSharedPointer< QFileDialogOptions > & options() const
static QString removeMnemonics(const QString &original)
\inmodule QtCore
Definition qpointer.h:18
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString & append(QChar c)
Definition qstring.cpp:3227
QString trimmed() const &
Definition qstring.h:380
@ NormalizationForm_C
Definition qstring.h:548
QString normalized(NormalizationForm mode, QChar::UnicodeVersion version=QChar::Unicode_Unassigned) const
Returns the string in the given Unicode normalization mode, according to the given version of the Uni...
Definition qstring.cpp:8212
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3354
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
\inmodule QtGui
Definition qwindow.h:63
QRect textRect
Combined button and popup list for selecting options.
WindowModality
@ WindowModal
@ ApplicationModal
@ SkipEmptyParts
Definition qnamespace.h:127
@ WindowStaysOnTopHint
Definition qnamespace.h:232
QString self
Definition language.cpp:57
QString * m_currentSelection
NSView * m_accessoryView
QSharedPointer< QFileDialogOptions > SharedPointerFileDialogOptions
NSString * m_currentDirectory
SharedPointerFileDialogOptions m_options
QStringList * m_nameFilterDropDownList
NSPopUpButton * m_popupButton
static NSString * strippedText(QString s)
QStringList * m_selectedNameFilter
static NSOpenPanel * openpanel_cast(NSSavePanel *panel)
QPointer< QCocoaFileDialogHelper > m_helper
NSTextField * m_textField
NSMutableArray< NSString * > * qt_mac_QStringListToNSMutableArray(const QStringList &list)
long NSInteger
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLuint index
[2]
GLenum GLenum GLsizei count
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint name
GLuint in
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
static QString toLocalFile(const QString &url)
Definition qqmlfile.cpp:611
static QString absolutePath(const QString &path)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define emit
#define Q_UNUSED(x)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
QWidget * panel
Definition settings.cpp:7
QFileInfo info(fileName)
[8]
QUrl url("example.com")
[constructor-url-reference]
dialog setNameFilters(filters)
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
QItemSelection * selection
[0]
QQuickView * view
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent