5#define QT_NO_URL_CAST_FROM_STRING
8#include <private/qwidgetitemdata_p.h>
12#include <private/qapplication_p.h>
13#include <private/qguiapplication_p.h>
14#include <qfontmetrics.h>
16#include <qactiongroup.h>
17#include <qheaderview.h>
18#if QT_CONFIG(shortcut)
19# include <qshortcut.h>
21#include <qgridlayout.h>
25#if QT_CONFIG(messagebox)
26#include <qmessagebox.h>
29#if QT_CONFIG(settings)
33#if QT_CONFIG(mimetype)
34#include <qmimedatabase.h>
36#if QT_CONFIG(regularexpression)
37#include <qregularexpression.h>
39#include <qapplication.h>
40#include <qstylepainter.h>
41#include "ui_qfiledialog.h"
45#elif defined(Q_OS_WIN)
46# include <QtCore/qt_windows.h>
49#include <private/qwasmlocalfileaccess_p.h>
56using namespace Qt::StringLiterals;
58Q_GLOBAL_STATIC(QUrl, lastVisitedDir)
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
150
151
152
153
154
157
158
159
160
161
162
163
164
165
166
167
168
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
230
231
232
233
234
235
236
237
240
241
242
243
244
245
246
247
250
251
252
253
254
255
256
257
260
261
262
263
264
265
266
267
270
271
272
273
274
275
276
277
280
281
282
283
284
285
286
289
290
291
292
293
294
295
296
299
300
301
302
303
306
307
308
309
310
311
314
315
316
317
319QT_BEGIN_INCLUDE_NAMESPACE
321#if QT_CONFIG(shortcut)
322# include <qshortcut.h>
324QT_END_INCLUDE_NAMESPACE
327
328
329
330
331QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
332 : QDialog(*
new QFileDialogPrivate, parent, f)
335 QFileDialogArgs args;
340
341
342
343
344
345
346QFileDialog::QFileDialog(QWidget *parent,
347 const QString &caption,
348 const QString &directory,
349 const QString &filter)
350 : QDialog(*
new QFileDialogPrivate, parent, { })
353 QFileDialogArgs args(QUrl::fromLocalFile(directory));
354 args.filter = filter;
355 args.caption = caption;
360
361
362QFileDialog::QFileDialog(
const QFileDialogArgs &args)
363 : QDialog(*
new QFileDialogPrivate, args.parent, { })
367 setFileMode(args.mode);
368 setOptions(args.options);
369 selectFile(args.selection);
373
374
375QFileDialog::~QFileDialog()
378#if QT_CONFIG(settings)
381 if (QPlatformFileDialogHelper *platformHelper = d->platformFileDialogHelper()) {
384 QObjectPrivate::disconnect(platformHelper, &QPlatformFileDialogHelper::directoryEntered,
385 d, &QFileDialogPrivate::nativeEnterDirectory);
390
391
392
393
394
395
396
397
398
399
400
401
402void QFileDialog::setSidebarUrls(
const QList<QUrl> &urls)
405 if (!d->nativeDialogInUse)
406 d->qFileDialogUi->sidebar->setUrls(urls);
410
411
412QList<QUrl> QFileDialog::sidebarUrls()
const
414 Q_D(
const QFileDialog);
415 return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
418static const qint32 QFileDialogMagic = 0xbe;
421
422
423
424
425
426QByteArray QFileDialog::saveState()
const
428 Q_D(
const QFileDialog);
431 QDataStream stream(&data, QIODevice::WriteOnly);
432 stream.setVersion(QDataStream::Qt_5_0);
434 stream << qint32(QFileDialogMagic);
435 stream << qint32(version);
436 if (d->usingWidgets()) {
437 stream << d->qFileDialogUi->splitter->saveState();
438 stream << d->qFileDialogUi->sidebar->urls();
440 stream << d->splitterState;
441 stream << d->sidebarUrls;
444 stream << *lastVisitedDir();
445 if (d->usingWidgets())
446 stream << d->qFileDialogUi->treeView->header()->saveState();
448 stream << d->headerData;
449 stream << qint32(viewMode());
454
455
456
457
458
459
460
461bool QFileDialog::restoreState(
const QByteArray &state)
464 QByteArray sd = state;
465 QDataStream stream(&sd, QIODevice::ReadOnly);
466 stream.setVersion(QDataStream::Qt_5_0);
470 QUrl currentDirectory;
477 if (marker != QFileDialogMagic || (v != 3 && v != 4))
480 stream >> d->splitterState
484 QString currentDirectoryString;
485 stream >> currentDirectoryString;
486 currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
488 stream >> currentDirectory;
490 stream >> d->headerData
493 setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
494 setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
496 if (!d->usingWidgets())
499 return d->restoreWidgetState(history, -1);
503
504
505void QFileDialog::changeEvent(QEvent *e)
508 if (e->type() == QEvent::LanguageChange) {
509 d->retranslateWindowTitle();
510 d->retranslateStrings();
512 QDialog::changeEvent(e);
515QFileDialogPrivate::QFileDialogPrivate()
517#if QT_CONFIG(proxymodel)
521 currentHistoryLocation(-1),
522 renameAction(
nullptr),
523 deleteAction(
nullptr),
524 showHiddenAction(
nullptr),
525 useDefaultCaption(
true),
526 qFileDialogUi(
nullptr),
527 options(QFileDialogOptions::create())
531QFileDialogPrivate::~QFileDialogPrivate()
535void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
538 auto *fileDialogHelper =
static_cast<QPlatformFileDialogHelper *>(h);
539 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::fileSelected,
540 this, &QFileDialogPrivate::emitUrlSelected);
541 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::filesSelected,
542 this, &QFileDialogPrivate::emitUrlsSelected);
543 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::currentChanged,
544 this, &QFileDialogPrivate::nativeCurrentChanged);
545 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::directoryEntered,
546 this, &QFileDialogPrivate::nativeEnterDirectory);
547 QObject::connect(fileDialogHelper, &QPlatformFileDialogHelper::filterSelected,
548 q, &QFileDialog::filterSelected);
549 fileDialogHelper->setOptions(options);
552void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
555 options->setWindowTitle(q->windowTitle());
556 options->setHistory(q->history());
558 options->setSidebarUrls(qFileDialogUi->sidebar->urls());
559 if (options->initiallySelectedNameFilter().isEmpty())
560 options->setInitiallySelectedNameFilter(q->selectedNameFilter());
561 if (options->initiallySelectedFiles().isEmpty())
562 options->setInitiallySelectedFiles(userSelectedFiles());
565void QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
567 if (code == QDialog::Accepted) {
569 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
570 q->setSidebarUrls(options->sidebarUrls());
571 q->setHistory(options->history());
575void QFileDialogPrivate::retranslateWindowTitle()
578 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
580 if (q->acceptMode() == QFileDialog::AcceptOpen) {
581 const QFileDialog::FileMode fileMode = q->fileMode();
582 if (fileMode == QFileDialog::Directory)
583 q->setWindowTitle(QFileDialog::tr(
"Find Directory"));
585 q->setWindowTitle(QFileDialog::tr(
"Open"));
587 q->setWindowTitle(QFileDialog::tr(
"Save As"));
589 setWindowTitle = q->windowTitle();
592void QFileDialogPrivate::setLastVisitedDirectory(
const QUrl &dir)
594 *lastVisitedDir() = dir;
597void QFileDialogPrivate::updateLookInLabel()
599 if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))
600 setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));
603void QFileDialogPrivate::updateFileNameLabel()
605 if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
606 setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
608 switch (q_func()->fileMode()) {
609 case QFileDialog::Directory:
610 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"Directory:"));
613 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"File &name:"));
619void QFileDialogPrivate::updateFileTypeLabel()
621 if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))
622 setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));
625void QFileDialogPrivate::updateOkButtonText(
bool saveAsOnFolder)
629 if (saveAsOnFolder) {
630 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Open"));
631 }
else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
632 setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));
635 switch (q->fileMode()) {
636 case QFileDialog::Directory:
637 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Choose"));
640 setLabelTextControl(QFileDialog::Accept,
641 q->acceptMode() == QFileDialog::AcceptOpen ?
642 QFileDialog::tr(
"&Open") :
643 QFileDialog::tr(
"&Save"));
649void QFileDialogPrivate::updateCancelButtonText()
651 if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))
652 setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));
655void QFileDialogPrivate::retranslateStrings()
659 if (options->useDefaultNameFilters())
660 q->setNameFilter(QFileDialogOptions::defaultNameFilterString());
664 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
665 QAbstractItemModel *abstractModel = model;
666#if QT_CONFIG(proxymodel)
668 abstractModel = proxyModel;
670 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
671 for (
int i = 1; i < total; ++i) {
672 actions.at(i - 1)->setText(QFileDialog::tr(
"Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
676 renameAction->setText(QFileDialog::tr(
"&Rename"));
677 deleteAction->setText(QFileDialog::tr(
"&Delete"));
678 showHiddenAction->setText(QFileDialog::tr(
"Show &hidden files"));
679 newFolderAction->setText(QFileDialog::tr(
"&New Folder"));
680 qFileDialogUi->retranslateUi(q);
682 updateFileNameLabel();
683 updateFileTypeLabel();
684 updateCancelButtonText();
687void QFileDialogPrivate::emitFilesSelected(
const QStringList &files)
690 emit q->filesSelected(files);
691 if (files.size() == 1)
692 emit q->fileSelected(files.first());
695bool QFileDialogPrivate::canBeNativeDialog()
const
699 const QDialog *
const q =
static_cast<
const QDialog*>(q_ptr);
700 if (nativeDialogInUse)
702 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
703 || q->testAttribute(Qt::WA_DontShowOnScreen)
704 || (options->options() & QFileDialog::DontUseNativeDialog)) {
708 return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
711bool QFileDialogPrivate::usingWidgets()
const
713 return !nativeDialogInUse && qFileDialogUi;
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732void QFileDialog::setOption(Option option,
bool on)
734 const QFileDialog::Options previousOptions = options();
735 if (!(previousOptions & option) != !on)
736 setOptions(previousOptions ^ option);
740
741
742
743
744
745bool QFileDialog::testOption(Option option)
const
747 Q_D(
const QFileDialog);
748 return d->options->testOption(
static_cast<QFileDialogOptions::FileDialogOption>(option));
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769void QFileDialog::setOptions(Options options)
773 Options changed = (options ^ QFileDialog::options());
777 d->options->setOptions(QFileDialogOptions::FileDialogOptions(
int(options)));
779 if (options & DontUseNativeDialog) {
780 d->nativeDialogInUse =
false;
784 if (d->usingWidgets()) {
785 if (changed & DontResolveSymlinks)
786 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
787 if (changed & ReadOnly) {
788 bool ro = (options & ReadOnly);
789 d->model->setReadOnly(ro);
790 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
791 d->renameAction->setEnabled(!ro);
792 d->deleteAction->setEnabled(!ro);
795 if (changed & DontUseCustomDirectoryIcons) {
796 QFileIconProvider::Options providerOptions = iconProvider()->options();
797 providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons,
798 options & DontUseCustomDirectoryIcons);
799 iconProvider()->setOptions(providerOptions);
803 if (changed & HideNameFilterDetails)
804 setNameFilters(d->options->nameFilters());
806 if (changed & ShowDirsOnly)
807 setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
810QFileDialog::Options QFileDialog::options()
const
812 Q_D(
const QFileDialog);
813 static_assert((
int)QFileDialog::ShowDirsOnly == (
int)QFileDialogOptions::ShowDirsOnly);
814 static_assert((
int)QFileDialog::DontResolveSymlinks == (
int)QFileDialogOptions::DontResolveSymlinks);
815 static_assert((
int)QFileDialog::DontConfirmOverwrite == (
int)QFileDialogOptions::DontConfirmOverwrite);
816 static_assert((
int)QFileDialog::DontUseNativeDialog == (
int)QFileDialogOptions::DontUseNativeDialog);
817 static_assert((
int)QFileDialog::ReadOnly == (
int)QFileDialogOptions::ReadOnly);
818 static_assert((
int)QFileDialog::HideNameFilterDetails == (
int)QFileDialogOptions::HideNameFilterDetails);
819 static_assert((
int)QFileDialog::DontUseCustomDirectoryIcons == (
int)QFileDialogOptions::DontUseCustomDirectoryIcons);
820 return QFileDialog::Options(
int(d->options->options()));
824
825
826
827
828
829
830void QFileDialog::open(QObject *receiver,
const char *member)
833 const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))
834 : SIGNAL(fileSelected(QString));
835 connect(
this, signal, receiver, member);
836 d->signalToDisconnectOnClose = signal;
837 d->receiverToDisconnectOnClose = receiver;
838 d->memberToDisconnectOnClose = member;
845
846
847void QFileDialog::setVisible(
bool visible)
850 QDialog::setVisible(visible);
854
855
856
857
858
859void QFileDialogPrivate::setVisible(
bool visible)
863 const auto q =
static_cast<QDialog *>(q_ptr);
865 if (canBeNativeDialog()){
866 if (setNativeDialogVisible(visible)){
869 q->setAttribute(Qt::WA_DontShowOnScreen);
870#if QT_CONFIG(fscompleter)
872 if (!nativeDialogInUse)
873 completer->setModel(
nullptr);
875 }
else if (visible) {
877 q->setAttribute(Qt::WA_DontShowOnScreen,
false);
878#if QT_CONFIG(fscompleter)
879 if (!nativeDialogInUse) {
880 if (proxyModel !=
nullptr)
881 completer->setModel(proxyModel);
883 completer->setModel(model);
889 if (visible && usingWidgets())
890 qFileDialogUi->fileNameEdit->setFocus();
892 QDialogPrivate::setVisible(visible);
896
897
898
899void QFileDialogPrivate::goToUrl(
const QUrl &url)
903 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(),
true);
904 QModelIndex idx = model->d_func()->index(node);
909
910
911
912
915
916
917
918
919
920
921
922
923
924
925
926void QFileDialog::setDirectory(
const QString &directory)
929 QString newDirectory = directory;
931 if (!directory.isEmpty())
932 newDirectory = QDir::cleanPath(directory);
934 if (!directory.isEmpty() && newDirectory.isEmpty())
937 QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
938 QFileDialogPrivate::setLastVisitedDirectory(newDirUrl);
940 d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
941 if (!d->usingWidgets()) {
942 d->setDirectory_sys(newDirUrl);
945 if (d->rootPath() == newDirectory)
947 QModelIndex root = d->model->setRootPath(newDirectory);
948 if (!d->nativeDialogInUse) {
949 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
950 if (root != d->rootIndex()) {
951#if QT_CONFIG(fscompleter)
952 if (directory.endsWith(u'/'))
953 d->completer->setCompletionPrefix(newDirectory);
955 d->completer->setCompletionPrefix(newDirectory + u'/');
957 d->setRootIndex(root);
959 d->qFileDialogUi->listView->selectionModel()->clear();
964
965
966QDir QFileDialog::directory()
const
968 Q_D(
const QFileDialog);
969 if (d->nativeDialogInUse) {
970 QString dir = d->directory_sys().toLocalFile();
971 return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
973 return d->rootPath();
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993void QFileDialog::setDirectoryUrl(
const QUrl &directory)
996 if (!directory.isValid())
999 QFileDialogPrivate::setLastVisitedDirectory(directory);
1000 d->options->setInitialDirectory(directory);
1002 if (d->nativeDialogInUse)
1003 d->setDirectory_sys(directory);
1004 else if (directory.isLocalFile())
1005 setDirectory(directory.toLocalFile());
1006 else if (Q_UNLIKELY(d->usingWidgets()))
1007 qWarning(
"Non-native QFileDialog supports only local files");
1011
1012
1013
1014
1015QUrl QFileDialog::directoryUrl()
const
1017 Q_D(
const QFileDialog);
1018 if (d->nativeDialogInUse)
1019 return d->directory_sys();
1021 return QUrl::fromLocalFile(directory().absolutePath());
1028#if defined(Q_OS_WIN)
1032#elif defined(Q_OS_MACOS)
1033 return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE) == 1;
1043 if (!QFileInfo(path).isAbsolute())
1045 if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
1046 path.remove(0, rootPath.size());
1051 if (path.at(0) == QDir::separator()
1054 || path.at(0) == u'/'
1063
1064
1065
1066
1067void QFileDialog::selectFile(
const QString &filename)
1070 if (filename.isEmpty())
1073 if (!d->usingWidgets()) {
1075 if (QFileInfo(filename).isRelative()) {
1076 url = d->options->initialDirectory();
1077 QString path = url.path();
1078 if (!path.endsWith(u'/'))
1080 url.setPath(path + filename);
1082 url = QUrl::fromLocalFile(filename);
1084 d->selectFile_sys(url);
1085 d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
1089 if (!QDir::isRelativePath(filename)) {
1090 QFileInfo info(filename);
1091 QString filenamePath = info.absoluteDir().path();
1093 if (d->model->rootPath() != filenamePath)
1094 setDirectory(filenamePath);
1097 QModelIndex index = d->model->index(filename);
1098 d->qFileDialogUi->listView->selectionModel()->clear();
1099 if (!isVisible() || !d->lineEdit()->hasFocus())
1100 d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
1104
1105
1106
1107
1108
1109
1110
1111void QFileDialog::selectUrl(
const QUrl &url)
1117 if (d->nativeDialogInUse)
1118 d->selectFile_sys(url);
1119 else if (url.isLocalFile())
1120 selectFile(url.toLocalFile());
1122 qWarning(
"Non-native QFileDialog supports only local files");
1126static QString homeDirFromPasswdEntry(
const QString &path,
const QByteArray &userName)
1128#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1131 long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
1134 QVarLengthArray<
char, 1024> buf(bufSize);
1136# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0
< 199506L
)
1137 tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());
1139 err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);
1143 return QFile::decodeName(pw.pw_dir);
1145 passwd *pw = getpwnam(userName.constData());
1148 return QFile::decodeName(pw->pw_dir);
1152Q_AUTOTEST_EXPORT QString qt_tildeExpansion(
const QString &path)
1154 if (!path.startsWith(u'~'))
1157 if (path.size() == 1)
1158 return QDir::homePath();
1160 QStringView sv(path);
1161 const qsizetype sepIndex = sv.indexOf(QDir::separator());
1163 return QDir::homePath() + sv.sliced(1);
1165#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1167 return QDir::homePath();
1168 return QDir::homePath() + sv.sliced(sepIndex);
1170 const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen(
"~")
1171 : path.size() - strlen(
"~");
1172 const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();
1173 QString homePath = homeDirFromPasswdEntry(path, userName);
1176 return homePath + sv.sliced(sepIndex);
1182
1183
1184QStringList QFileDialogPrivate::typedFiles()
const
1186 Q_Q(
const QFileDialog);
1188 QString editText = lineEdit()->text();
1189 if (!editText.contains(u'"')) {
1191 const QString prefix = q->directory().absolutePath() + QDir::separator();
1192 if (QFile::exists(prefix + editText))
1195 files << qt_tildeExpansion(editText);
1203 QStringList tokens = editText.split(u'\"');
1204 for (
int i=0; i<tokens.size(); ++i) {
1208 const QString token = tokens.at(i);
1209 const QString prefix = q->directory().absolutePath() + QDir::separator();
1210 if (QFile::exists(prefix + token))
1213 files << qt_tildeExpansion(token);
1215 files << toInternal(tokens.at(i));
1219 return addDefaultSuffixToFiles(files);
1225QList<QUrl> QFileDialogPrivate::userSelectedFiles()
const
1229 if (!usingWidgets())
1230 return addDefaultSuffixToUrls(selectedFiles_sys());
1232 const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
1233 files.reserve(selectedRows.size());
1234 for (
const QModelIndex &index : selectedRows)
1235 files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));
1237 if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
1238 const QStringList typedFilesList = typedFiles();
1239 files.reserve(typedFilesList.size());
1240 for (
const QString &path : typedFilesList)
1241 files.append(QUrl::fromLocalFile(path));
1247QStringList QFileDialogPrivate::addDefaultSuffixToFiles(
const QStringList &filesToFix)
const
1250 for (
int i=0; i<filesToFix.size(); ++i) {
1251 QString name = toInternal(filesToFix.at(i));
1252 QFileInfo info(name);
1254 const QString defaultSuffix = options->defaultSuffix();
1255 if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
1256 name += u'.' + defaultSuffix;
1258 if (info.isAbsolute()) {
1264 QString path = rootPath();
1265 if (!path.endsWith(u'/'))
1274QList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(
const QList<QUrl> &urlsToFix)
const
1277 urls.reserve(urlsToFix.size());
1279 const QString defaultSuffix = options->defaultSuffix();
1280 for (QUrl url : urlsToFix) {
1281 if (!defaultSuffix.isEmpty()) {
1282 const QString urlPath = url.path();
1283 const auto idx = urlPath.lastIndexOf(u'/');
1284 if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
1285 url.setPath(urlPath + u'.' + defaultSuffix);
1294
1295
1296
1297
1298
1299
1300QStringList QFileDialog::selectedFiles()
const
1302 Q_D(
const QFileDialog);
1305 const QList<QUrl> userSelectedFiles = d->userSelectedFiles();
1306 files.reserve(userSelectedFiles.size());
1307 for (
const QUrl &file : userSelectedFiles)
1308 files.append(file.toString(QUrl::PreferLocalFile));
1310 if (files.isEmpty() && d->usingWidgets()) {
1311 const FileMode fm = fileMode();
1312 if (fm != ExistingFile && fm != ExistingFiles)
1313 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1319
1320
1321
1322
1323
1324
1325
1326QList<QUrl> QFileDialog::selectedUrls()
const
1328 Q_D(
const QFileDialog);
1329 if (d->nativeDialogInUse) {
1330 return d->userSelectedFiles();
1333 const QStringList selectedFileList = selectedFiles();
1334 urls.reserve(selectedFileList.size());
1335 for (
const QString &file : selectedFileList)
1336 urls.append(QUrl::fromLocalFile(file));
1342
1343
1344
1347 if (filter.isEmpty())
1348 return QStringList();
1351 if (!filter.contains(sep) && filter.contains(u'\n'))
1354 return filter.split(sep);
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372void QFileDialog::setNameFilter(
const QString &filter)
1374 setNameFilters(qt_make_filter_list(filter));
1379
1380
1383#if QT_CONFIG(regularexpression)
1384 QStringList strippedFilters;
1385 static const QRegularExpression r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
1386 strippedFilters.reserve(filters.size());
1387 for (
const QString &filter : filters) {
1389 auto match = r.match(filter);
1390 if (match.hasMatch())
1391 filterName = match.captured(1);
1392 strippedFilters.append(filterName.simplified());
1394 return strippedFilters;
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418void QFileDialog::setNameFilters(
const QStringList &filters)
1421 QStringList cleanedFilters;
1422 cleanedFilters.reserve(filters.size());
1423 for (
const QString &filter : filters)
1424 cleanedFilters << filter.simplified();
1426 d->options->setNameFilters(cleanedFilters);
1428 if (!d->usingWidgets())
1431 d->qFileDialogUi->fileTypeCombo->clear();
1432 if (cleanedFilters.isEmpty())
1435 if (testOption(HideNameFilterDetails))
1436 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1438 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1440 d->useNameFilter(0);
1444
1445
1446
1447QStringList QFileDialog::nameFilters()
const
1449 return d_func()->options->nameFilters();
1453
1454
1455
1456
1457
1458void QFileDialog::selectNameFilter(
const QString &filter)
1461 d->options->setInitiallySelectedNameFilter(filter);
1462 if (!d->usingWidgets()) {
1463 d->selectNameFilter_sys(filter);
1467 if (testOption(HideNameFilterDetails)) {
1468 const QStringList filters = qt_strip_filters(qt_make_filter_list(filter));
1469 if (!filters.isEmpty())
1470 i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());
1472 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1475 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1476 d->useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1481
1482
1483
1484
1485QString QFileDialog::selectedNameFilter()
const
1487 Q_D(
const QFileDialog);
1488 if (!d->usingWidgets())
1489 return d->selectedNameFilter_sys();
1491 if (testOption(HideNameFilterDetails)) {
1492 const auto idx = d->qFileDialogUi->fileTypeCombo->currentIndex();
1493 if (idx >= 0 && idx < d->options->nameFilters().size())
1494 return d->options->nameFilters().at(d->qFileDialogUi->fileTypeCombo->currentIndex());
1496 return d->qFileDialogUi->fileTypeCombo->currentText();
1500
1501
1502
1503
1504QDir::Filters QFileDialog::filter()
const
1506 Q_D(
const QFileDialog);
1507 if (d->usingWidgets())
1508 return d->model->filter();
1509 return d->options->filter();
1513
1514
1515
1516
1517
1519void QFileDialog::setFilter(QDir::Filters filters)
1522 d->options->setFilter(filters);
1523 if (!d->usingWidgets()) {
1528 d->model->setFilter(filters);
1529 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1532#if QT_CONFIG(mimetype)
1534static QString nameFilterForMime(
const QString &mimeType)
1537 QMimeType mime(db.mimeTypeForName(mimeType));
1538 if (mime.isValid()) {
1539 if (mime.isDefault()) {
1540 return QFileDialog::tr(
"All files (*)");
1542 const QString patterns = mime.globPatterns().join(u' ');
1543 return mime.comment() +
" ("_L1 + patterns + u')';
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566void QFileDialog::setMimeTypeFilters(
const QStringList &filters)
1569 QStringList nameFilters;
1570 for (
const QString &mimeType : filters) {
1571 const QString text = nameFilterForMime(mimeType);
1572 if (!text.isEmpty())
1573 nameFilters.append(text);
1575 setNameFilters(nameFilters);
1576 d->options->setMimeTypeFilters(filters);
1580
1581
1582
1583
1584
1585QStringList QFileDialog::mimeTypeFilters()
const
1587 return d_func()->options->mimeTypeFilters();
1591
1592
1593
1594
1595
1596void QFileDialog::selectMimeTypeFilter(
const QString &filter)
1599 d->options->setInitiallySelectedMimeTypeFilter(filter);
1601 const QString filterForMime = nameFilterForMime(filter);
1603 if (!d->usingWidgets()) {
1604 d->selectMimeTypeFilter_sys(filter);
1605 if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
1606 selectNameFilter(filterForMime);
1608 }
else if (!filterForMime.isEmpty()) {
1609 selectNameFilter(filterForMime);
1616
1617
1618
1619QString QFileDialog::selectedMimeTypeFilter()
const
1621 Q_D(
const QFileDialog);
1622 QString mimeTypeFilter;
1623 if (!d->usingWidgets())
1624 mimeTypeFilter = d->selectedMimeTypeFilter_sys();
1626#if QT_CONFIG(mimetype)
1627 if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
1628 const auto nameFilter = selectedNameFilter();
1629 const auto mimeTypes = d->options->mimeTypeFilters();
1630 for (
const auto &mimeType: mimeTypes) {
1631 QString filter = nameFilterForMime(mimeType);
1632 if (testOption(HideNameFilterDetails))
1633 filter = qt_strip_filters({ filter }).constFirst();
1634 if (filter == nameFilter) {
1635 mimeTypeFilter = mimeType;
1642 return mimeTypeFilter;
1646
1647
1648
1649
1650
1651
1652
1653
1654void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
1657 d->options->setViewMode(
static_cast<QFileDialogOptions::ViewMode>(mode));
1658 if (!d->usingWidgets())
1661 d->showDetailsView();
1666QFileDialog::ViewMode QFileDialog::viewMode()
const
1668 Q_D(
const QFileDialog);
1669 if (!d->usingWidgets())
1670 return static_cast<QFileDialog::ViewMode>(d->options->viewMode());
1671 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689void QFileDialog::setFileMode(QFileDialog::FileMode mode)
1692 d->options->setFileMode(
static_cast<QFileDialogOptions::FileMode>(mode));
1693 if (!d->usingWidgets())
1696 d->retranslateWindowTitle();
1699 QAbstractItemView::SelectionMode selectionMode;
1700 if (mode == QFileDialog::ExistingFiles)
1701 selectionMode = QAbstractItemView::ExtendedSelection;
1703 selectionMode = QAbstractItemView::SingleSelection;
1704 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1705 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1707 d->model->setFilter(d->filterForMode(filter()));
1709 if (mode == Directory) {
1710 d->qFileDialogUi->fileTypeCombo->clear();
1711 d->qFileDialogUi->fileTypeCombo->addItem(tr(
"Directories"));
1712 d->qFileDialogUi->fileTypeCombo->setEnabled(
false);
1714 d->updateFileNameLabel();
1715 d->updateOkButtonText();
1716 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1717 d->updateOkButton();
1720QFileDialog::FileMode QFileDialog::fileMode()
const
1722 Q_D(
const QFileDialog);
1723 return static_cast<FileMode>(d->options->fileMode());
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
1739 d->options->setAcceptMode(
static_cast<QFileDialogOptions::AcceptMode>(mode));
1741 setAttribute(Qt::WA_DontShowOnScreen,
false);
1742 if (!d->usingWidgets())
1744 QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
1745 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1746 d->qFileDialogUi->buttonBox->button(button)->setEnabled(
false);
1747 d->updateOkButton();
1748 if (mode == AcceptSave) {
1749 d->qFileDialogUi->lookInCombo->setEditable(
false);
1751 d->retranslateWindowTitle();
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1767void QFileDialog::setSupportedSchemes(
const QStringList &schemes)
1770 d->options->setSupportedSchemes(schemes);
1773QStringList QFileDialog::supportedSchemes()
const
1775 return d_func()->options->supportedSchemes();
1779
1780
1781
1782QModelIndex QFileDialogPrivate::rootIndex()
const {
1783 return mapToSource(qFileDialogUi->listView->rootIndex());
1786QAbstractItemView *QFileDialogPrivate::currentView()
const {
1787 if (!qFileDialogUi->stackedWidget)
1789 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1790 return qFileDialogUi->listView;
1791 return qFileDialogUi->treeView;
1794QLineEdit *QFileDialogPrivate::lineEdit()
const {
1795 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1798long QFileDialogPrivate::maxNameLength(
const QString &path)
1800#if defined(Q_OS_UNIX)
1801 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1802#elif defined(Q_OS_WIN)
1804 const QString drive = path.left(3);
1805 if (::GetVolumeInformation(
reinterpret_cast<
const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) ==
false)
1815
1816
1817void QFileDialogPrivate::setRootIndex(
const QModelIndex &index)
const {
1818 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1819 QModelIndex idx = mapFromSource(index);
1820 qFileDialogUi->treeView->setRootIndex(idx);
1821 qFileDialogUi->listView->setRootIndex(idx);
1824
1825
1826
1827QModelIndex QFileDialogPrivate::select(
const QModelIndex &index)
const {
1828 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1830 QModelIndex idx = mapFromSource(index);
1831 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1832 qFileDialogUi->listView->selectionModel()->select(idx,
1833 QItemSelectionModel::Select | QItemSelectionModel::Rows);
1837QFileDialog::AcceptMode QFileDialog::acceptMode()
const
1839 Q_D(
const QFileDialog);
1840 return static_cast<AcceptMode>(d->options->acceptMode());
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854void QFileDialog::setDefaultSuffix(
const QString &suffix)
1857 d->options->setDefaultSuffix(suffix);
1860QString QFileDialog::defaultSuffix()
const
1862 Q_D(
const QFileDialog);
1863 return d->options->defaultSuffix();
1867
1868
1869
1870void QFileDialog::setHistory(
const QStringList &paths)
1873 if (d->usingWidgets())
1874 d->qFileDialogUi->lookInCombo->setHistory(paths);
1882 const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1884 const QUrl url = idx.isValid()
1885 ? QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()))
1889 urlModel->setUrls(list);
1893
1894
1895QStringList QFileDialog::history()
const
1897 Q_D(
const QFileDialog);
1898 if (!d->usingWidgets())
1899 return QStringList();
1900 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1902 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1903 if (!currentHistory.contains(newHistory))
1904 currentHistory << newHistory;
1905 return currentHistory;
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
1929 if (!d->usingWidgets())
1931 d->qFileDialogUi->listView->setItemDelegate(delegate);
1932 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1936
1937
1938QAbstractItemDelegate *QFileDialog::itemDelegate()
const
1940 Q_D(
const QFileDialog);
1941 if (!d->usingWidgets())
1943 return d->qFileDialogUi->listView->itemDelegate();
1947
1948
1949void QFileDialog::setIconProvider(QAbstractFileIconProvider *provider)
1952 if (!d->usingWidgets())
1954 d->model->setIconProvider(provider);
1956 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1960
1961
1962QAbstractFileIconProvider *QFileDialog::iconProvider()
const
1964 Q_D(
const QFileDialog);
1967 return d->model->iconProvider();
1970void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label,
const QString &text)
1975 case QFileDialog::LookIn:
1976 qFileDialogUi->lookInLabel->setText(text);
1978 case QFileDialog::FileName:
1979 qFileDialogUi->fileNameLabel->setText(text);
1981 case QFileDialog::FileType:
1982 qFileDialogUi->fileTypeLabel->setText(text);
1984 case QFileDialog::Accept:
1985 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
1986 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
1987 button->setText(text);
1989 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
1990 button->setText(text);
1993 case QFileDialog::Reject:
1994 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
1995 button->setText(text);
2001
2002
2004void QFileDialog::setLabelText(DialogLabel label,
const QString &text)
2007 d->options->setLabelText(
static_cast<QFileDialogOptions::DialogLabel>(label), text);
2008 d->setLabelTextControl(label, text);
2012
2013
2014QString QFileDialog::labelText(DialogLabel label)
const
2016 Q_D(
const QFileDialog);
2017 if (!d->usingWidgets())
2018 return d->options->labelText(
static_cast<QFileDialogOptions::DialogLabel>(label));
2019 QPushButton *button;
2022 return d->qFileDialogUi->lookInLabel->text();
2024 return d->qFileDialogUi->fileNameLabel->text();
2026 return d->qFileDialogUi->fileTypeLabel->text();
2028 if (acceptMode() == AcceptOpen)
2029 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
2031 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
2033 return button->text();
2036 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
2038 return button->text();
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086QString QFileDialog::getOpenFileName(QWidget *parent,
2087 const QString &caption,
2089 const QString &filter,
2090 QString *selectedFilter,
2093 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2094 const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2095 selectedFilter, options, schemes);
2096 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2097 return selectedUrl.toLocalFile();
2099 return selectedUrl.toString();
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
2130 const QString &caption,
2132 const QString &filter,
2133 QString *selectedFilter,
2135 const QStringList &supportedSchemes)
2137 QFileDialogArgs args(dir);
2138 args.parent = parent;
2139 args.caption = caption;
2140 args.filter = filter;
2141 args.mode = ExistingFile;
2142 args.options = options;
2144 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2145 dialog->setSupportedSchemes(supportedSchemes);
2146 if (selectedFilter && !selectedFilter->isEmpty())
2147 dialog->selectNameFilter(*selectedFilter);
2148 const int execResult = dialog->exec();
2149 if (
bool(dialog) && execResult == QDialog::Accepted) {
2151 *selectedFilter = dialog->selectedNameFilter();
2152 return dialog->selectedUrls().value(0);
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196QStringList QFileDialog::getOpenFileNames(QWidget *parent,
2197 const QString &caption,
2199 const QString &filter,
2200 QString *selectedFilter,
2203 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2204 const QList<QUrl> selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),
2205 filter, selectedFilter, options, schemes);
2206 QStringList fileNames;
2207 fileNames.reserve(selectedUrls.size());
2208 for (
const QUrl &url : selectedUrls)
2209 fileNames.append(url.toString(QUrl::PreferLocalFile));
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
2242 const QString &caption,
2244 const QString &filter,
2245 QString *selectedFilter,
2247 const QStringList &supportedSchemes)
2249 QFileDialogArgs args(dir);
2250 args.parent = parent;
2251 args.caption = caption;
2252 args.filter = filter;
2253 args.mode = ExistingFiles;
2254 args.options = options;
2256 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2257 dialog->setSupportedSchemes(supportedSchemes);
2258 if (selectedFilter && !selectedFilter->isEmpty())
2259 dialog->selectNameFilter(*selectedFilter);
2260 const int execResult = dialog->exec();
2261 if (
bool(dialog) && execResult == QDialog::Accepted) {
2263 *selectedFilter = dialog->selectedNameFilter();
2264 return dialog->selectedUrls();
2266 return QList<QUrl>();
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288void QFileDialog::getOpenFileContent(
const QString &nameFilter,
const std::function<
void(
const QString &,
const QByteArray &)> &fileOpenCompleted, QWidget *parent)
2292 auto openFileImpl = std::make_shared<std::function<
void(
void)>>();
2294 QByteArray fileContent;
2295 *openFileImpl = [=]()
mutable {
2296 auto fileDialogClosed = [&](
bool fileSelected) {
2297 if (!fileSelected) {
2298 fileOpenCompleted(fileName, fileContent);
2299 openFileImpl.reset();
2302 auto acceptFile = [&](uint64_t size,
const std::string name) ->
char * {
2303 const uint64_t twoGB = 1ULL << 31;
2307 fileName = QString::fromStdString(name);
2308 fileContent.resize(size);
2309 return fileContent.data();
2311 auto fileContentReady = [&]()
mutable {
2312 fileOpenCompleted(fileName, fileContent);
2313 openFileImpl.reset();
2316 QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
2321 QFileDialog *dialog =
new QFileDialog(parent);
2322 dialog->setFileMode(QFileDialog::ExistingFile);
2323 dialog->setNameFilter(nameFilter);
2324 dialog->setAttribute(Qt::WA_DeleteOnClose);
2326 auto fileSelected = [=](
const QString &fileName) {
2327 QByteArray fileContent;
2328 if (!fileName.isNull()) {
2329 QFile selectedFile(fileName);
2330 if (selectedFile.open(QIODevice::ReadOnly))
2331 fileContent = selectedFile.readAll();
2333 fileOpenCompleted(fileName, fileContent);
2336 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359void QFileDialog::saveFileContent(
const QByteArray &fileContent,
const QString &fileNameHint, QWidget *parent)
2363 QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
2365 QFileDialog *dialog =
new QFileDialog(parent);
2366 dialog->setAcceptMode(QFileDialog::AcceptSave);
2367 dialog->setFileMode(QFileDialog::AnyFile);
2368 dialog->selectFile(fileNameHint);
2370 auto fileSelected = [=](
const QString &fileName) {
2371 if (!fileName.isNull()) {
2372 QFile selectedFile(fileName);
2373 if (selectedFile.open(QIODevice::WriteOnly))
2374 selectedFile.write(fileContent);
2378 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2379 dialog->setAttribute(Qt::WA_DeleteOnClose);
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428QString QFileDialog::getSaveFileName(QWidget *parent,
2429 const QString &caption,
2431 const QString &filter,
2432 QString *selectedFilter,
2435 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2436 const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2437 selectedFilter, options, schemes);
2438 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2439 return selectedUrl.toLocalFile();
2441 return selectedUrl.toString();
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
2472 const QString &caption,
2474 const QString &filter,
2475 QString *selectedFilter,
2477 const QStringList &supportedSchemes)
2479 QFileDialogArgs args(dir);
2480 args.parent = parent;
2481 args.caption = caption;
2482 args.filter = filter;
2483 args.mode = AnyFile;
2484 args.options = options;
2486 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2487 dialog->setSupportedSchemes(supportedSchemes);
2488 dialog->setAcceptMode(AcceptSave);
2489 if (selectedFilter && !selectedFilter->isEmpty())
2490 dialog->selectNameFilter(*selectedFilter);
2491 const int execResult = dialog->exec();
2492 if (
bool(dialog) && execResult == QDialog::Accepted) {
2494 *selectedFilter = dialog->selectedNameFilter();
2495 return dialog->selectedUrls().value(0);
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540QString QFileDialog::getExistingDirectory(QWidget *parent,
2541 const QString &caption,
2545 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2546 const QUrl selectedUrl =
2547 getExistingDirectoryUrl(parent, caption, QUrl::fromLocalFile(dir), options, schemes);
2548 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2549 return selectedUrl.toLocalFile();
2551 return selectedUrl.toString();
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
2582 const QString &caption,
2585 const QStringList &supportedSchemes)
2587 QFileDialogArgs args(dir);
2588 args.parent = parent;
2589 args.caption = caption;
2590 args.mode = Directory;
2591 args.options = options;
2593 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2594 dialog->setSupportedSchemes(supportedSchemes);
2595 const int execResult = dialog->exec();
2596 if (
bool(dialog) && execResult == QDialog::Accepted)
2597 return dialog->selectedUrls().value(0);
2603 if (url.isLocalFile()) {
2604 QFileInfo info = local;
2605 if (!local.isAbsolute())
2606 info = QFileInfo(QDir::current(), url.toLocalFile());
2607 const QFileInfo pathInfo(info.absolutePath());
2608 if (!pathInfo.exists() || !pathInfo.isDir())
2610 if (info.exists() && info.isDir())
2611 return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));
2612 return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
2619#if QT_CONFIG(settings)
2620 if (lastVisitedDir()->isEmpty()) {
2621 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2622 const QString &lastVisisted = settings.value(
"FileDialog/lastVisited", QString()).toString();
2623 *lastVisitedDir() = QUrl::fromLocalFile(lastVisisted);
2629
2630
2634 const QFileInfo local(url.toLocalFile());
2637 directory = _qt_get_directory(url, local);
2638 if (directory.isEmpty()) {
2640 const QUrl lastVisited = *lastVisitedDir();
2641 if (lastVisited != url)
2642 directory = _qt_get_directory(lastVisited, QFileInfo());
2644 if (directory.isEmpty())
2645 directory = QUrl::fromLocalFile(QDir::currentPath());
2648
2649
2650
2651 if (selection.isEmpty() && !url.isEmpty()) {
2652 if (url.isLocalFile()) {
2654 selection = local.fileName();
2657 selection = url.fileName();
2663
2664
2665void QFileDialog::done(
int result)
2669 QDialog::done(result);
2671 if (d->receiverToDisconnectOnClose) {
2672 disconnect(
this, d->signalToDisconnectOnClose,
2673 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2674 d->receiverToDisconnectOnClose =
nullptr;
2676 d->memberToDisconnectOnClose.clear();
2677 d->signalToDisconnectOnClose.clear();
2680bool QFileDialogPrivate::itemAlreadyExists(
const QString &fileName)
2682#if QT_CONFIG(messagebox)
2684 const QString msg = QFileDialog::tr(
"%1 already exists.\nDo you want to replace it?").arg(fileName);
2685 using B = QMessageBox;
2686 const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
2687 return res == B::Yes;
2692void QFileDialogPrivate::itemNotFound(
const QString &fileName, QFileDialog::FileMode mode)
2694#if QT_CONFIG(messagebox)
2696 const QString message = mode == QFileDialog::Directory
2697 ? QFileDialog::tr(
"%1\nDirectory not found.\n"
2698 "Please verify the correct directory name was given.")
2699 : QFileDialog::tr(
"%1\nFile not found.\nPlease verify the "
2700 "correct file name was given.");
2702 QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
2707
2708
2709void QFileDialog::accept()
2712 if (!d->usingWidgets()) {
2713 const QList<QUrl> urls = selectedUrls();
2716 d->emitUrlsSelected(urls);
2717 if (urls.size() == 1)
2718 d->emitUrlSelected(urls.first());
2723 const QStringList files = selectedFiles();
2724 if (files.isEmpty())
2726 QString lineEditText = d->lineEdit()->text();
2729 if (lineEditText ==
".."_L1) {
2730 d->navigateToParent();
2731 const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
2732 d->lineEdit()->selectAll();
2736 const auto mode = fileMode();
2739 QString fn = files.first();
2742 info = QFileInfo(d->getEnvironmentVariable(fn));
2743 if (!info.exists()) {
2744 d->itemNotFound(info.fileName(), mode);
2748 d->emitFilesSelected(files);
2755 QString fn = files.first();
2758 setDirectory(info.absoluteFilePath());
2762 if (!info.exists()) {
2763 const long maxNameLength = d->maxNameLength(info.path());
2764 if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
2769 if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {
2770 d->emitFilesSelected(QStringList(fn));
2773 if (d->itemAlreadyExists(info.fileName())) {
2774 d->emitFilesSelected(QStringList(fn));
2783 for (
const auto &file : files) {
2784 QFileInfo info(file);
2786 info = QFileInfo(d->getEnvironmentVariable(file));
2787 if (!info.exists()) {
2788 d->itemNotFound(info.fileName(), mode);
2792 setDirectory(info.absoluteFilePath());
2793 d->lineEdit()->clear();
2797 d->emitFilesSelected(files);
2803#if QT_CONFIG(settings)
2804void QFileDialogPrivate::saveSettings()
2807 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2808 settings.beginGroup(
"FileDialog");
2810 if (usingWidgets()) {
2811 settings.setValue(
"sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
2812 settings.setValue(
"shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
2813 settings.setValue(
"treeViewHeader", qFileDialogUi->treeView->header()->saveState());
2815 QStringList historyUrls;
2816 const QStringList history = q->history();
2817 historyUrls.reserve(history.size());
2818 for (
const QString &path : history)
2819 historyUrls << QUrl::fromLocalFile(path).toString();
2820 settings.setValue(
"history", historyUrls);
2821 settings.setValue(
"lastVisited", lastVisitedDir()->toString());
2822 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2823 settings.setValue(
"viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
2824 settings.setValue(
"qtVersion", QT_VERSION_STR
""_L1);
2827bool QFileDialogPrivate::restoreFromSettings()
2830 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2831 if (!settings.childGroups().contains(
"FileDialog"_L1))
2833 settings.beginGroup(
"FileDialog");
2835 q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value(
"lastVisited").toUrl() : *lastVisitedDir());
2837 QByteArray viewModeStr = settings.value(
"viewMode").toString().toLatin1();
2838 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2840 int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
2842 viewMode = QFileDialog::List;
2843 q->setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
2845 sidebarUrls = QUrl::fromStringList(settings.value(
"shortcuts").toStringList());
2846 headerData = settings.value(
"treeViewHeader").toByteArray();
2848 if (!usingWidgets())
2851 QStringList history;
2852 const auto urlStrings = settings.value(
"history").toStringList();
2853 for (
const QString &urlStr : urlStrings) {
2855 if (url.isLocalFile())
2856 history << url.toLocalFile();
2859 return restoreWidgetState(history, settings.value(
"sidebarWidth", -1).toInt());
2863bool QFileDialogPrivate::restoreWidgetState(QStringList &history,
int splitterPosition)
2866 if (splitterPosition >= 0) {
2867 QList<
int> splitterSizes;
2868 splitterSizes.append(splitterPosition);
2869 splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
2870 qFileDialogUi->splitter->setSizes(splitterSizes);
2872 if (!qFileDialogUi->splitter->restoreState(splitterState))
2874 QList<
int> list = qFileDialogUi->splitter->sizes();
2875 if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
2876 for (
int i = 0; i < list.size(); ++i)
2877 list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
2878 qFileDialogUi->splitter->setSizes(list);
2882 qFileDialogUi->sidebar->setUrls(sidebarUrls);
2884 static const int MaxHistorySize = 5;
2885 if (history.size() > MaxHistorySize)
2886 history.erase(history.begin(), history.end() - MaxHistorySize);
2887 q->setHistory(history);
2889 QHeaderView *headerView = qFileDialogUi->treeView->header();
2890 if (!headerView->restoreState(headerData))
2893 QList<QAction*> actions = headerView->actions();
2894 QAbstractItemModel *abstractModel = model;
2895#if QT_CONFIG(proxymodel)
2897 abstractModel = proxyModel;
2899 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
2900 for (
int i = 1; i < total; ++i)
2901 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
2907
2908
2909
2910
2911void QFileDialogPrivate::init(
const QFileDialogArgs &args)
2914 if (!args.caption.isEmpty()) {
2915 useDefaultCaption =
false;
2916 setWindowTitle = args.caption;
2917 q->setWindowTitle(args.caption);
2920 q->setAcceptMode(QFileDialog::AcceptOpen);
2921 nativeDialogInUse = platformFileDialogHelper() !=
nullptr;
2922 if (!nativeDialogInUse)
2924 q->setFileMode(QFileDialog::AnyFile);
2925 if (!args.filter.isEmpty())
2926 q->setNameFilter(args.filter);
2927 q->setDirectoryUrl(args.directory);
2928 if (args.directory.isLocalFile())
2929 q->selectFile(args.selection);
2931 q->selectUrl(args.directory);
2933#if QT_CONFIG(settings)
2936 if (!restoreFromSettings()) {
2937 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
2938 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
2942#if defined(Q_EMBEDDED_SMALLSCREEN)
2943 qFileDialogUi->lookInLabel->setVisible(
false);
2944 qFileDialogUi->fileNameLabel->setVisible(
false);
2945 qFileDialogUi->fileTypeLabel->setVisible(
false);
2946 qFileDialogUi->sidebar->hide();
2949 const QSize sizeHint = q->sizeHint();
2950 if (sizeHint.isValid())
2951 q->resize(sizeHint);
2955
2956
2957
2958
2959void QFileDialogPrivate::createWidgets()
2968 QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
2969 Qt::WindowStates preState = q->windowState();
2971 model =
new QFileSystemModel(q);
2972 model->setIconProvider(&defaultIconProvider);
2973 model->setFilter(options->filter());
2974 model->setObjectName(
"qt_filesystem_model"_L1);
2975 if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
2976 model->setNameFilterDisables(helper->defaultNameFilterDisables());
2978 model->setNameFilterDisables(
false);
2979 model->d_func()->disableRecursiveSort =
true;
2980 QObjectPrivate::connect(model, &QFileSystemModel::fileRenamed,
2981 this, &QFileDialogPrivate::fileRenamed);
2982 QObjectPrivate::connect(model, &QFileSystemModel::rootPathChanged,
2983 this, &QFileDialogPrivate::pathChanged);
2984 QObjectPrivate::connect(model, &QFileSystemModel::rowsInserted,
2985 this, &QFileDialogPrivate::rowsInserted);
2986 model->setReadOnly(
false);
2988 qFileDialogUi.reset(
new Ui_QFileDialog());
2989 qFileDialogUi->setupUi(q);
2991 QList<QUrl> initialBookmarks;
2992 initialBookmarks << QUrl(
"file:"_L1)
2993 << QUrl::fromLocalFile(QDir::homePath());
2994 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
2995 QObjectPrivate::connect(qFileDialogUi->sidebar, &QSidebar::goToUrl,
2996 this, &QFileDialogPrivate::goToUrl);
2998 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::accepted,
2999 q, &QFileDialog::accept);
3000 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::rejected,
3001 q, &QFileDialog::reject);
3003 qFileDialogUi->lookInCombo->setFileDialogPrivate(
this);
3004 QObjectPrivate::connect(qFileDialogUi->lookInCombo, &QComboBox::textActivated,
3005 this, &QFileDialogPrivate::goToDirectory);
3007 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
3008 qFileDialogUi->lookInCombo->setDuplicatesEnabled(
false);
3011 qFileDialogUi->fileNameEdit->setFileDialogPrivate(
this);
3012#ifndef QT_NO_SHORTCUT
3013 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
3015#if QT_CONFIG(fscompleter)
3016 completer =
new QFSCompleter(model, q);
3017 qFileDialogUi->fileNameEdit->setCompleter(completer);
3020 qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
3022 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3023 this, &QFileDialogPrivate::autoCompleteFileName);
3024 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3025 this, &QFileDialogPrivate::updateOkButton);
3026 QObject::connect(qFileDialogUi->fileNameEdit, &QLineEdit::returnPressed,
3027 q, &QFileDialog::accept);
3030 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(
false);
3031 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
3032 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
3033 QObjectPrivate::connect(qFileDialogUi->fileTypeCombo, &QComboBox::activated,
3034 this, &QFileDialogPrivate::useNameFilter);
3035 QObject::connect(qFileDialogUi->fileTypeCombo, &QComboBox::textActivated,
3036 q, &QFileDialog::filterSelected);
3038 qFileDialogUi->listView->setFileDialogPrivate(
this);
3039 qFileDialogUi->listView->setModel(model);
3040 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::activated,
3041 this, &QFileDialogPrivate::enterDirectory);
3042 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::customContextMenuRequested,
3043 this, &QFileDialogPrivate::showContextMenu);
3044#ifndef QT_NO_SHORTCUT
3045 QShortcut *shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);
3046 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3047 this, &QFileDialogPrivate::deleteCurrent);
3050 qFileDialogUi->treeView->setFileDialogPrivate(
this);
3051 qFileDialogUi->treeView->setModel(model);
3052 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
3053 QFontMetrics fm(q->font());
3054 treeHeader->resizeSection(0, fm.horizontalAdvance(
"wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
3055 treeHeader->resizeSection(1, fm.horizontalAdvance(
"128.88 GB"_L1));
3056 treeHeader->resizeSection(2, fm.horizontalAdvance(
"mp3Folder"_L1));
3057 treeHeader->resizeSection(3, fm.horizontalAdvance(
"10/29/81 02:02PM"_L1));
3058 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
3060 QActionGroup *showActionGroup =
new QActionGroup(q);
3061 showActionGroup->setExclusive(
false);
3062 QObjectPrivate::connect(showActionGroup, &QActionGroup::triggered,
3063 this, &QFileDialogPrivate::showHeader);
3065 QAbstractItemModel *abstractModel = model;
3066#if QT_CONFIG(proxymodel)
3068 abstractModel = proxyModel;
3070 for (
int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
3071 QAction *showHeader =
new QAction(showActionGroup);
3072 showHeader->setCheckable(
true);
3073 showHeader->setChecked(
true);
3074 treeHeader->addAction(showHeader);
3077 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
3078 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
3080 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::activated,
3081 this, &QFileDialogPrivate::enterDirectory);
3082 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::customContextMenuRequested,
3083 this, &QFileDialogPrivate::showContextMenu);
3084#ifndef QT_NO_SHORTCUT
3085 shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);
3086 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3087 this, &QFileDialogPrivate::deleteCurrent);
3091 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
3092 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3093 this, &QFileDialogPrivate::selectionChanged);
3094 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3095 this, &QFileDialogPrivate::currentChanged);
3096 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
3098 createToolButtons();
3099 createMenuActions();
3101#if QT_CONFIG(settings)
3104 if (!restoreFromSettings()) {
3105 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
3106 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
3111 q->setFileMode(
static_cast<QFileDialog::FileMode>(options->fileMode()));
3112 q->setAcceptMode(
static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
3113 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
3114 q->setOptions(
static_cast<QFileDialog::Options>(
static_cast<
int>(options->options())));
3115 if (!options->sidebarUrls().isEmpty())
3116 q->setSidebarUrls(options->sidebarUrls());
3117 q->setDirectoryUrl(options->initialDirectory());
3118#if QT_CONFIG(mimetype)
3119 if (!options->mimeTypeFilters().isEmpty())
3120 q->setMimeTypeFilters(options->mimeTypeFilters());
3123 if (!options->nameFilters().isEmpty())
3124 q->setNameFilters(options->nameFilters());
3125 q->selectNameFilter(options->initiallySelectedNameFilter());
3126 q->setDefaultSuffix(options->defaultSuffix());
3127 q->setHistory(options->history());
3128 const auto initiallySelectedFiles = options->initiallySelectedFiles();
3129 if (initiallySelectedFiles.size() == 1)
3130 q->selectFile(initiallySelectedFiles.first().fileName());
3131 for (
const QUrl &url : initiallySelectedFiles)
3133 lineEdit()->selectAll();
3135 retranslateStrings();
3136 q->resize(preSize.isValid() ? preSize : q->sizeHint());
3137 q->setWindowState(preState);
3140void QFileDialogPrivate::showHeader(QAction *action)
3143 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
3144 qFileDialogUi->treeView->header()->setSectionHidden(
int(actionGroup->actions().indexOf(action) + 1),
3145 !action->isChecked());
3148#if QT_CONFIG(proxymodel)
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
3162 if (!d->usingWidgets())
3164 if ((!proxyModel && !d->proxyModel)
3165 || (proxyModel == d->proxyModel))
3168 QModelIndex idx = d->rootIndex();
3170 QObjectPrivate::disconnect(d->proxyModel, &QAbstractProxyModel::rowsInserted,
3171 d, &QFileDialogPrivate::rowsInserted);
3173 QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsInserted,
3174 d, &QFileDialogPrivate::rowsInserted);
3176 if (proxyModel !=
nullptr) {
3177 proxyModel->setParent(
this);
3178 d->proxyModel = proxyModel;
3179 proxyModel->setSourceModel(d->model);
3180 d->qFileDialogUi->listView->setModel(d->proxyModel);
3181 d->qFileDialogUi->treeView->setModel(d->proxyModel);
3182#if QT_CONFIG(fscompleter)
3183 d->completer->setModel(d->proxyModel);
3184 d->completer->proxyModel = d->proxyModel;
3186 QObjectPrivate::connect(d->proxyModel, &QAbstractItemModel::rowsInserted,
3187 d, &QFileDialogPrivate::rowsInserted);
3189 d->proxyModel =
nullptr;
3190 d->qFileDialogUi->listView->setModel(d->model);
3191 d->qFileDialogUi->treeView->setModel(d->model);
3192#if QT_CONFIG(fscompleter)
3193 d->completer->setModel(d->model);
3194 d->completer->sourceModel = d->model;
3195 d->completer->proxyModel =
nullptr;
3197 QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted,
3198 d, &QFileDialogPrivate::rowsInserted);
3200 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
3201 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
3203 d->setRootIndex(idx);
3206 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
3207 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3208 d, &QFileDialogPrivate::selectionChanged);
3209 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3210 d, &QFileDialogPrivate::currentChanged);
3214
3215
3216
3217
3218QAbstractProxyModel *QFileDialog::proxyModel()
const
3220 Q_D(
const QFileDialog);
3221 return d->proxyModel;
3226
3227
3228
3229
3230void QFileDialogPrivate::createToolButtons()
3233 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack,
nullptr, q));
3234 qFileDialogUi->backButton->setAutoRaise(
true);
3235 qFileDialogUi->backButton->setEnabled(
false);
3236 QObjectPrivate::connect(qFileDialogUi->backButton, &QPushButton::clicked,
3237 this, &QFileDialogPrivate::navigateBackward);
3239 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward,
nullptr, q));
3240 qFileDialogUi->forwardButton->setAutoRaise(
true);
3241 qFileDialogUi->forwardButton->setEnabled(
false);
3242 QObjectPrivate::connect(qFileDialogUi->forwardButton, &QPushButton::clicked,
3243 this, &QFileDialogPrivate::navigateForward);
3245 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent,
nullptr, q));
3246 qFileDialogUi->toParentButton->setAutoRaise(
true);
3247 qFileDialogUi->toParentButton->setEnabled(
false);
3248 QObjectPrivate::connect(qFileDialogUi->toParentButton, &QPushButton::clicked,
3249 this, &QFileDialogPrivate::navigateToParent);
3251 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView,
nullptr, q));
3252 qFileDialogUi->listModeButton->setAutoRaise(
true);
3253 qFileDialogUi->listModeButton->setDown(
true);
3254 QObjectPrivate::connect(qFileDialogUi->listModeButton, &QPushButton::clicked,
3255 this, &QFileDialogPrivate::showListView);
3257 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView,
nullptr, q));
3258 qFileDialogUi->detailModeButton->setAutoRaise(
true);
3259 QObjectPrivate::connect(qFileDialogUi->detailModeButton, &QPushButton::clicked,
3260 this, &QFileDialogPrivate::showDetailsView);
3262 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
3263 qFileDialogUi->backButton->setFixedSize(toolSize);
3264 qFileDialogUi->listModeButton->setFixedSize(toolSize);
3265 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
3266 qFileDialogUi->forwardButton->setFixedSize(toolSize);
3267 qFileDialogUi->toParentButton->setFixedSize(toolSize);
3269 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder,
nullptr, q));
3270 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
3271 qFileDialogUi->newFolderButton->setAutoRaise(
true);
3272 qFileDialogUi->newFolderButton->setEnabled(
false);
3273 QObjectPrivate::connect(qFileDialogUi->newFolderButton, &QPushButton::clicked,
3274 this, &QFileDialogPrivate::createDirectory);
3278
3279
3280
3281
3282void QFileDialogPrivate::createMenuActions()
3286 QAction *goHomeAction =
new QAction(q);
3287#ifndef QT_NO_SHORTCUT
3288 goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
3290 QObjectPrivate::connect(goHomeAction, &QAction::triggered,
3291 this, &QFileDialogPrivate::goHome);
3292 q->addAction(goHomeAction);
3296 QAction *goToParent =
new QAction(q);
3297 goToParent->setObjectName(
"qt_goto_parent_action"_L1);
3298#ifndef QT_NO_SHORTCUT
3299 goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
3301 QObjectPrivate::connect(goToParent, &QAction::triggered,
3302 this, &QFileDialogPrivate::navigateToParent);
3303 q->addAction(goToParent);
3305 renameAction =
new QAction(q);
3306 renameAction->setEnabled(
false);
3307 renameAction->setObjectName(
"qt_rename_action"_L1);
3308 QObjectPrivate::connect(renameAction, &QAction::triggered,
3309 this, &QFileDialogPrivate::renameCurrent);
3311 deleteAction =
new QAction(q);
3312 deleteAction->setEnabled(
false);
3313 deleteAction->setObjectName(
"qt_delete_action"_L1);
3314 QObjectPrivate::connect(deleteAction, &QAction::triggered,
3315 this, &QFileDialogPrivate::deleteCurrent);
3317 showHiddenAction =
new QAction(q);
3318 showHiddenAction->setObjectName(
"qt_show_hidden_action"_L1);
3319 showHiddenAction->setCheckable(
true);
3320 QObjectPrivate::connect(showHiddenAction, &QAction::triggered,
3321 this, &QFileDialogPrivate::showHidden);
3323 newFolderAction =
new QAction(q);
3324 newFolderAction->setObjectName(
"qt_new_folder_action"_L1);
3325 QObjectPrivate::connect(newFolderAction, &QAction::triggered,
3326 this, &QFileDialogPrivate::createDirectory);
3329void QFileDialogPrivate::goHome()
3332 q->setDirectory(QDir::homePath());
3336void QFileDialogPrivate::saveHistorySelection()
3338 if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
3340 auto &item = currentHistory[currentHistoryLocation];
3341 item.selection.clear();
3342 const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3343 for (
const auto &index : selectedIndexes)
3344 item.selection.append(QPersistentModelIndex(index));
3348
3349
3350
3351
3352void QFileDialogPrivate::pathChanged(
const QString &newPath)
3355 qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
3356 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
3357 q->setHistory(qFileDialogUi->lookInCombo->history());
3359 const QString newNativePath = QDir::toNativeSeparators(newPath);
3362 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
3363 if (currentHistoryLocation >= 0)
3364 saveHistorySelection();
3365 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
3366 currentHistory.removeLast();
3368 currentHistory.append({newNativePath, PersistentModelIndexList()});
3369 ++currentHistoryLocation;
3371 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
3372 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
3375void QFileDialogPrivate::navigate(HistoryItem &historyItem)
3378 q->setDirectory(historyItem.path);
3380 if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
3382 if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
3383 [](
const QPersistentModelIndex &i) {
return !i.isValid(); })) {
3384 historyItem.selection.clear();
3388 QAbstractItemView *view = q->viewMode() == QFileDialog::List
3389 ?
static_cast<QAbstractItemView *>(qFileDialogUi->listView)
3390 :
static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
3391 auto selectionModel = view->selectionModel();
3392 const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
3393 | QItemSelectionModel::Rows;
3394 selectionModel->select(historyItem.selection.constFirst(),
3395 flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);
3396 auto it = historyItem.selection.cbegin() + 1;
3397 const auto end = historyItem.selection.cend();
3398 for (; it != end; ++it)
3399 selectionModel->select(*it, flags);
3401 view->scrollTo(historyItem.selection.constFirst());
3405
3406
3407
3408
3409void QFileDialogPrivate::navigateBackward()
3411 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
3412 saveHistorySelection();
3413 navigate(currentHistory[--currentHistoryLocation]);
3418
3419
3420
3421
3422void QFileDialogPrivate::navigateForward()
3424 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
3425 saveHistorySelection();
3426 navigate(currentHistory[++currentHistoryLocation]);
3431
3432
3433
3434
3435
3436void QFileDialogPrivate::navigateToParent()
3439 QDir dir(model->rootDirectory());
3440 QString newDirectory;
3442 newDirectory = model->myComputer().toString();
3445 newDirectory = dir.absolutePath();
3447 q->setDirectory(newDirectory);
3448 emit q->directoryEntered(newDirectory);
3452
3453
3454
3455
3456void QFileDialogPrivate::createDirectory()
3459 qFileDialogUi->listView->clearSelection();
3461 QString newFolderString = QFileDialog::tr(
"New Folder");
3462 QString folderName = newFolderString;
3463 QString prefix = q->directory().absolutePath() + QDir::separator();
3464 if (QFile::exists(prefix + folderName)) {
3465 qlonglong suffix = 2;
3466 while (QFile::exists(prefix + folderName)) {
3467 folderName = newFolderString + QString::number(suffix++);
3471 QModelIndex parent = rootIndex();
3472 QModelIndex index = model->mkdir(parent, folderName);
3473 if (!index.isValid())
3476 index = select(index);
3477 if (index.isValid()) {
3478 qFileDialogUi->treeView->setCurrentIndex(index);
3479 currentView()->edit(index);
3483void QFileDialogPrivate::showListView()
3485 qFileDialogUi->listModeButton->setDown(
true);
3486 qFileDialogUi->detailModeButton->setDown(
false);
3487 qFileDialogUi->treeView->hide();
3488 qFileDialogUi->listView->show();
3489 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
3490 qFileDialogUi->listView->doItemsLayout();
3493void QFileDialogPrivate::showDetailsView()
3495 qFileDialogUi->listModeButton->setDown(
false);
3496 qFileDialogUi->detailModeButton->setDown(
true);
3497 qFileDialogUi->listView->hide();
3498 qFileDialogUi->treeView->show();
3499 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
3500 qFileDialogUi->treeView->doItemsLayout();
3504
3505
3506
3507
3508void QFileDialogPrivate::showContextMenu(
const QPoint &position)
3514 QAbstractItemView *view =
nullptr;
3515 if (q->viewMode() == QFileDialog::Detail)
3516 view = qFileDialogUi->treeView;
3518 view = qFileDialogUi->listView;
3519 QModelIndex index = view->indexAt(position);
3520 index = mapToSource(index.sibling(index.row(), 0));
3522 QMenu *menu =
new QMenu(view);
3523 menu->setAttribute(Qt::WA_DeleteOnClose);
3525 if (index.isValid()) {
3527 const bool ro = model && model->isReadOnly();
3528 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3529 renameAction->setEnabled(!ro && p & QFile::WriteUser);
3530 menu->addAction(renameAction);
3531 deleteAction->setEnabled(!ro && p & QFile::WriteUser);
3532 menu->addAction(deleteAction);
3533 menu->addSeparator();
3535 menu->addAction(showHiddenAction);
3536 if (qFileDialogUi->newFolderButton->isVisible()) {
3537 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
3538 menu->addAction(newFolderAction);
3540 menu->popup(view->viewport()->mapToGlobal(position));
3546
3547
3548void QFileDialogPrivate::renameCurrent()
3551 QModelIndex index = qFileDialogUi->listView->currentIndex();
3552 index = index.sibling(index.row(), 0);
3553 if (q->viewMode() == QFileDialog::List)
3554 qFileDialogUi->listView->edit(index);
3556 qFileDialogUi->treeView->edit(index);
3559bool QFileDialogPrivate::removeDirectory(
const QString &path)
3561 QModelIndex modelIndex = model->index(path);
3562 return model->remove(modelIndex);
3566
3567
3568
3569
3570void QFileDialogPrivate::deleteCurrent()
3572 if (model->isReadOnly())
3575 const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
3576 for (
auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
3577 QPersistentModelIndex index = *it;
3578 if (index == qFileDialogUi->listView->rootIndex())
3581 index = mapToSource(index.sibling(index.row(), 0));
3582 if (!index.isValid())
3585 QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
3586 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
3588 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3589#if QT_CONFIG(messagebox)
3591 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3592 QFileDialog::tr(
"'%1' is write protected.\nDo you want to delete it anyway?")
3594 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
3596 else if (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3597 QFileDialog::tr(
"Are you sure you want to delete '%1'?")
3599 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
3603 if (!index.isValid())
3607 if (!(p & QFile::WriteUser))
3611 if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
3612 if (!removeDirectory(filePath)) {
3613#if QT_CONFIG(messagebox)
3614 QMessageBox::warning(q, q->windowTitle(),
3615 QFileDialog::tr(
"Could not delete directory."));
3619 model->remove(index);
3624void QFileDialogPrivate::autoCompleteFileName(
const QString &text)
3626 if (text.startsWith(
"//"_L1) || text.startsWith(u'\\')) {
3627 qFileDialogUi->listView->selectionModel()->clearSelection();
3631 const QStringList multipleFiles = typedFiles();
3632 if (multipleFiles.size() > 0) {
3633 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
3634 QList<QModelIndex> newFiles;
3635 for (
const auto &file : multipleFiles) {
3636 QModelIndex idx = model->index(file);
3637 if (oldFiles.removeAll(idx) == 0)
3638 newFiles.append(idx);
3640 for (
const auto &newFile : std::as_const(newFiles))
3642 if (lineEdit()->hasFocus()) {
3643 auto *sm = qFileDialogUi->listView->selectionModel();
3644 for (
const auto &oldFile : std::as_const(oldFiles))
3645 sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
3651
3652
3653void QFileDialogPrivate::updateOkButton()
3656 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
3657 ? QDialogButtonBox::Open : QDialogButtonBox::Save);
3660 const QFileDialog::FileMode fileMode = q->fileMode();
3662 bool enableButton =
true;
3663 bool isOpenDirectory =
false;
3665 const QStringList files = q->selectedFiles();
3666 QString lineEditText = lineEdit()->text();
3668 if (lineEditText.startsWith(
"//"_L1) || lineEditText.startsWith(u'\\')) {
3669 button->setEnabled(
true);
3670 updateOkButtonText();
3674 if (files.isEmpty()) {
3675 enableButton =
false;
3676 }
else if (lineEditText ==
".."_L1) {
3677 isOpenDirectory =
true;
3680 case QFileDialog::Directory: {
3681 QString fn = files.first();
3682 QModelIndex idx = model->index(fn);
3684 idx = model->index(getEnvironmentVariable(fn));
3685 if (!idx.isValid() || !model->isDir(idx))
3686 enableButton =
false;
3689 case QFileDialog::AnyFile: {
3690 QString fn = files.first();
3692 QModelIndex idx = model->index(fn);
3696 fileDir = info.canonicalFilePath();
3698 fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
3699 fileName = fn.mid(fileDir.size() + 1);
3701 if (lineEditText.contains(
".."_L1)) {
3702 fileDir = info.canonicalFilePath();
3703 fileName = info.fileName();
3706 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
3707 enableButton =
false;
3710 if (idx.isValid() && model->isDir(idx)) {
3711 isOpenDirectory =
true;
3712 enableButton =
true;
3715 if (!idx.isValid()) {
3716 const long maxLength = maxNameLength(fileDir);
3717 enableButton = maxLength < 0 || fileName.size() <= maxLength;
3721 case QFileDialog::ExistingFile:
3722 case QFileDialog::ExistingFiles:
3723 for (
const auto &file : files) {
3724 QModelIndex idx = model->index(file);
3726 idx = model->index(getEnvironmentVariable(file));
3727 if (!idx.isValid()) {
3728 enableButton =
false;
3731 if (idx.isValid() && model->isDir(idx)) {
3732 isOpenDirectory =
true;
3742 button->setEnabled(enableButton);
3743 updateOkButtonText(isOpenDirectory);
3747
3748
3749void QFileDialogPrivate::currentChanged(
const QModelIndex &index)
3752 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
3756
3757
3758
3759
3760
3761void QFileDialogPrivate::enterDirectory(
const QModelIndex &index)
3765 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
3766 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
3767 if (path.isEmpty() || model->isDir(sourceIndex)) {
3768 const QFileDialog::FileMode fileMode = q->fileMode();
3769 q->setDirectory(path);
3770 emit q->directoryEntered(path);
3771 if (fileMode == QFileDialog::Directory) {
3773 lineEdit()->setText(QString());
3774 lineEdit()->clear();
3778 if ((!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick,
nullptr, qFileDialogUi->treeView)
3779 || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL))
3780 && index.model()->flags(index) & Qt::ItemIsEnabled) {
3787
3788
3789
3790
3791
3792void QFileDialogPrivate::goToDirectory(
const QString &path)
3794 enum { UrlRole = Qt::UserRole + 1 };
3796 #if QT_CONFIG(messagebox)
3799 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
3800 qFileDialogUi->lookInCombo->modelColumn(),
3801 qFileDialogUi->lookInCombo->rootModelIndex());
3802 QString path2 = path;
3803 if (!index.isValid())
3804 index = mapFromSource(model->index(getEnvironmentVariable(path)));
3806 path2 = index.data(UrlRole).toUrl().toLocalFile();
3807 index = mapFromSource(model->index(path2));
3811 dir.setPath(getEnvironmentVariable(path2));
3813 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
3814 enterDirectory(index);
3815#if QT_CONFIG(messagebox)
3817 QString message = QFileDialog::tr(
"%1\nDirectory not found.\nPlease verify the "
3818 "correct directory name was given.");
3819 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
3825
3826
3827
3828
3829
3830void QFileDialogPrivate::useNameFilter(
int index)
3832 QStringList nameFilters = options->nameFilters();
3833 if (index == nameFilters.size()) {
3834 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3835 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3836 options->setNameFilters(nameFilters);
3839 QString nameFilter = nameFilters.at(index);
3840 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3841 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3842 QString newNameFilterExtension;
3843 if (newNameFilters.size() > 0)
3844 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3846 QString fileName = lineEdit()->text();
3847 const QString fileNameExtension = QFileInfo(fileName).suffix();
3848 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3849 const qsizetype fileNameExtensionLength = fileNameExtension.size();
3850 fileName.replace(fileName.size() - fileNameExtensionLength,
3851 fileNameExtensionLength, newNameFilterExtension);
3852 qFileDialogUi->listView->clearSelection();
3853 lineEdit()->setText(fileName);
3857 model->setNameFilters(newNameFilters);
3861
3862
3863
3864
3865
3866void QFileDialogPrivate::selectionChanged()
3868 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3869 const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3870 bool stripDirs = fileMode != QFileDialog::Directory;
3872 QStringList allFiles;
3873 for (
const auto &index : indexes) {
3874 if (stripDirs && model->isDir(mapToSource(index)))
3876 allFiles.append(index.data().toString());
3878 if (allFiles.size() > 1)
3879 for (qsizetype i = 0; i < allFiles.size(); ++i) {
3880 allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
3883 QString finalFiles = allFiles.join(u' ');
3884 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3885 lineEdit()->setText(finalFiles);
3891
3892
3893
3894
3895void QFileDialogPrivate::showHidden()
3898 QDir::Filters dirFilters = q->filter();
3899 dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
3900 q->setFilter(dirFilters);
3904
3905
3906
3907
3908
3909void QFileDialogPrivate::rowsInserted(
const QModelIndex &parent)
3911 if (!qFileDialogUi->treeView
3912 || parent != qFileDialogUi->treeView->rootIndex()
3913 || !qFileDialogUi->treeView->selectionModel()
3914 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3915 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3919void QFileDialogPrivate::fileRenamed(
const QString &path,
const QString &oldName,
const QString &newName)
3921 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3922 if (fileMode == QFileDialog::Directory) {
3923 if (path == rootPath() && lineEdit()->text() == oldName)
3924 lineEdit()->setText(newName);
3928void QFileDialogPrivate::emitUrlSelected(
const QUrl &file)
3931 emit q->urlSelected(file);
3932 if (file.isLocalFile())
3933 emit q->fileSelected(file.toLocalFile());
3936void QFileDialogPrivate::emitUrlsSelected(
const QList<QUrl> &files)
3939 emit q->urlsSelected(files);
3940 QStringList localFiles;
3941 for (
const QUrl &file : files)
3942 if (file.isLocalFile())
3943 localFiles.append(file.toLocalFile());
3944 if (!localFiles.isEmpty())
3945 emit q->filesSelected(localFiles);
3948void QFileDialogPrivate::nativeCurrentChanged(
const QUrl &file)
3951 emit q->currentUrlChanged(file);
3952 if (file.isLocalFile())
3953 emit q->currentChanged(file.toLocalFile());
3956void QFileDialogPrivate::nativeEnterDirectory(
const QUrl &directory)
3959 emit q->directoryUrlEntered(directory);
3960 if (!directory.isEmpty()) {
3961 *lastVisitedDir() = directory;
3962 if (directory.isLocalFile())
3963 emit q->directoryEntered(directory.toLocalFile());
3968
3969
3970
3971
3972
3973
3974bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
3976#if QT_CONFIG(shortcut)
3978 if (event->matches(QKeySequence::Cancel)) {
3983 switch (event->key()) {
3984 case Qt::Key_Backspace:
3988#ifdef QT_KEYPAD_NAVIGATION
3989 if (QApplicationPrivate::keypadNavigationEnabled())
3993 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
4004QString QFileDialogPrivate::getEnvironmentVariable(
const QString &string)
4007 if (string.size() > 1 && string.startsWith(u'$')) {
4008 return qEnvironmentVariable(QStringView{string}.mid(1).toLatin1().constData());
4011 if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
4012 return qEnvironmentVariable(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData());
4020 urlModel =
new QUrlModel(
this);
4021 urlModel->showFullPath =
true;
4022 urlModel->setFileSystemModel(d_ptr->model);
4028 if (model()->rowCount() > 1)
4029 QComboBox::showPopup();
4031 urlModel->setUrls(QList<QUrl>());
4033 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
4034 while (idx.isValid()) {
4035 QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
4041 list.append(QUrl(
"file:"_L1));
4042 urlModel->addUrls(list, 0);
4043 idx = model()->index(model()->rowCount() - 1, 0);
4047 for (
int i = 0; i < m_history.size(); ++i) {
4048 QUrl path = QUrl::fromLocalFile(m_history.at(i));
4049 if (!urls.contains(path))
4052 if (urls.size() > 0) {
4053 model()->insertRow(model()->rowCount());
4054 idx = model()->index(model()->rowCount()-1, 0);
4056 model()->setData(idx, QFileDialog::tr(
"Recent Places"));
4057 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
4059 Qt::ItemFlags flags = m->flags(idx);
4060 flags &= ~Qt::ItemIsEnabled;
4061 m->item(idx.row(), idx.column())->setFlags(flags);
4063 urlModel->addUrls(urls, -1,
false);
4067 QComboBox::showPopup();
4073 QStylePainter painter(
this);
4074 painter.setPen(palette().color(QPalette::Text));
4077 QStyleOptionComboBox opt;
4078 initStyleOption(&opt);
4080 QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
4081 QStyle::SC_ComboBoxEditField,
this);
4082 int size = editRect.width() - opt.iconSize.width() - 4;
4083 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
4084 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
4087 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
4093 setSelectionBehavior(QAbstractItemView::SelectRows);
4095 setResizeMode(QListView::Adjust);
4096 setEditTriggers(QAbstractItemView::EditKeyPressed);
4097 setContextMenuPolicy(Qt::CustomContextMenu);
4098#if QT_CONFIG(draganddrop)
4099 setDragDropMode(QAbstractItemView::InternalMove);
4105 int height = qMax(10, sizeHintForRow(0));
4106 return QSize(QListView::sizeHint().width() * 2, height * 30);
4111#ifdef QT_KEYPAD_NAVIGATION
4112 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4113 QListView::keyPressEvent(e);
4118 if (!d_ptr->itemViewKeyboardEvent(e))
4119 QListView::keyPressEvent(e);
4126 setSelectionBehavior(QAbstractItemView::SelectRows);
4127 setRootIsDecorated(
false);
4128 setItemsExpandable(
false);
4129 setSortingEnabled(
true);
4130 header()->setSortIndicator(0, Qt::AscendingOrder);
4131 header()->setStretchLastSection(
false);
4132 setTextElideMode(Qt::ElideMiddle);
4133 setEditTriggers(QAbstractItemView::EditKeyPressed);
4134 setContextMenuPolicy(Qt::CustomContextMenu);
4135#if QT_CONFIG(draganddrop)
4136 setDragDropMode(QAbstractItemView::InternalMove);
4142#ifdef QT_KEYPAD_NAVIGATION
4143 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4144 QTreeView::keyPressEvent(e);
4149 if (!d_ptr->itemViewKeyboardEvent(e))
4150 QTreeView::keyPressEvent(e);
4156 int height = qMax(10, sizeHintForRow(0));
4157 QSize sizeHint = header()->sizeHint();
4158 return QSize(sizeHint.width() * 4, height * 30);
4162
4163
4164
4167#ifdef QT_KEYPAD_NAVIGATION
4168 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4169 QLineEdit::keyPressEvent(e);
4174#if QT_CONFIG(shortcut)
4177 QLineEdit::keyPressEvent(e);
4178#if QT_CONFIG(shortcut)
4179 if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
4184#if QT_CONFIG(fscompleter)
4186QString QFSCompleter::pathFromIndex(
const QModelIndex &index)
const
4188 const QFileSystemModel *dirModel;
4190 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4192 dirModel = sourceModel;
4193 QString currentLocation = dirModel->rootPath();
4194 QString path = index.data(QFileSystemModel::FilePathRole).toString();
4195 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
4196#if defined(Q_OS_UNIX)
4197 if (currentLocation == QDir::separator())
4198 return path.remove(0, currentLocation.size());
4200 if (currentLocation.endsWith(u'/'))
4201 return path.remove(0, currentLocation.size());
4203 return path.remove(0, currentLocation.size()+1);
4205 return index.data(QFileSystemModel::FilePathRole).toString();
4208QStringList QFSCompleter::splitPath(
const QString &path)
const
4211 return QStringList(completionPrefix());
4213 QString pathCopy = QDir::toNativeSeparators(path);
4214 QChar sep = QDir::separator();
4215#if defined(Q_OS_WIN)
4216 if (pathCopy ==
"\\"_L1 || pathCopy ==
"\\\\"_L1)
4217 return QStringList(pathCopy);
4218 QString doubleSlash(
"\\\\"_L1);
4219 if (pathCopy.startsWith(doubleSlash))
4220 pathCopy = pathCopy.mid(2);
4222 doubleSlash.clear();
4223#elif defined(Q_OS_UNIX)
4225 QString tildeExpanded = qt_tildeExpansion(pathCopy);
4226 if (tildeExpanded != pathCopy) {
4227 QFileSystemModel *dirModel;
4229 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
4231 dirModel = sourceModel;
4232 dirModel->fetchMore(dirModel->index(tildeExpanded));
4234 pathCopy = std::move(tildeExpanded);
4238#if defined(Q_OS_WIN)
4239 QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
4240 if (!doubleSlash.isEmpty() && !parts.isEmpty())
4241 parts[0].prepend(doubleSlash);
4242 if (pathCopy.endsWith(sep))
4243 parts.append(QString());
4245 QStringList parts = pathCopy.split(sep);
4246 if (pathCopy[0] == sep)
4250#if defined(Q_OS_WIN)
4251 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
4253 bool startsFromRoot = pathCopy[0] == sep;
4255 if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
4256 const QFileSystemModel *dirModel;
4258 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4260 dirModel = sourceModel;
4261 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
4262#if defined(Q_OS_WIN)
4263 if (currentLocation.endsWith(u':'))
4264 currentLocation.append(sep);
4266 if (currentLocation.contains(sep) && path != currentLocation) {
4267 QStringList currentLocationList = splitPath(currentLocation);
4268 while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) ==
".."_L1) {
4269 parts.removeFirst();
4270 currentLocationList.removeLast();
4272 if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
4273 currentLocationList.removeLast();
4274 return currentLocationList + parts;
4285#include "moc_qfiledialog.cpp"
void setHistory(const QStringList &paths)
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
void showPopup() override
Displays the list of items in the combobox.
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
QSize sizeHint() const override
QSize sizeHint() const override
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)
static void _qt_init_lastVisited()
QStringList qt_strip_filters(const QStringList &filters)
QStringList qt_make_filter_list(const QString &filter)
static QString fileFromPath(const QString &rootPath, QString path)
static bool isCaseSensitiveFileSystem(const QString &path)
QFileDialogArgs(const QUrl &url={})