6#include <private/qwidgetitemdata_p.h>
10#include <private/qapplication_p.h>
11#include <private/qguiapplication_p.h>
12#include <qfontmetrics.h>
14#include <qactiongroup.h>
15#include <qheaderview.h>
16#if QT_CONFIG(shortcut)
17# include <qshortcut.h>
19#include <qgridlayout.h>
23#if QT_CONFIG(messagebox)
24#include <qmessagebox.h>
27#if QT_CONFIG(settings)
31#if QT_CONFIG(mimetype)
32#include <qmimedatabase.h>
34#if QT_CONFIG(regularexpression)
35#include <qregularexpression.h>
37#include <qapplication.h>
38#include <qstylepainter.h>
39#include "ui_qfiledialog.h"
43#elif defined(Q_OS_WIN)
44# include <QtCore/qt_windows.h>
47#include <private/qwasmlocalfileaccess_p.h>
54using namespace Qt::StringLiterals;
56Q_GLOBAL_STATIC(QUrl, lastVisitedDir)
59
60
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
177
178
179
180
181
184
185
186
187
188
189
190
191
192
193
194
195
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
257
258
259
260
261
262
263
264
267
268
269
270
271
272
273
274
277
278
279
280
281
282
283
284
287
288
289
290
291
292
293
294
297
298
299
300
301
302
303
304
307
308
309
310
311
312
313
316
317
318
319
320
321
322
323
326
327
328
329
330
333
334
335
336
337
338
341
342
343
344
346QT_BEGIN_INCLUDE_NAMESPACE
348#if QT_CONFIG(shortcut)
349# include <qshortcut.h>
351QT_END_INCLUDE_NAMESPACE
354
355
356
357
358QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
359 : QDialog(*
new QFileDialogPrivate, parent, f)
362 QFileDialogArgs args;
367
368
369
370
371
372
373QFileDialog::QFileDialog(QWidget *parent,
374 const QString &caption,
375 const QString &directory,
376 const QString &filter)
377 : QDialog(*
new QFileDialogPrivate, parent, { })
380 QFileDialogArgs args(QUrl::fromLocalFile(directory));
381 args.filter = filter;
382 args.caption = caption;
387
388
389QFileDialog::QFileDialog(
const QFileDialogArgs &args)
390 : QDialog(*
new QFileDialogPrivate, args.parent, { })
394 setFileMode(args.mode);
395 setOptions(args.options);
396 selectFile(args.selection);
400
401
402QFileDialog::~QFileDialog()
405#if QT_CONFIG(settings)
408 if (QPlatformFileDialogHelper *platformHelper = d->platformFileDialogHelper()) {
411 QObjectPrivate::disconnect(platformHelper, &QPlatformFileDialogHelper::directoryEntered,
412 d, &QFileDialogPrivate::nativeEnterDirectory);
417
418
419
420
421
422
423
424
425
426
427
428
429void QFileDialog::setSidebarUrls(
const QList<QUrl> &urls)
432 if (!d->nativeDialogInUse)
433 d->qFileDialogUi->sidebar->setUrls(urls);
437
438
439QList<QUrl> QFileDialog::sidebarUrls()
const
441 Q_D(
const QFileDialog);
442 return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
445static const qint32 QFileDialogMagic = 0xbe;
448
449
450
451
452
453QByteArray QFileDialog::saveState()
const
455 Q_D(
const QFileDialog);
458 QDataStream stream(&data, QIODevice::WriteOnly);
459 stream.setVersion(QDataStream::Qt_5_0);
461 stream << qint32(QFileDialogMagic);
462 stream << qint32(version);
463 if (d->usingWidgets()) {
464 stream << d->qFileDialogUi->splitter->saveState();
465 stream << d->qFileDialogUi->sidebar->urls();
467 stream << d->splitterState;
468 stream << d->sidebarUrls;
471 stream << *lastVisitedDir();
472 if (d->usingWidgets())
473 stream << d->qFileDialogUi->treeView->header()->saveState();
475 stream << d->headerData;
476 stream << qint32(viewMode());
481
482
483
484
485
486
487
488bool QFileDialog::restoreState(
const QByteArray &state)
491 QByteArray sd = state;
492 QDataStream stream(&sd, QIODevice::ReadOnly);
493 stream.setVersion(QDataStream::Qt_5_0);
497 QUrl currentDirectory;
504 if (marker != QFileDialogMagic || (v != 3 && v != 4))
507 stream >> d->splitterState
511 QString currentDirectoryString;
512 stream >> currentDirectoryString;
513 currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
515 stream >> currentDirectory;
517 stream >> d->headerData
520 setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
521 setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
523 if (!d->usingWidgets())
526 return d->restoreWidgetState(history, -1);
530
531
532void QFileDialog::changeEvent(QEvent *e)
535 if (e->type() == QEvent::LanguageChange) {
536 d->retranslateWindowTitle();
537 d->retranslateStrings();
539 QDialog::changeEvent(e);
542QFileDialogPrivate::QFileDialogPrivate()
544#if QT_CONFIG(proxymodel)
548 currentHistoryLocation(-1),
549 renameAction(
nullptr),
550 deleteAction(
nullptr),
551 showHiddenAction(
nullptr),
552 useDefaultCaption(
true),
553 qFileDialogUi(
nullptr),
554 options(QFileDialogOptions::create())
558QFileDialogPrivate::~QFileDialogPrivate()
562void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
565 auto *fileDialogHelper =
static_cast<QPlatformFileDialogHelper *>(h);
566 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::fileSelected,
567 this, &QFileDialogPrivate::emitUrlSelected);
568 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::filesSelected,
569 this, &QFileDialogPrivate::emitUrlsSelected);
570 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::currentChanged,
571 this, &QFileDialogPrivate::nativeCurrentChanged);
572 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::directoryEntered,
573 this, &QFileDialogPrivate::nativeEnterDirectory);
574 QObject::connect(fileDialogHelper, &QPlatformFileDialogHelper::filterSelected,
575 q, &QFileDialog::filterSelected);
576 fileDialogHelper->setOptions(options);
579void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
582 options->setWindowTitle(q->windowTitle());
583 options->setHistory(q->history());
585 options->setSidebarUrls(qFileDialogUi->sidebar->urls());
586 if (options->initiallySelectedNameFilter().isEmpty())
587 options->setInitiallySelectedNameFilter(q->selectedNameFilter());
588 if (options->initiallySelectedFiles().isEmpty())
589 options->setInitiallySelectedFiles(userSelectedFiles());
592void QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
594 if (code == QDialog::Accepted) {
596 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
597 q->setSidebarUrls(options->sidebarUrls());
598 q->setHistory(options->history());
602void QFileDialogPrivate::retranslateWindowTitle()
605 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
607 if (q->acceptMode() == QFileDialog::AcceptOpen) {
608 const QFileDialog::FileMode fileMode = q->fileMode();
609 if (fileMode == QFileDialog::Directory)
610 q->setWindowTitle(QFileDialog::tr(
"Find Directory"));
612 q->setWindowTitle(QFileDialog::tr(
"Open"));
614 q->setWindowTitle(QFileDialog::tr(
"Save As"));
616 setWindowTitle = q->windowTitle();
619void QFileDialogPrivate::setLastVisitedDirectory(
const QUrl &dir)
621 *lastVisitedDir() = dir;
624void QFileDialogPrivate::updateLookInLabel()
626 if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))
627 setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));
630void QFileDialogPrivate::updateFileNameLabel()
632 if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
633 setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
635 switch (q_func()->fileMode()) {
636 case QFileDialog::Directory:
637 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"Directory:"));
640 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"File &name:"));
646void QFileDialogPrivate::updateFileTypeLabel()
648 if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))
649 setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));
652void QFileDialogPrivate::updateOkButtonText(
bool saveAsOnFolder)
656 if (saveAsOnFolder) {
657 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Open"));
658 }
else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
659 setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));
662 switch (q->fileMode()) {
663 case QFileDialog::Directory:
664 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Choose"));
667 setLabelTextControl(QFileDialog::Accept,
668 q->acceptMode() == QFileDialog::AcceptOpen ?
669 QFileDialog::tr(
"&Open") :
670 QFileDialog::tr(
"&Save"));
676void QFileDialogPrivate::updateCancelButtonText()
678 if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))
679 setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));
682void QFileDialogPrivate::retranslateStrings()
686 if (options->useDefaultNameFilters())
687 q->setNameFilter(QFileDialogOptions::defaultNameFilterString());
691 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
692 QAbstractItemModel *abstractModel = model;
693#if QT_CONFIG(proxymodel)
695 abstractModel = proxyModel;
697 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
698 for (
int i = 1; i < total; ++i) {
699 actions.at(i - 1)->setText(QFileDialog::tr(
"Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
703 renameAction->setText(QFileDialog::tr(
"&Rename"));
704 deleteAction->setText(QFileDialog::tr(
"&Delete"));
705 showHiddenAction->setText(QFileDialog::tr(
"Show &hidden files"));
706 newFolderAction->setText(QFileDialog::tr(
"&New Folder"));
707 qFileDialogUi->retranslateUi(q);
709 updateFileNameLabel();
710 updateFileTypeLabel();
711 updateCancelButtonText();
714void QFileDialogPrivate::emitFilesSelected(
const QStringList &files)
717 emit q->filesSelected(files);
718 if (files.size() == 1)
719 emit q->fileSelected(files.first());
722bool QFileDialogPrivate::canBeNativeDialog()
const
726 const QDialog *
const q =
static_cast<
const QDialog*>(q_ptr);
727 if (nativeDialogInUse)
729 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
730 || q->testAttribute(Qt::WA_DontShowOnScreen)
731 || (options->options() & QFileDialog::DontUseNativeDialog)) {
735 return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
738bool QFileDialogPrivate::usingWidgets()
const
740 return !nativeDialogInUse && qFileDialogUi;
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759void QFileDialog::setOption(Option option,
bool on)
761 const QFileDialog::Options previousOptions = options();
762 if (!(previousOptions & option) != !on)
763 setOptions(previousOptions ^ option);
767
768
769
770
771
772bool QFileDialog::testOption(Option option)
const
774 Q_D(
const QFileDialog);
775 return d->options->testOption(
static_cast<QFileDialogOptions::FileDialogOption>(option));
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796void QFileDialog::setOptions(Options options)
800 Options changed = (options ^ QFileDialog::options());
804 d->options->setOptions(QFileDialogOptions::FileDialogOptions(
int(options)));
806 if (options & DontUseNativeDialog) {
807 d->nativeDialogInUse =
false;
811 if (d->usingWidgets()) {
812 if (changed & DontResolveSymlinks)
813 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
814 if (changed & ReadOnly) {
815 bool ro = (options & ReadOnly);
816 d->model->setReadOnly(ro);
817 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
818 d->renameAction->setEnabled(!ro);
819 d->deleteAction->setEnabled(!ro);
822 if (changed & DontUseCustomDirectoryIcons) {
823 QFileIconProvider::Options providerOptions = iconProvider()->options();
824 providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons,
825 options & DontUseCustomDirectoryIcons);
826 iconProvider()->setOptions(providerOptions);
830 if (changed & HideNameFilterDetails)
831 setNameFilters(d->options->nameFilters());
833 if (changed & ShowDirsOnly)
834 setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
837QFileDialog::Options QFileDialog::options()
const
839 Q_D(
const QFileDialog);
840 static_assert((
int)QFileDialog::ShowDirsOnly == (
int)QFileDialogOptions::ShowDirsOnly);
841 static_assert((
int)QFileDialog::DontResolveSymlinks == (
int)QFileDialogOptions::DontResolveSymlinks);
842 static_assert((
int)QFileDialog::DontConfirmOverwrite == (
int)QFileDialogOptions::DontConfirmOverwrite);
843 static_assert((
int)QFileDialog::DontUseNativeDialog == (
int)QFileDialogOptions::DontUseNativeDialog);
844 static_assert((
int)QFileDialog::ReadOnly == (
int)QFileDialogOptions::ReadOnly);
845 static_assert((
int)QFileDialog::HideNameFilterDetails == (
int)QFileDialogOptions::HideNameFilterDetails);
846 static_assert((
int)QFileDialog::DontUseCustomDirectoryIcons == (
int)QFileDialogOptions::DontUseCustomDirectoryIcons);
847 return QFileDialog::Options(
int(d->options->options()));
851
852
853
854
855
856
857void QFileDialog::open(QObject *receiver,
const char *member)
860 const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))
861 : SIGNAL(fileSelected(QString));
862 connect(
this, signal, receiver, member);
863 d->signalToDisconnectOnClose = signal;
864 d->receiverToDisconnectOnClose = receiver;
865 d->memberToDisconnectOnClose = member;
872
873
874void QFileDialog::setVisible(
bool visible)
877 QDialog::setVisible(visible);
881
882
883
884
885
886void QFileDialogPrivate::setVisible(
bool visible)
890 const auto q =
static_cast<QDialog *>(q_ptr);
892 if (canBeNativeDialog()){
893 if (setNativeDialogVisible(visible)){
896 q->setAttribute(Qt::WA_DontShowOnScreen);
897#if QT_CONFIG(fscompleter)
899 if (!nativeDialogInUse)
900 completer->setModel(
nullptr);
902 }
else if (visible) {
904 q->setAttribute(Qt::WA_DontShowOnScreen,
false);
905#if QT_CONFIG(fscompleter)
906 if (!nativeDialogInUse) {
907 if (proxyModel !=
nullptr)
908 completer->setModel(proxyModel);
910 completer->setModel(model);
916 if (visible && usingWidgets())
917 qFileDialogUi->fileNameEdit->setFocus();
919 QDialogPrivate::setVisible(visible);
923
924
925
926void QFileDialogPrivate::goToUrl(
const QUrl &url)
930 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(),
true);
931 QModelIndex idx = model->d_func()->index(node);
936
937
938
939
942
943
944
945
946
947
948
949
950
951
952
953void QFileDialog::setDirectory(
const QString &directory)
956 QString newDirectory = directory;
958 if (!directory.isEmpty())
959 newDirectory = QDir::cleanPath(directory);
961 if (!directory.isEmpty() && newDirectory.isEmpty())
964 QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
965 QFileDialogPrivate::setLastVisitedDirectory(newDirUrl);
967 d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
968 if (!d->usingWidgets()) {
969 d->setDirectory_sys(newDirUrl);
972 if (d->rootPath() == newDirectory)
974 QModelIndex root = d->model->setRootPath(newDirectory);
975 if (!d->nativeDialogInUse) {
976 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
977 if (root != d->rootIndex()) {
978#if QT_CONFIG(fscompleter)
979 if (directory.endsWith(u'/'))
980 d->completer->setCompletionPrefix(newDirectory);
982 d->completer->setCompletionPrefix(newDirectory + u'/');
984 d->setRootIndex(root);
986 d->qFileDialogUi->listView->selectionModel()->clear();
991
992
993QDir QFileDialog::directory()
const
995 Q_D(
const QFileDialog);
996 if (d->nativeDialogInUse) {
997 QString dir = d->directory_sys().toLocalFile();
998 return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
1000 return d->rootPath();
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020void QFileDialog::setDirectoryUrl(
const QUrl &directory)
1023 if (!directory.isValid())
1026 QFileDialogPrivate::setLastVisitedDirectory(directory);
1027 d->options->setInitialDirectory(directory);
1029 if (d->nativeDialogInUse)
1030 d->setDirectory_sys(directory);
1031 else if (directory.isLocalFile())
1032 setDirectory(directory.toLocalFile());
1033 else if (Q_UNLIKELY(d->usingWidgets()))
1034 qWarning(
"Non-native QFileDialog supports only local files");
1038
1039
1040
1041
1042QUrl QFileDialog::directoryUrl()
const
1044 Q_D(
const QFileDialog);
1045 if (d->nativeDialogInUse)
1046 return d->directory_sys();
1048 return QUrl::fromLocalFile(directory().absolutePath());
1055#if defined(Q_OS_WIN)
1059#elif defined(Q_OS_MACOS)
1060 return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE) == 1;
1070 if (!QFileInfo(path).isAbsolute())
1072 if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
1073 path.remove(0, rootPath.size());
1078 if (path.at(0) == QDir::separator()
1081 || path.at(0) == u'/'
1090
1091
1092
1093
1094void QFileDialog::selectFile(
const QString &filename)
1097 if (filename.isEmpty())
1100 if (!d->usingWidgets()) {
1102 if (QFileInfo(filename).isRelative()) {
1103 url = d->options->initialDirectory();
1104 QString path = url.path();
1105 if (!path.endsWith(u'/'))
1107 url.setPath(path + filename);
1109 url = QUrl::fromLocalFile(filename);
1111 d->selectFile_sys(url);
1112 d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
1116 if (!QDir::isRelativePath(filename)) {
1117 QFileInfo info(filename);
1118 QString filenamePath = info.absoluteDir().path();
1120 if (d->model->rootPath() != filenamePath)
1121 setDirectory(filenamePath);
1124 QModelIndex index = d->model->index(filename);
1125 d->qFileDialogUi->listView->selectionModel()->clear();
1126 if (!isVisible() || !d->lineEdit()->hasFocus())
1127 d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
1131
1132
1133
1134
1135
1136
1137
1138void QFileDialog::selectUrl(
const QUrl &url)
1144 if (d->nativeDialogInUse)
1145 d->selectFile_sys(url);
1146 else if (url.isLocalFile())
1147 selectFile(url.toLocalFile());
1149 qWarning(
"Non-native QFileDialog supports only local files");
1153static QString homeDirFromPasswdEntry(
const QString &path,
const QByteArray &userName)
1155#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1158 long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
1161 QVarLengthArray<
char, 1024> buf(bufSize);
1163# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0
< 199506L
)
1164 tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());
1166 err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);
1170 return QFile::decodeName(pw.pw_dir);
1172 passwd *pw = getpwnam(userName.constData());
1175 return QFile::decodeName(pw->pw_dir);
1179Q_AUTOTEST_EXPORT QString qt_tildeExpansion(
const QString &path)
1181 if (!path.startsWith(u'~'))
1184 if (path.size() == 1)
1185 return QDir::homePath();
1187 QStringView sv(path);
1188 const qsizetype sepIndex = sv.indexOf(QDir::separator());
1190 return QDir::homePath() + sv.sliced(1);
1192#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1194 return QDir::homePath();
1195 return QDir::homePath() + sv.sliced(sepIndex);
1197 const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen(
"~")
1198 : path.size() - strlen(
"~");
1199 const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();
1200 QString homePath = homeDirFromPasswdEntry(path, userName);
1203 return homePath + sv.sliced(sepIndex);
1209
1210
1211QStringList QFileDialogPrivate::typedFiles()
const
1213 Q_Q(
const QFileDialog);
1215 QString editText = lineEdit()->text();
1216 if (!editText.contains(u'"')) {
1218 const QString prefix = q->directory().absolutePath() + QDir::separator();
1219 if (QFile::exists(prefix + editText))
1222 files << qt_tildeExpansion(editText);
1230 QStringList tokens = editText.split(u'\"');
1231 for (
int i=0; i<tokens.size(); ++i) {
1235 const QString token = tokens.at(i);
1236 const QString prefix = q->directory().absolutePath() + QDir::separator();
1237 if (QFile::exists(prefix + token))
1240 files << qt_tildeExpansion(token);
1242 files << toInternal(tokens.at(i));
1246 return addDefaultSuffixToFiles(files);
1252QList<QUrl> QFileDialogPrivate::userSelectedFiles()
const
1256 if (!usingWidgets())
1257 return addDefaultSuffixToUrls(selectedFiles_sys());
1259 const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
1260 files.reserve(selectedRows.size());
1261 for (
const QModelIndex &index : selectedRows)
1262 files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));
1264 if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
1265 const QStringList typedFilesList = typedFiles();
1266 files.reserve(typedFilesList.size());
1267 for (
const QString &path : typedFilesList)
1268 files.append(QUrl::fromLocalFile(path));
1274QStringList QFileDialogPrivate::addDefaultSuffixToFiles(
const QStringList &filesToFix)
const
1277 for (
int i=0; i<filesToFix.size(); ++i) {
1278 QString name = toInternal(filesToFix.at(i));
1279 QFileInfo info(name);
1281 const QString defaultSuffix = options->defaultSuffix();
1282 if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
1283 name += u'.' + defaultSuffix;
1285 if (info.isAbsolute()) {
1291 QString path = rootPath();
1292 if (!path.endsWith(u'/'))
1301QList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(
const QList<QUrl> &urlsToFix)
const
1304 urls.reserve(urlsToFix.size());
1306 const QString defaultSuffix = options->defaultSuffix();
1307 for (QUrl url : urlsToFix) {
1308 if (!defaultSuffix.isEmpty()) {
1309 const QString urlPath = url.path();
1310 const auto idx = urlPath.lastIndexOf(u'/');
1311 if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
1312 url.setPath(urlPath + u'.' + defaultSuffix);
1321
1322
1323
1324
1325
1326
1327QStringList QFileDialog::selectedFiles()
const
1329 Q_D(
const QFileDialog);
1332 const QList<QUrl> userSelectedFiles = d->userSelectedFiles();
1333 files.reserve(userSelectedFiles.size());
1334 for (
const QUrl &file : userSelectedFiles)
1335 files.append(file.toString(QUrl::PreferLocalFile));
1337 if (files.isEmpty() && d->usingWidgets()) {
1338 const FileMode fm = fileMode();
1339 if (fm != ExistingFile && fm != ExistingFiles)
1340 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1346
1347
1348
1349
1350
1351
1352
1353QList<QUrl> QFileDialog::selectedUrls()
const
1355 Q_D(
const QFileDialog);
1356 if (d->nativeDialogInUse) {
1357 return d->userSelectedFiles();
1360 const QStringList selectedFileList = selectedFiles();
1361 urls.reserve(selectedFileList.size());
1362 for (
const QString &file : selectedFileList)
1363 urls.append(QUrl::fromLocalFile(file));
1369
1370
1371
1374 if (filter.isEmpty())
1375 return QStringList();
1378 if (!filter.contains(sep) && filter.contains(u'\n'))
1381 return filter.split(sep);
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399void QFileDialog::setNameFilter(
const QString &filter)
1401 setNameFilters(qt_make_filter_list(filter));
1406
1407
1410#if QT_CONFIG(regularexpression)
1411 QStringList strippedFilters;
1412 static const QRegularExpression r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
1413 strippedFilters.reserve(filters.size());
1414 for (
const QString &filter : filters) {
1416 auto match = r.match(filter);
1417 if (match.hasMatch())
1418 filterName = match.captured(1);
1419 strippedFilters.append(filterName.simplified());
1421 return strippedFilters;
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445void QFileDialog::setNameFilters(
const QStringList &filters)
1448 QStringList cleanedFilters;
1449 cleanedFilters.reserve(filters.size());
1450 for (
const QString &filter : filters)
1451 cleanedFilters << filter.simplified();
1453 d->options->setNameFilters(cleanedFilters);
1455 if (!d->usingWidgets())
1458 d->qFileDialogUi->fileTypeCombo->clear();
1459 if (cleanedFilters.isEmpty())
1462 if (testOption(HideNameFilterDetails))
1463 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1465 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1467 d->useNameFilter(0);
1471
1472
1473
1474QStringList QFileDialog::nameFilters()
const
1476 return d_func()->options->nameFilters();
1480
1481
1482
1483
1484
1485void QFileDialog::selectNameFilter(
const QString &filter)
1488 d->options->setInitiallySelectedNameFilter(filter);
1489 if (!d->usingWidgets()) {
1490 d->selectNameFilter_sys(filter);
1494 if (testOption(HideNameFilterDetails)) {
1495 const QStringList filters = qt_strip_filters(qt_make_filter_list(filter));
1496 if (!filters.isEmpty())
1497 i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());
1499 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1502 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1503 d->useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1508
1509
1510
1511
1512QString QFileDialog::selectedNameFilter()
const
1514 Q_D(
const QFileDialog);
1515 if (!d->usingWidgets())
1516 return d->selectedNameFilter_sys();
1518 if (testOption(HideNameFilterDetails)) {
1519 const auto idx = d->qFileDialogUi->fileTypeCombo->currentIndex();
1520 if (idx >= 0 && idx < d->options->nameFilters().size())
1521 return d->options->nameFilters().at(d->qFileDialogUi->fileTypeCombo->currentIndex());
1523 return d->qFileDialogUi->fileTypeCombo->currentText();
1527
1528
1529
1530
1531QDir::Filters QFileDialog::filter()
const
1533 Q_D(
const QFileDialog);
1534 if (d->usingWidgets())
1535 return d->model->filter();
1536 return d->options->filter();
1540
1541
1542
1543
1544
1546void QFileDialog::setFilter(QDir::Filters filters)
1549 d->options->setFilter(filters);
1550 if (!d->usingWidgets()) {
1555 d->model->setFilter(filters);
1556 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1559#if QT_CONFIG(mimetype)
1561static QString nameFilterForMime(
const QString &mimeType)
1564 QMimeType mime(db.mimeTypeForName(mimeType));
1565 if (mime.isValid()) {
1566 if (mime.isDefault()) {
1567 return QFileDialog::tr(
"All files (*)");
1569 const QString patterns = mime.globPatterns().join(u' ');
1570 return mime.comment() +
" ("_L1 + patterns + u')';
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593void QFileDialog::setMimeTypeFilters(
const QStringList &filters)
1596 QStringList nameFilters;
1597 for (
const QString &mimeType : filters) {
1598 const QString text = nameFilterForMime(mimeType);
1599 if (!text.isEmpty())
1600 nameFilters.append(text);
1602 setNameFilters(nameFilters);
1603 d->options->setMimeTypeFilters(filters);
1607
1608
1609
1610
1611
1612QStringList QFileDialog::mimeTypeFilters()
const
1614 return d_func()->options->mimeTypeFilters();
1618
1619
1620
1621
1622
1623void QFileDialog::selectMimeTypeFilter(
const QString &filter)
1626 d->options->setInitiallySelectedMimeTypeFilter(filter);
1628 const QString filterForMime = nameFilterForMime(filter);
1630 if (!d->usingWidgets()) {
1631 d->selectMimeTypeFilter_sys(filter);
1632 if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
1633 selectNameFilter(filterForMime);
1635 }
else if (!filterForMime.isEmpty()) {
1636 selectNameFilter(filterForMime);
1643
1644
1645
1646QString QFileDialog::selectedMimeTypeFilter()
const
1648 Q_D(
const QFileDialog);
1649 QString mimeTypeFilter;
1650 if (!d->usingWidgets())
1651 mimeTypeFilter = d->selectedMimeTypeFilter_sys();
1653#if QT_CONFIG(mimetype)
1654 if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
1655 const auto nameFilter = selectedNameFilter();
1656 const auto mimeTypes = d->options->mimeTypeFilters();
1657 for (
const auto &mimeType: mimeTypes) {
1658 QString filter = nameFilterForMime(mimeType);
1659 if (testOption(HideNameFilterDetails))
1660 filter = qt_strip_filters({ filter }).constFirst();
1661 if (filter == nameFilter) {
1662 mimeTypeFilter = mimeType;
1669 return mimeTypeFilter;
1673
1674
1675
1676
1677
1678
1679
1680
1681void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
1684 d->options->setViewMode(
static_cast<QFileDialogOptions::ViewMode>(mode));
1685 if (!d->usingWidgets())
1688 d->showDetailsView();
1693QFileDialog::ViewMode QFileDialog::viewMode()
const
1695 Q_D(
const QFileDialog);
1696 if (!d->usingWidgets())
1697 return static_cast<QFileDialog::ViewMode>(d->options->viewMode());
1698 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716void QFileDialog::setFileMode(QFileDialog::FileMode mode)
1719 d->options->setFileMode(
static_cast<QFileDialogOptions::FileMode>(mode));
1720 if (!d->usingWidgets())
1723 d->retranslateWindowTitle();
1726 QAbstractItemView::SelectionMode selectionMode;
1727 if (mode == QFileDialog::ExistingFiles)
1728 selectionMode = QAbstractItemView::ExtendedSelection;
1730 selectionMode = QAbstractItemView::SingleSelection;
1731 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1732 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1734 d->model->setFilter(d->filterForMode(filter()));
1736 if (mode == Directory) {
1737 d->qFileDialogUi->fileTypeCombo->clear();
1738 d->qFileDialogUi->fileTypeCombo->addItem(tr(
"Directories"));
1739 d->qFileDialogUi->fileTypeCombo->setEnabled(
false);
1741 d->updateFileNameLabel();
1742 d->updateOkButtonText();
1743 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1744 d->updateOkButton();
1747QFileDialog::FileMode QFileDialog::fileMode()
const
1749 Q_D(
const QFileDialog);
1750 return static_cast<FileMode>(d->options->fileMode());
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
1766 d->options->setAcceptMode(
static_cast<QFileDialogOptions::AcceptMode>(mode));
1768 setAttribute(Qt::WA_DontShowOnScreen,
false);
1769 if (!d->usingWidgets())
1771 QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
1772 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1773 d->qFileDialogUi->buttonBox->button(button)->setEnabled(
false);
1774 d->updateOkButton();
1775 if (mode == AcceptSave) {
1776 d->qFileDialogUi->lookInCombo->setEditable(
false);
1778 d->retranslateWindowTitle();
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1794void QFileDialog::setSupportedSchemes(
const QStringList &schemes)
1797 d->options->setSupportedSchemes(schemes);
1800QStringList QFileDialog::supportedSchemes()
const
1802 return d_func()->options->supportedSchemes();
1806
1807
1808
1809QModelIndex QFileDialogPrivate::rootIndex()
const {
1810 return mapToSource(qFileDialogUi->listView->rootIndex());
1813QAbstractItemView *QFileDialogPrivate::currentView()
const {
1814 if (!qFileDialogUi->stackedWidget)
1816 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1817 return qFileDialogUi->listView;
1818 return qFileDialogUi->treeView;
1821QLineEdit *QFileDialogPrivate::lineEdit()
const {
1822 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1825long QFileDialogPrivate::maxNameLength(
const QString &path)
1827#if defined(Q_OS_UNIX)
1828 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1829#elif defined(Q_OS_WIN)
1831 const QString drive = path.left(3);
1832 if (::GetVolumeInformation(
reinterpret_cast<
const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) ==
false)
1842
1843
1844void QFileDialogPrivate::setRootIndex(
const QModelIndex &index)
const {
1845 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1846 QModelIndex idx = mapFromSource(index);
1847 qFileDialogUi->treeView->setRootIndex(idx);
1848 qFileDialogUi->listView->setRootIndex(idx);
1851
1852
1853
1854QModelIndex QFileDialogPrivate::select(
const QModelIndex &index)
const {
1855 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1857 QModelIndex idx = mapFromSource(index);
1858 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1859 qFileDialogUi->listView->selectionModel()->select(idx,
1860 QItemSelectionModel::Select | QItemSelectionModel::Rows);
1864QFileDialog::AcceptMode QFileDialog::acceptMode()
const
1866 Q_D(
const QFileDialog);
1867 return static_cast<AcceptMode>(d->options->acceptMode());
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881void QFileDialog::setDefaultSuffix(
const QString &suffix)
1884 d->options->setDefaultSuffix(suffix);
1887QString QFileDialog::defaultSuffix()
const
1889 Q_D(
const QFileDialog);
1890 return d->options->defaultSuffix();
1894
1895
1896
1897void QFileDialog::setHistory(
const QStringList &paths)
1900 if (d->usingWidgets())
1901 d->qFileDialogUi->lookInCombo->setHistory(paths);
1909 const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1911 const QUrl url = idx.isValid()
1912 ? QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()))
1916 urlModel->setUrls(list);
1920
1921
1922QStringList QFileDialog::history()
const
1924 Q_D(
const QFileDialog);
1925 if (!d->usingWidgets())
1926 return QStringList();
1927 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1929 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1930 if (!currentHistory.contains(newHistory))
1931 currentHistory << newHistory;
1932 return currentHistory;
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
1956 if (!d->usingWidgets())
1958 d->qFileDialogUi->listView->setItemDelegate(delegate);
1959 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1963
1964
1965QAbstractItemDelegate *QFileDialog::itemDelegate()
const
1967 Q_D(
const QFileDialog);
1968 if (!d->usingWidgets())
1970 return d->qFileDialogUi->listView->itemDelegate();
1974
1975
1976void QFileDialog::setIconProvider(QAbstractFileIconProvider *provider)
1979 if (!d->usingWidgets())
1981 d->model->setIconProvider(provider);
1983 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1987
1988
1989QAbstractFileIconProvider *QFileDialog::iconProvider()
const
1991 Q_D(
const QFileDialog);
1994 return d->model->iconProvider();
1997void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label,
const QString &text)
2002 case QFileDialog::LookIn:
2003 qFileDialogUi->lookInLabel->setText(text);
2005 case QFileDialog::FileName:
2006 qFileDialogUi->fileNameLabel->setText(text);
2008 case QFileDialog::FileType:
2009 qFileDialogUi->fileTypeLabel->setText(text);
2011 case QFileDialog::Accept:
2012 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
2013 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
2014 button->setText(text);
2016 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
2017 button->setText(text);
2020 case QFileDialog::Reject:
2021 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
2022 button->setText(text);
2028
2029
2031void QFileDialog::setLabelText(DialogLabel label,
const QString &text)
2034 d->options->setLabelText(
static_cast<QFileDialogOptions::DialogLabel>(label), text);
2035 d->setLabelTextControl(label, text);
2039
2040
2041QString QFileDialog::labelText(DialogLabel label)
const
2043 Q_D(
const QFileDialog);
2044 if (!d->usingWidgets())
2045 return d->options->labelText(
static_cast<QFileDialogOptions::DialogLabel>(label));
2046 QPushButton *button;
2049 return d->qFileDialogUi->lookInLabel->text();
2051 return d->qFileDialogUi->fileNameLabel->text();
2053 return d->qFileDialogUi->fileTypeLabel->text();
2055 if (acceptMode() == AcceptOpen)
2056 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
2058 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
2060 return button->text();
2063 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
2065 return button->text();
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113QString QFileDialog::getOpenFileName(QWidget *parent,
2114 const QString &caption,
2116 const QString &filter,
2117 QString *selectedFilter,
2120 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2121 const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2122 selectedFilter, options, schemes);
2123 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2124 return selectedUrl.toLocalFile();
2126 return selectedUrl.toString();
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
2157 const QString &caption,
2159 const QString &filter,
2160 QString *selectedFilter,
2162 const QStringList &supportedSchemes)
2164 QFileDialogArgs args(dir);
2165 args.parent = parent;
2166 args.caption = caption;
2167 args.filter = filter;
2168 args.mode = ExistingFile;
2169 args.options = options;
2171 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2172 dialog->setSupportedSchemes(supportedSchemes);
2173 if (selectedFilter && !selectedFilter->isEmpty())
2174 dialog->selectNameFilter(*selectedFilter);
2175 const int execResult = dialog->exec();
2176 if (
bool(dialog) && execResult == QDialog::Accepted) {
2178 *selectedFilter = dialog->selectedNameFilter();
2179 return dialog->selectedUrls().value(0);
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223QStringList QFileDialog::getOpenFileNames(QWidget *parent,
2224 const QString &caption,
2226 const QString &filter,
2227 QString *selectedFilter,
2230 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2231 const QList<QUrl> selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),
2232 filter, selectedFilter, options, schemes);
2233 QStringList fileNames;
2234 fileNames.reserve(selectedUrls.size());
2235 for (
const QUrl &url : selectedUrls)
2236 fileNames.append(url.toString(QUrl::PreferLocalFile));
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
2269 const QString &caption,
2271 const QString &filter,
2272 QString *selectedFilter,
2274 const QStringList &supportedSchemes)
2276 QFileDialogArgs args(dir);
2277 args.parent = parent;
2278 args.caption = caption;
2279 args.filter = filter;
2280 args.mode = ExistingFiles;
2281 args.options = options;
2283 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2284 dialog->setSupportedSchemes(supportedSchemes);
2285 if (selectedFilter && !selectedFilter->isEmpty())
2286 dialog->selectNameFilter(*selectedFilter);
2287 const int execResult = dialog->exec();
2288 if (
bool(dialog) && execResult == QDialog::Accepted) {
2290 *selectedFilter = dialog->selectedNameFilter();
2291 return dialog->selectedUrls();
2293 return QList<QUrl>();
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315void QFileDialog::getOpenFileContent(
const QString &nameFilter,
const std::function<
void(
const QString &,
const QByteArray &)> &fileOpenCompleted, QWidget *parent)
2319 auto openFileImpl = std::make_shared<std::function<
void(
void)>>();
2321 QByteArray fileContent;
2322 *openFileImpl = [=]()
mutable {
2323 auto fileDialogClosed = [&](
bool fileSelected) {
2324 if (!fileSelected) {
2325 fileOpenCompleted(fileName, fileContent);
2326 openFileImpl.reset();
2329 auto acceptFile = [&](uint64_t size,
const std::string name) ->
char * {
2330 const uint64_t twoGB = 1ULL << 31;
2334 fileName = QString::fromStdString(name);
2335 fileContent.resize(size);
2336 return fileContent.data();
2338 auto fileContentReady = [&]()
mutable {
2339 fileOpenCompleted(fileName, fileContent);
2340 openFileImpl.reset();
2343 QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
2348 QFileDialog *dialog =
new QFileDialog(parent);
2349 dialog->setFileMode(QFileDialog::ExistingFile);
2350 dialog->setNameFilter(nameFilter);
2351 dialog->setAttribute(Qt::WA_DeleteOnClose);
2353 auto fileSelected = [=](
const QString &fileName) {
2354 QByteArray fileContent;
2355 if (!fileName.isNull()) {
2356 QFile selectedFile(fileName);
2357 if (selectedFile.open(QIODevice::ReadOnly))
2358 fileContent = selectedFile.readAll();
2360 fileOpenCompleted(fileName, fileContent);
2363 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386void QFileDialog::saveFileContent(
const QByteArray &fileContent,
const QString &fileNameHint, QWidget *parent)
2390 QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
2392 QFileDialog *dialog =
new QFileDialog(parent);
2393 dialog->setAcceptMode(QFileDialog::AcceptSave);
2394 dialog->setFileMode(QFileDialog::AnyFile);
2395 dialog->selectFile(fileNameHint);
2397 auto fileSelected = [=](
const QString &fileName) {
2398 if (!fileName.isNull()) {
2399 QFile selectedFile(fileName);
2400 if (selectedFile.open(QIODevice::WriteOnly))
2401 selectedFile.write(fileContent);
2405 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2406 dialog->setAttribute(Qt::WA_DeleteOnClose);
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455QString QFileDialog::getSaveFileName(QWidget *parent,
2456 const QString &caption,
2458 const QString &filter,
2459 QString *selectedFilter,
2462 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2463 const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2464 selectedFilter, options, schemes);
2465 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2466 return selectedUrl.toLocalFile();
2468 return selectedUrl.toString();
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
2499 const QString &caption,
2501 const QString &filter,
2502 QString *selectedFilter,
2504 const QStringList &supportedSchemes)
2506 QFileDialogArgs args(dir);
2507 args.parent = parent;
2508 args.caption = caption;
2509 args.filter = filter;
2510 args.mode = AnyFile;
2511 args.options = options;
2513 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2514 dialog->setSupportedSchemes(supportedSchemes);
2515 dialog->setAcceptMode(AcceptSave);
2516 if (selectedFilter && !selectedFilter->isEmpty())
2517 dialog->selectNameFilter(*selectedFilter);
2518 const int execResult = dialog->exec();
2519 if (
bool(dialog) && execResult == QDialog::Accepted) {
2521 *selectedFilter = dialog->selectedNameFilter();
2522 return dialog->selectedUrls().value(0);
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567QString QFileDialog::getExistingDirectory(QWidget *parent,
2568 const QString &caption,
2572 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2573 const QUrl selectedUrl =
2574 getExistingDirectoryUrl(parent, caption, QUrl::fromLocalFile(dir), options, schemes);
2575 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2576 return selectedUrl.toLocalFile();
2578 return selectedUrl.toString();
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
2609 const QString &caption,
2612 const QStringList &supportedSchemes)
2614 QFileDialogArgs args(dir);
2615 args.parent = parent;
2616 args.caption = caption;
2617 args.mode = Directory;
2618 args.options = options;
2620 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2621 dialog->setSupportedSchemes(supportedSchemes);
2622 const int execResult = dialog->exec();
2623 if (
bool(dialog) && execResult == QDialog::Accepted)
2624 return dialog->selectedUrls().value(0);
2630 if (url.isLocalFile()) {
2631 QFileInfo info = local;
2632 if (!local.isAbsolute())
2633 info = QFileInfo(QDir::current(), url.toLocalFile());
2634 const QFileInfo pathInfo(info.absolutePath());
2635 if (!pathInfo.exists() || !pathInfo.isDir())
2637 if (info.exists() && info.isDir())
2638 return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));
2639 return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
2646#if QT_CONFIG(settings)
2647 if (lastVisitedDir()->isEmpty()) {
2648 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2649 const QString &lastVisisted = settings.value(
"FileDialog/lastVisited", QString()).toString();
2650 *lastVisitedDir() = QUrl::fromLocalFile(lastVisisted);
2656
2657
2661 const QFileInfo local(url.toLocalFile());
2664 directory = _qt_get_directory(url, local);
2665 if (directory.isEmpty()) {
2667 const QUrl lastVisited = *lastVisitedDir();
2668 if (lastVisited != url)
2669 directory = _qt_get_directory(lastVisited, QFileInfo());
2671 if (directory.isEmpty())
2672 directory = QUrl::fromLocalFile(QDir::currentPath());
2675
2676
2677
2678 if (selection.isEmpty() && !url.isEmpty()) {
2679 if (url.isLocalFile()) {
2681 selection = local.fileName();
2684 selection = url.fileName();
2690
2691
2692void QFileDialog::done(
int result)
2696 QDialog::done(result);
2698 if (d->receiverToDisconnectOnClose) {
2699 disconnect(
this, d->signalToDisconnectOnClose,
2700 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2701 d->receiverToDisconnectOnClose =
nullptr;
2703 d->memberToDisconnectOnClose.clear();
2704 d->signalToDisconnectOnClose.clear();
2707bool QFileDialogPrivate::itemAlreadyExists(
const QString &fileName)
2709#if QT_CONFIG(messagebox)
2711 const QString msg = QFileDialog::tr(
"%1 already exists.\nDo you want to replace it?").arg(fileName);
2712 using B = QMessageBox;
2713 const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
2714 return res == B::Yes;
2719void QFileDialogPrivate::itemNotFound(
const QString &fileName, QFileDialog::FileMode mode)
2721#if QT_CONFIG(messagebox)
2723 const QString message = mode == QFileDialog::Directory
2724 ? QFileDialog::tr(
"%1\nDirectory not found.\n"
2725 "Please verify the correct directory name was given.")
2726 : QFileDialog::tr(
"%1\nFile not found.\nPlease verify the "
2727 "correct file name was given.");
2729 QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
2734
2735
2736void QFileDialog::accept()
2739 if (!d->usingWidgets()) {
2740 const QList<QUrl> urls = selectedUrls();
2743 d->emitUrlsSelected(urls);
2744 if (urls.size() == 1)
2745 d->emitUrlSelected(urls.first());
2750 const QStringList files = selectedFiles();
2751 if (files.isEmpty())
2753 QString lineEditText = d->lineEdit()->text();
2756 if (lineEditText ==
".."_L1) {
2757 d->navigateToParent();
2758 const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
2759 d->lineEdit()->selectAll();
2763 const auto mode = fileMode();
2766 QString fn = files.first();
2769 info = QFileInfo(d->getEnvironmentVariable(fn));
2770 if (!info.exists()) {
2771 d->itemNotFound(info.fileName(), mode);
2775 d->emitFilesSelected(files);
2782 QString fn = files.first();
2785 setDirectory(info.absoluteFilePath());
2789 if (!info.exists()) {
2790 const long maxNameLength = d->maxNameLength(info.path());
2791 if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
2796 if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {
2797 d->emitFilesSelected(QStringList(fn));
2800 if (d->itemAlreadyExists(info.fileName())) {
2801 d->emitFilesSelected(QStringList(fn));
2810 for (
const auto &file : files) {
2811 QFileInfo info(file);
2813 info = QFileInfo(d->getEnvironmentVariable(file));
2814 if (!info.exists()) {
2815 d->itemNotFound(info.fileName(), mode);
2819 setDirectory(info.absoluteFilePath());
2820 d->lineEdit()->clear();
2824 d->emitFilesSelected(files);
2830#if QT_CONFIG(settings)
2831void QFileDialogPrivate::saveSettings()
2834 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2835 settings.beginGroup(
"FileDialog");
2837 if (usingWidgets()) {
2838 settings.setValue(
"sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
2839 settings.setValue(
"shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
2840 settings.setValue(
"treeViewHeader", qFileDialogUi->treeView->header()->saveState());
2842 QStringList historyUrls;
2843 const QStringList history = q->history();
2844 historyUrls.reserve(history.size());
2845 for (
const QString &path : history)
2846 historyUrls << QUrl::fromLocalFile(path).toString();
2847 settings.setValue(
"history", historyUrls);
2848 settings.setValue(
"lastVisited", lastVisitedDir()->toString());
2849 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2850 settings.setValue(
"viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
2851 settings.setValue(
"qtVersion", QT_VERSION_STR
""_L1);
2854bool QFileDialogPrivate::restoreFromSettings()
2857 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2858 if (!settings.childGroups().contains(
"FileDialog"_L1))
2860 settings.beginGroup(
"FileDialog");
2862 q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value(
"lastVisited").toUrl() : *lastVisitedDir());
2864 QByteArray viewModeStr = settings.value(
"viewMode").toString().toLatin1();
2865 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2867 int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
2869 viewMode = QFileDialog::List;
2870 q->setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
2872 sidebarUrls = QUrl::fromStringList(settings.value(
"shortcuts").toStringList());
2873 headerData = settings.value(
"treeViewHeader").toByteArray();
2875 if (!usingWidgets())
2878 QStringList history;
2879 const auto urlStrings = settings.value(
"history").toStringList();
2880 for (
const QString &urlStr : urlStrings) {
2882 if (url.isLocalFile())
2883 history << url.toLocalFile();
2886 return restoreWidgetState(history, settings.value(
"sidebarWidth", -1).toInt());
2890bool QFileDialogPrivate::restoreWidgetState(QStringList &history,
int splitterPosition)
2893 if (splitterPosition >= 0) {
2894 QList<
int> splitterSizes;
2895 splitterSizes.append(splitterPosition);
2896 splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
2897 qFileDialogUi->splitter->setSizes(splitterSizes);
2899 if (!qFileDialogUi->splitter->restoreState(splitterState))
2901 QList<
int> list = qFileDialogUi->splitter->sizes();
2902 if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
2903 for (
int i = 0; i < list.size(); ++i)
2904 list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
2905 qFileDialogUi->splitter->setSizes(list);
2909 qFileDialogUi->sidebar->setUrls(sidebarUrls);
2911 static const int MaxHistorySize = 5;
2912 if (history.size() > MaxHistorySize)
2913 history.erase(history.begin(), history.end() - MaxHistorySize);
2914 q->setHistory(history);
2916 QHeaderView *headerView = qFileDialogUi->treeView->header();
2917 if (!headerView->restoreState(headerData))
2920 QList<QAction*> actions = headerView->actions();
2921 QAbstractItemModel *abstractModel = model;
2922#if QT_CONFIG(proxymodel)
2924 abstractModel = proxyModel;
2926 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
2927 for (
int i = 1; i < total; ++i)
2928 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
2934
2935
2936
2937
2938void QFileDialogPrivate::init(
const QFileDialogArgs &args)
2941 if (!args.caption.isEmpty()) {
2942 useDefaultCaption =
false;
2943 setWindowTitle = args.caption;
2944 q->setWindowTitle(args.caption);
2947 q->setAcceptMode(QFileDialog::AcceptOpen);
2948 nativeDialogInUse = platformFileDialogHelper() !=
nullptr;
2949 if (!nativeDialogInUse)
2951 q->setFileMode(QFileDialog::AnyFile);
2952 if (!args.filter.isEmpty())
2953 q->setNameFilter(args.filter);
2954 q->setDirectoryUrl(args.directory);
2955 if (args.directory.isLocalFile())
2956 q->selectFile(args.selection);
2958 q->selectUrl(args.directory);
2960#if QT_CONFIG(settings)
2963 if (!restoreFromSettings()) {
2964 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
2965 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
2969#if defined(Q_EMBEDDED_SMALLSCREEN)
2970 qFileDialogUi->lookInLabel->setVisible(
false);
2971 qFileDialogUi->fileNameLabel->setVisible(
false);
2972 qFileDialogUi->fileTypeLabel->setVisible(
false);
2973 qFileDialogUi->sidebar->hide();
2976 const QSize sizeHint = q->sizeHint();
2977 if (sizeHint.isValid())
2978 q->resize(sizeHint);
2982
2983
2984
2985
2986void QFileDialogPrivate::createWidgets()
2995 QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
2996 Qt::WindowStates preState = q->windowState();
2998 model =
new QFileSystemModel(q);
2999 model->setIconProvider(&defaultIconProvider);
3000 model->setFilter(options->filter());
3001 model->setObjectName(
"qt_filesystem_model"_L1);
3002 if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
3003 model->setNameFilterDisables(helper->defaultNameFilterDisables());
3005 model->setNameFilterDisables(
false);
3006 model->d_func()->disableRecursiveSort =
true;
3007 QObjectPrivate::connect(model, &QFileSystemModel::fileRenamed,
3008 this, &QFileDialogPrivate::fileRenamed);
3009 QObjectPrivate::connect(model, &QFileSystemModel::rootPathChanged,
3010 this, &QFileDialogPrivate::pathChanged);
3011 QObjectPrivate::connect(model, &QFileSystemModel::rowsInserted,
3012 this, &QFileDialogPrivate::rowsInserted);
3013 model->setReadOnly(
false);
3015 qFileDialogUi.reset(
new Ui_QFileDialog());
3016 qFileDialogUi->setupUi(q);
3018 QList<QUrl> initialBookmarks;
3019 initialBookmarks << QUrl(
"file:"_L1)
3020 << QUrl::fromLocalFile(QDir::homePath());
3021 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
3022 QObjectPrivate::connect(qFileDialogUi->sidebar, &QSidebar::goToUrl,
3023 this, &QFileDialogPrivate::goToUrl);
3025 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::accepted,
3026 q, &QFileDialog::accept);
3027 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::rejected,
3028 q, &QFileDialog::reject);
3030 qFileDialogUi->lookInCombo->setFileDialogPrivate(
this);
3031 QObjectPrivate::connect(qFileDialogUi->lookInCombo, &QComboBox::textActivated,
3032 this, &QFileDialogPrivate::goToDirectory);
3034 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
3035 qFileDialogUi->lookInCombo->setDuplicatesEnabled(
false);
3038#ifndef QT_NO_SHORTCUT
3039 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
3041#if QT_CONFIG(fscompleter)
3042 completer =
new QFSCompleter(model, q);
3043 qFileDialogUi->fileNameEdit->setCompleter(completer);
3046 qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
3048 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3049 this, &QFileDialogPrivate::autoCompleteFileName);
3050 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3051 this, &QFileDialogPrivate::updateOkButton);
3052 QObject::connect(qFileDialogUi->fileNameEdit, &QLineEdit::returnPressed,
3053 q, &QFileDialog::accept);
3056 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(
false);
3057 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
3058 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
3059 QObjectPrivate::connect(qFileDialogUi->fileTypeCombo, &QComboBox::activated,
3060 this, &QFileDialogPrivate::useNameFilter);
3061 QObject::connect(qFileDialogUi->fileTypeCombo, &QComboBox::textActivated,
3062 q, &QFileDialog::filterSelected);
3064 qFileDialogUi->listView->setFileDialogPrivate(
this);
3065 qFileDialogUi->listView->setModel(model);
3066 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::activated,
3067 this, &QFileDialogPrivate::enterDirectory);
3068 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::customContextMenuRequested,
3069 this, &QFileDialogPrivate::showContextMenu);
3070#ifndef QT_NO_SHORTCUT
3071 QShortcut *shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);
3072 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3073 this, &QFileDialogPrivate::deleteCurrent);
3076 qFileDialogUi->treeView->setFileDialogPrivate(
this);
3077 qFileDialogUi->treeView->setModel(model);
3078 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
3079 QFontMetrics fm(q->font());
3080 treeHeader->resizeSection(0, fm.horizontalAdvance(
"wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
3081 treeHeader->resizeSection(1, fm.horizontalAdvance(
"128.88 GB"_L1));
3082 treeHeader->resizeSection(2, fm.horizontalAdvance(
"mp3Folder"_L1));
3083 treeHeader->resizeSection(3, fm.horizontalAdvance(
"10/29/81 02:02PM"_L1));
3084 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
3086 QActionGroup *showActionGroup =
new QActionGroup(q);
3087 showActionGroup->setExclusive(
false);
3088 QObjectPrivate::connect(showActionGroup, &QActionGroup::triggered,
3089 this, &QFileDialogPrivate::showHeader);
3091 QAbstractItemModel *abstractModel = model;
3092#if QT_CONFIG(proxymodel)
3094 abstractModel = proxyModel;
3096 for (
int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
3097 QAction *showHeader =
new QAction(showActionGroup);
3098 showHeader->setCheckable(
true);
3099 showHeader->setChecked(
true);
3100 treeHeader->addAction(showHeader);
3103 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
3104 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
3106 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::activated,
3107 this, &QFileDialogPrivate::enterDirectory);
3108 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::customContextMenuRequested,
3109 this, &QFileDialogPrivate::showContextMenu);
3110#ifndef QT_NO_SHORTCUT
3111 shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);
3112 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3113 this, &QFileDialogPrivate::deleteCurrent);
3117 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
3118 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3119 this, &QFileDialogPrivate::selectionChanged);
3120 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3121 this, &QFileDialogPrivate::currentChanged);
3122 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
3124 createToolButtons();
3125 createMenuActions();
3127#if QT_CONFIG(settings)
3130 if (!restoreFromSettings()) {
3131 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
3132 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
3137 q->setFileMode(
static_cast<QFileDialog::FileMode>(options->fileMode()));
3138 q->setAcceptMode(
static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
3139 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
3140 q->setOptions(
static_cast<QFileDialog::Options>(
static_cast<
int>(options->options())));
3141 if (!options->sidebarUrls().isEmpty())
3142 q->setSidebarUrls(options->sidebarUrls());
3143 q->setDirectoryUrl(options->initialDirectory());
3144#if QT_CONFIG(mimetype)
3145 if (!options->mimeTypeFilters().isEmpty())
3146 q->setMimeTypeFilters(options->mimeTypeFilters());
3149 if (!options->nameFilters().isEmpty())
3150 q->setNameFilters(options->nameFilters());
3151 q->selectNameFilter(options->initiallySelectedNameFilter());
3152 q->setDefaultSuffix(options->defaultSuffix());
3153 q->setHistory(options->history());
3154 const auto initiallySelectedFiles = options->initiallySelectedFiles();
3155 if (initiallySelectedFiles.size() == 1)
3156 q->selectFile(initiallySelectedFiles.first().fileName());
3157 for (
const QUrl &url : initiallySelectedFiles)
3159 lineEdit()->selectAll();
3161 retranslateStrings();
3162 q->resize(preSize.isValid() ? preSize : q->sizeHint());
3163 q->setWindowState(preState);
3166void QFileDialogPrivate::showHeader(QAction *action)
3169 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
3170 qFileDialogUi->treeView->header()->setSectionHidden(
int(actionGroup->actions().indexOf(action) + 1),
3171 !action->isChecked());
3174#if QT_CONFIG(proxymodel)
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
3188 if (!d->usingWidgets())
3190 if ((!proxyModel && !d->proxyModel)
3191 || (proxyModel == d->proxyModel))
3194 QModelIndex idx = d->rootIndex();
3196 QObjectPrivate::disconnect(d->proxyModel, &QAbstractProxyModel::rowsInserted,
3197 d, &QFileDialogPrivate::rowsInserted);
3199 QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsInserted,
3200 d, &QFileDialogPrivate::rowsInserted);
3202 if (proxyModel !=
nullptr) {
3203 proxyModel->setParent(
this);
3204 d->proxyModel = proxyModel;
3205 proxyModel->setSourceModel(d->model);
3206 d->qFileDialogUi->listView->setModel(d->proxyModel);
3207 d->qFileDialogUi->treeView->setModel(d->proxyModel);
3208#if QT_CONFIG(fscompleter)
3209 d->completer->setModel(d->proxyModel);
3210 d->completer->proxyModel = d->proxyModel;
3212 QObjectPrivate::connect(d->proxyModel, &QAbstractItemModel::rowsInserted,
3213 d, &QFileDialogPrivate::rowsInserted);
3215 d->proxyModel =
nullptr;
3216 d->qFileDialogUi->listView->setModel(d->model);
3217 d->qFileDialogUi->treeView->setModel(d->model);
3218#if QT_CONFIG(fscompleter)
3219 d->completer->setModel(d->model);
3220 d->completer->sourceModel = d->model;
3221 d->completer->proxyModel =
nullptr;
3223 QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted,
3224 d, &QFileDialogPrivate::rowsInserted);
3226 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
3227 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
3229 d->setRootIndex(idx);
3232 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
3233 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3234 d, &QFileDialogPrivate::selectionChanged);
3235 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3236 d, &QFileDialogPrivate::currentChanged);
3240
3241
3242
3243
3244QAbstractProxyModel *QFileDialog::proxyModel()
const
3246 Q_D(
const QFileDialog);
3247 return d->proxyModel;
3252
3253
3254
3255
3256void QFileDialogPrivate::createToolButtons()
3259 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack,
nullptr, q));
3260 qFileDialogUi->backButton->setAutoRaise(
true);
3261 qFileDialogUi->backButton->setEnabled(
false);
3262 QObjectPrivate::connect(qFileDialogUi->backButton, &QPushButton::clicked,
3263 this, &QFileDialogPrivate::navigateBackward);
3265 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward,
nullptr, q));
3266 qFileDialogUi->forwardButton->setAutoRaise(
true);
3267 qFileDialogUi->forwardButton->setEnabled(
false);
3268 QObjectPrivate::connect(qFileDialogUi->forwardButton, &QPushButton::clicked,
3269 this, &QFileDialogPrivate::navigateForward);
3271 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent,
nullptr, q));
3272 qFileDialogUi->toParentButton->setAutoRaise(
true);
3273 qFileDialogUi->toParentButton->setEnabled(
false);
3274 QObjectPrivate::connect(qFileDialogUi->toParentButton, &QPushButton::clicked,
3275 this, &QFileDialogPrivate::navigateToParent);
3277 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView,
nullptr, q));
3278 qFileDialogUi->listModeButton->setAutoRaise(
true);
3279 qFileDialogUi->listModeButton->setDown(
true);
3280 QObjectPrivate::connect(qFileDialogUi->listModeButton, &QPushButton::clicked,
3281 this, &QFileDialogPrivate::showListView);
3283 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView,
nullptr, q));
3284 qFileDialogUi->detailModeButton->setAutoRaise(
true);
3285 QObjectPrivate::connect(qFileDialogUi->detailModeButton, &QPushButton::clicked,
3286 this, &QFileDialogPrivate::showDetailsView);
3288 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
3289 qFileDialogUi->backButton->setFixedSize(toolSize);
3290 qFileDialogUi->listModeButton->setFixedSize(toolSize);
3291 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
3292 qFileDialogUi->forwardButton->setFixedSize(toolSize);
3293 qFileDialogUi->toParentButton->setFixedSize(toolSize);
3295 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder,
nullptr, q));
3296 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
3297 qFileDialogUi->newFolderButton->setAutoRaise(
true);
3298 qFileDialogUi->newFolderButton->setEnabled(
false);
3299 QObjectPrivate::connect(qFileDialogUi->newFolderButton, &QPushButton::clicked,
3300 this, &QFileDialogPrivate::createDirectory);
3304
3305
3306
3307
3308void QFileDialogPrivate::createMenuActions()
3312 QAction *goHomeAction =
new QAction(q);
3313#ifndef QT_NO_SHORTCUT
3314 goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
3316 QObjectPrivate::connect(goHomeAction, &QAction::triggered,
3317 this, &QFileDialogPrivate::goHome);
3318 q->addAction(goHomeAction);
3322 QAction *goToParent =
new QAction(q);
3323 goToParent->setObjectName(
"qt_goto_parent_action"_L1);
3324#ifndef QT_NO_SHORTCUT
3325 goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
3327 QObjectPrivate::connect(goToParent, &QAction::triggered,
3328 this, &QFileDialogPrivate::navigateToParent);
3329 q->addAction(goToParent);
3331 renameAction =
new QAction(q);
3332 renameAction->setEnabled(
false);
3333 renameAction->setObjectName(
"qt_rename_action"_L1);
3334 QObjectPrivate::connect(renameAction, &QAction::triggered,
3335 this, &QFileDialogPrivate::renameCurrent);
3337 deleteAction =
new QAction(q);
3338 deleteAction->setEnabled(
false);
3339 deleteAction->setObjectName(
"qt_delete_action"_L1);
3340 QObjectPrivate::connect(deleteAction, &QAction::triggered,
3341 this, &QFileDialogPrivate::deleteCurrent);
3343 showHiddenAction =
new QAction(q);
3344 showHiddenAction->setObjectName(
"qt_show_hidden_action"_L1);
3345 showHiddenAction->setCheckable(
true);
3346 QObjectPrivate::connect(showHiddenAction, &QAction::triggered,
3347 this, &QFileDialogPrivate::showHidden);
3349 newFolderAction =
new QAction(q);
3350 newFolderAction->setObjectName(
"qt_new_folder_action"_L1);
3351 QObjectPrivate::connect(newFolderAction, &QAction::triggered,
3352 this, &QFileDialogPrivate::createDirectory);
3355void QFileDialogPrivate::goHome()
3358 q->setDirectory(QDir::homePath());
3362void QFileDialogPrivate::saveHistorySelection()
3364 if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
3366 auto &item = currentHistory[currentHistoryLocation];
3367 item.selection.clear();
3368 const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3369 for (
const auto &index : selectedIndexes)
3370 item.selection.append(QPersistentModelIndex(index));
3374
3375
3376
3377
3378void QFileDialogPrivate::pathChanged(
const QString &newPath)
3381 qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
3382 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
3383 q->setHistory(qFileDialogUi->lookInCombo->history());
3385 const QString newNativePath = QDir::toNativeSeparators(newPath);
3388 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
3389 if (currentHistoryLocation >= 0)
3390 saveHistorySelection();
3391 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
3392 currentHistory.removeLast();
3394 currentHistory.append({newNativePath, PersistentModelIndexList()});
3395 ++currentHistoryLocation;
3397 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
3398 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
3401void QFileDialogPrivate::navigate(HistoryItem &historyItem)
3404 q->setDirectory(historyItem.path);
3406 if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
3408 if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
3409 [](
const QPersistentModelIndex &i) {
return !i.isValid(); })) {
3410 historyItem.selection.clear();
3414 QAbstractItemView *view = q->viewMode() == QFileDialog::List
3415 ?
static_cast<QAbstractItemView *>(qFileDialogUi->listView)
3416 :
static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
3417 auto selectionModel = view->selectionModel();
3418 const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
3419 | QItemSelectionModel::Rows;
3420 selectionModel->select(historyItem.selection.constFirst(),
3421 flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);
3422 auto it = historyItem.selection.cbegin() + 1;
3423 const auto end = historyItem.selection.cend();
3424 for (; it != end; ++it)
3425 selectionModel->select(*it, flags);
3427 view->scrollTo(historyItem.selection.constFirst());
3431
3432
3433
3434
3435void QFileDialogPrivate::navigateBackward()
3437 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
3438 saveHistorySelection();
3439 navigate(currentHistory[--currentHistoryLocation]);
3444
3445
3446
3447
3448void QFileDialogPrivate::navigateForward()
3450 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
3451 saveHistorySelection();
3452 navigate(currentHistory[++currentHistoryLocation]);
3457
3458
3459
3460
3461
3462void QFileDialogPrivate::navigateToParent()
3465 QDir dir(model->rootDirectory());
3466 QString newDirectory;
3468 newDirectory = model->myComputer().toString();
3471 newDirectory = dir.absolutePath();
3473 q->setDirectory(newDirectory);
3474 emit q->directoryEntered(newDirectory);
3478
3479
3480
3481
3482void QFileDialogPrivate::createDirectory()
3485 qFileDialogUi->listView->clearSelection();
3487 QString newFolderString = QFileDialog::tr(
"New Folder");
3488 QString folderName = newFolderString;
3489 QString prefix = q->directory().absolutePath() + QDir::separator();
3490 if (QFile::exists(prefix + folderName)) {
3491 qlonglong suffix = 2;
3492 while (QFile::exists(prefix + folderName)) {
3493 folderName = newFolderString + QString::number(suffix++);
3497 QModelIndex parent = rootIndex();
3498 QModelIndex index = model->mkdir(parent, folderName);
3499 if (!index.isValid())
3502 index = select(index);
3503 if (index.isValid()) {
3504 qFileDialogUi->treeView->setCurrentIndex(index);
3505 currentView()->edit(index);
3509void QFileDialogPrivate::showListView()
3511 qFileDialogUi->listModeButton->setDown(
true);
3512 qFileDialogUi->detailModeButton->setDown(
false);
3513 qFileDialogUi->treeView->hide();
3514 qFileDialogUi->listView->show();
3515 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
3516 qFileDialogUi->listView->doItemsLayout();
3519void QFileDialogPrivate::showDetailsView()
3521 qFileDialogUi->listModeButton->setDown(
false);
3522 qFileDialogUi->detailModeButton->setDown(
true);
3523 qFileDialogUi->listView->hide();
3524 qFileDialogUi->treeView->show();
3525 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
3526 qFileDialogUi->treeView->doItemsLayout();
3530
3531
3532
3533
3534void QFileDialogPrivate::showContextMenu(
const QPoint &position)
3540 QAbstractItemView *view =
nullptr;
3541 if (q->viewMode() == QFileDialog::Detail)
3542 view = qFileDialogUi->treeView;
3544 view = qFileDialogUi->listView;
3545 QModelIndex index = view->indexAt(position);
3546 index = mapToSource(index.sibling(index.row(), 0));
3548 QMenu *menu =
new QMenu(view);
3549 menu->setAttribute(Qt::WA_DeleteOnClose);
3551 if (index.isValid()) {
3553 const bool ro = model && model->isReadOnly();
3554 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3555 renameAction->setEnabled(!ro && p & QFile::WriteUser);
3556 menu->addAction(renameAction);
3557 deleteAction->setEnabled(!ro && p & QFile::WriteUser);
3558 menu->addAction(deleteAction);
3559 menu->addSeparator();
3561 menu->addAction(showHiddenAction);
3562 if (qFileDialogUi->newFolderButton->isVisible()) {
3563 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
3564 menu->addAction(newFolderAction);
3566 menu->popup(view->viewport()->mapToGlobal(position));
3572
3573
3574void QFileDialogPrivate::renameCurrent()
3577 QModelIndex index = qFileDialogUi->listView->currentIndex();
3578 index = index.sibling(index.row(), 0);
3579 if (q->viewMode() == QFileDialog::List)
3580 qFileDialogUi->listView->edit(index);
3582 qFileDialogUi->treeView->edit(index);
3585bool QFileDialogPrivate::removeDirectory(
const QString &path)
3587 QModelIndex modelIndex = model->index(path);
3588 return model->remove(modelIndex);
3592
3593
3594
3595
3596void QFileDialogPrivate::deleteCurrent()
3598 if (model->isReadOnly())
3601 const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
3602 for (
auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
3603 QPersistentModelIndex index = *it;
3604 if (index == qFileDialogUi->listView->rootIndex())
3607 index = mapToSource(index.sibling(index.row(), 0));
3608 if (!index.isValid())
3611 QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
3612 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
3614 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3615#if QT_CONFIG(messagebox)
3617 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3618 QFileDialog::tr(
"'%1' is write protected.\nDo you want to delete it anyway?")
3620 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
3622 else if (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3623 QFileDialog::tr(
"Are you sure you want to delete '%1'?")
3625 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
3629 if (!index.isValid())
3633 if (!(p & QFile::WriteUser))
3637 if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
3638 if (!removeDirectory(filePath)) {
3639#if QT_CONFIG(messagebox)
3640 QMessageBox::warning(q, q->windowTitle(),
3641 QFileDialog::tr(
"Could not delete directory."));
3645 model->remove(index);
3650void QFileDialogPrivate::autoCompleteFileName(
const QString &text)
3652 if (text.startsWith(
"//"_L1) || text.startsWith(u'\\')) {
3653 qFileDialogUi->listView->selectionModel()->clearSelection();
3657 const QStringList multipleFiles = typedFiles();
3658 if (multipleFiles.size() > 0) {
3659 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
3660 QList<QModelIndex> newFiles;
3661 for (
const auto &file : multipleFiles) {
3662 QModelIndex idx = model->index(file);
3663 if (oldFiles.removeAll(idx) == 0)
3664 newFiles.append(idx);
3666 for (
const auto &newFile : std::as_const(newFiles))
3668 if (lineEdit()->hasFocus()) {
3669 auto *sm = qFileDialogUi->listView->selectionModel();
3670 for (
const auto &oldFile : std::as_const(oldFiles))
3671 sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
3677
3678
3679void QFileDialogPrivate::updateOkButton()
3682 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
3683 ? QDialogButtonBox::Open : QDialogButtonBox::Save);
3686 const QFileDialog::FileMode fileMode = q->fileMode();
3688 bool enableButton =
true;
3689 bool isOpenDirectory =
false;
3691 const QStringList files = q->selectedFiles();
3692 QString lineEditText = lineEdit()->text();
3694 if (lineEditText.startsWith(
"//"_L1) || lineEditText.startsWith(u'\\')) {
3695 button->setEnabled(
true);
3696 updateOkButtonText();
3700 if (files.isEmpty()) {
3701 enableButton =
false;
3702 }
else if (lineEditText ==
".."_L1) {
3703 isOpenDirectory =
true;
3706 case QFileDialog::Directory: {
3707 QString fn = files.first();
3708 QModelIndex idx = model->index(fn);
3710 idx = model->index(getEnvironmentVariable(fn));
3711 if (!idx.isValid() || !model->isDir(idx))
3712 enableButton =
false;
3715 case QFileDialog::AnyFile: {
3716 QString fn = files.first();
3718 QModelIndex idx = model->index(fn);
3722 fileDir = info.canonicalFilePath();
3724 fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
3725 fileName = fn.mid(fileDir.size() + 1);
3727 if (lineEditText.contains(
".."_L1)) {
3728 fileDir = info.canonicalFilePath();
3729 fileName = info.fileName();
3732 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
3733 enableButton =
false;
3736 if (idx.isValid() && model->isDir(idx)) {
3737 isOpenDirectory =
true;
3738 enableButton =
true;
3741 if (!idx.isValid()) {
3742 const long maxLength = maxNameLength(fileDir);
3743 enableButton = maxLength < 0 || fileName.size() <= maxLength;
3747 case QFileDialog::ExistingFile:
3748 case QFileDialog::ExistingFiles:
3749 for (
const auto &file : files) {
3750 QModelIndex idx = model->index(file);
3752 idx = model->index(getEnvironmentVariable(file));
3753 if (!idx.isValid()) {
3754 enableButton =
false;
3757 if (idx.isValid() && model->isDir(idx)) {
3758 isOpenDirectory =
true;
3768 button->setEnabled(enableButton);
3769 updateOkButtonText(isOpenDirectory);
3773
3774
3775void QFileDialogPrivate::currentChanged(
const QModelIndex &index)
3778 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
3782
3783
3784
3785
3786
3787void QFileDialogPrivate::enterDirectory(
const QModelIndex &index)
3791 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
3792 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
3793 if (path.isEmpty() || model->isDir(sourceIndex)) {
3794 if (q->directory().path() == path)
3797 const QFileDialog::FileMode fileMode = q->fileMode();
3798 q->setDirectory(path);
3799 emit q->directoryEntered(path);
3800 if (fileMode == QFileDialog::Directory) {
3802 lineEdit()->setText(QString());
3803 lineEdit()->clear();
3807 if ((!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick,
nullptr, qFileDialogUi->treeView)
3808 || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL))
3809 && index.model()->flags(index) & Qt::ItemIsEnabled) {
3816
3817
3818
3819
3820
3821void QFileDialogPrivate::goToDirectory(
const QString &path)
3823 enum { UrlRole = Qt::UserRole + 1 };
3825 #if QT_CONFIG(messagebox)
3828 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
3829 qFileDialogUi->lookInCombo->modelColumn(),
3830 qFileDialogUi->lookInCombo->rootModelIndex());
3831 QString path2 = path;
3832 if (!index.isValid())
3833 index = mapFromSource(model->index(getEnvironmentVariable(path)));
3835 path2 = index.data(UrlRole).toUrl().toLocalFile();
3836 index = mapFromSource(model->index(path2));
3840 dir.setPath(getEnvironmentVariable(path2));
3842 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
3843 enterDirectory(index);
3844#if QT_CONFIG(messagebox)
3846 QString message = QFileDialog::tr(
"%1\nDirectory not found.\nPlease verify the "
3847 "correct directory name was given.");
3848 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
3854
3855
3856
3857
3858
3859void QFileDialogPrivate::useNameFilter(
int index)
3861 QStringList nameFilters = options->nameFilters();
3862 if (index == nameFilters.size()) {
3863 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3864 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3865 options->setNameFilters(nameFilters);
3868 QString nameFilter = nameFilters.at(index);
3869 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3870 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3871 QString newNameFilterExtension;
3872 if (newNameFilters.size() > 0)
3873 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3875 QString fileName = lineEdit()->text();
3876 const QString fileNameExtension = QFileInfo(fileName).suffix();
3877 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3878 const qsizetype fileNameExtensionLength = fileNameExtension.size();
3879 fileName.replace(fileName.size() - fileNameExtensionLength,
3880 fileNameExtensionLength, newNameFilterExtension);
3881 qFileDialogUi->listView->clearSelection();
3882 lineEdit()->setText(fileName);
3886 model->setNameFilters(newNameFilters);
3890
3891
3892
3893
3894
3895void QFileDialogPrivate::selectionChanged()
3897 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3898 const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3899 bool stripDirs = fileMode != QFileDialog::Directory;
3901 QStringList allFiles;
3902 for (
const auto &index : indexes) {
3903 if (stripDirs && model->isDir(mapToSource(index)))
3905 allFiles.append(index.data().toString());
3907 if (allFiles.size() > 1)
3908 for (qsizetype i = 0; i < allFiles.size(); ++i) {
3909 allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
3912 QString finalFiles = allFiles.join(u' ');
3913 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3914 lineEdit()->setText(finalFiles);
3920
3921
3922
3923
3924void QFileDialogPrivate::showHidden()
3927 QDir::Filters dirFilters = q->filter();
3928 dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
3929 q->setFilter(dirFilters);
3933
3934
3935
3936
3937
3938void QFileDialogPrivate::rowsInserted(
const QModelIndex &parent)
3940 if (!qFileDialogUi->treeView
3941 || parent != qFileDialogUi->treeView->rootIndex()
3942 || !qFileDialogUi->treeView->selectionModel()
3943 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3944 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3948void QFileDialogPrivate::fileRenamed(
const QString &path,
const QString &oldName,
const QString &newName)
3950 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3951 if (fileMode == QFileDialog::Directory) {
3952 if (path == rootPath() && lineEdit()->text() == oldName)
3953 lineEdit()->setText(newName);
3957void QFileDialogPrivate::emitUrlSelected(
const QUrl &file)
3960 emit q->urlSelected(file);
3961 if (file.isLocalFile())
3962 emit q->fileSelected(file.toLocalFile());
3965void QFileDialogPrivate::emitUrlsSelected(
const QList<QUrl> &files)
3968 emit q->urlsSelected(files);
3969 QStringList localFiles;
3970 for (
const QUrl &file : files)
3971 if (file.isLocalFile())
3972 localFiles.append(file.toLocalFile());
3973 if (!localFiles.isEmpty())
3974 emit q->filesSelected(localFiles);
3977void QFileDialogPrivate::nativeCurrentChanged(
const QUrl &file)
3980 emit q->currentUrlChanged(file);
3981 if (file.isLocalFile())
3982 emit q->currentChanged(file.toLocalFile());
3985void QFileDialogPrivate::nativeEnterDirectory(
const QUrl &directory)
3988 emit q->directoryUrlEntered(directory);
3989 if (!directory.isEmpty()) {
3990 *lastVisitedDir() = directory;
3991 if (directory.isLocalFile())
3992 emit q->directoryEntered(directory.toLocalFile());
3997
3998
3999
4000
4001
4002
4003bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
4005#if QT_CONFIG(shortcut)
4007 if (event->matches(QKeySequence::Cancel)) {
4012 switch (event->key()) {
4013 case Qt::Key_Backspace:
4018 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
4029QString QFileDialogPrivate::getEnvironmentVariable(
const QString &string)
4032 if (string.size() > 1 && string.startsWith(u'$')) {
4033 return qEnvironmentVariable(QStringView{string}.mid(1).toLatin1().constData());
4036 if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
4037 return qEnvironmentVariable(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData());
4045 urlModel =
new QUrlModel(
this);
4046 urlModel->showFullPath =
true;
4047 urlModel->setFileSystemModel(d_ptr->model);
4053 if (model()->rowCount() > 1)
4054 QComboBox::showPopup();
4056 urlModel->setUrls(QList<QUrl>());
4058 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
4059 while (idx.isValid()) {
4060 QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
4066 list.append(QUrl(
"file:"_L1));
4067 urlModel->addUrls(list, 0);
4068 idx = model()->index(model()->rowCount() - 1, 0);
4072 for (
int i = 0; i < m_history.size(); ++i) {
4073 QUrl path = QUrl::fromLocalFile(m_history.at(i));
4074 if (!urls.contains(path))
4077 if (urls.size() > 0) {
4078 model()->insertRow(model()->rowCount());
4079 idx = model()->index(model()->rowCount()-1, 0);
4081 model()->setData(idx, QFileDialog::tr(
"Recent Places"));
4082 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
4084 Qt::ItemFlags flags = m->flags(idx);
4085 flags &= ~Qt::ItemIsEnabled;
4086 m->item(idx.row(), idx.column())->setFlags(flags);
4088 urlModel->addUrls(urls, -1,
false);
4092 QComboBox::showPopup();
4098 QStylePainter painter(
this);
4099 painter.setPen(palette().color(QPalette::Text));
4102 QStyleOptionComboBox opt;
4103 initStyleOption(&opt);
4105 QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
4106 QStyle::SC_ComboBoxEditField,
this);
4107 int size = editRect.width() - opt.iconSize.width() - 4;
4108 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
4109 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
4112 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
4118 setSelectionBehavior(QAbstractItemView::SelectRows);
4120 setResizeMode(QListView::Adjust);
4121 setEditTriggers(QAbstractItemView::EditKeyPressed);
4122 setContextMenuPolicy(Qt::CustomContextMenu);
4123#if QT_CONFIG(draganddrop)
4124 setDragDropMode(QAbstractItemView::InternalMove);
4130 int height = qMax(10, sizeHintForRow(0));
4131 return QSize(QListView::sizeHint().width() * 2, height * 30);
4136 if (!d_ptr->itemViewKeyboardEvent(e))
4137 QListView::keyPressEvent(e);
4144 setSelectionBehavior(QAbstractItemView::SelectRows);
4145 setRootIsDecorated(
false);
4146 setItemsExpandable(
false);
4147 setSortingEnabled(
true);
4148 header()->setSortIndicator(0, Qt::AscendingOrder);
4149 header()->setStretchLastSection(
false);
4150 setTextElideMode(Qt::ElideMiddle);
4151 setEditTriggers(QAbstractItemView::EditKeyPressed);
4152 setContextMenuPolicy(Qt::CustomContextMenu);
4153#if QT_CONFIG(draganddrop)
4154 setDragDropMode(QAbstractItemView::InternalMove);
4160 if (!d_ptr->itemViewKeyboardEvent(e))
4161 QTreeView::keyPressEvent(e);
4167 int height = qMax(10, sizeHintForRow(0));
4168 QSize sizeHint = header()->sizeHint();
4169 return QSize(sizeHint.width() * 4, height * 30);
4173
4174
4175
4176
4179
4180
4181
4184#if QT_CONFIG(shortcut)
4187 QLineEdit::keyPressEvent(e);
4188#if QT_CONFIG(shortcut)
4189 if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
4194#if QT_CONFIG(fscompleter)
4196QString QFSCompleter::pathFromIndex(
const QModelIndex &index)
const
4198 const QFileSystemModel *dirModel;
4200 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4202 dirModel = sourceModel;
4203 QString currentLocation = dirModel->rootPath();
4204 QString path = index.data(QFileSystemModel::FilePathRole).toString();
4205 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
4206#if defined(Q_OS_UNIX)
4207 if (currentLocation == QDir::separator())
4208 return path.remove(0, currentLocation.size());
4210 if (currentLocation.endsWith(u'/'))
4211 return path.remove(0, currentLocation.size());
4213 return path.remove(0, currentLocation.size()+1);
4215 return index.data(QFileSystemModel::FilePathRole).toString();
4218QStringList QFSCompleter::splitPath(
const QString &path)
const
4221 return QStringList(completionPrefix());
4223 QString pathCopy = QDir::toNativeSeparators(path);
4224 QChar sep = QDir::separator();
4225#if defined(Q_OS_WIN)
4226 if (pathCopy ==
"\\"_L1 || pathCopy ==
"\\\\"_L1)
4227 return QStringList(pathCopy);
4228 QString doubleSlash(
"\\\\"_L1);
4229 if (pathCopy.startsWith(doubleSlash))
4230 pathCopy = pathCopy.mid(2);
4232 doubleSlash.clear();
4233#elif defined(Q_OS_UNIX)
4235 QString tildeExpanded = qt_tildeExpansion(pathCopy);
4236 if (tildeExpanded != pathCopy) {
4237 QFileSystemModel *dirModel;
4239 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
4241 dirModel = sourceModel;
4242 dirModel->fetchMore(dirModel->index(tildeExpanded));
4244 pathCopy = std::move(tildeExpanded);
4248#if defined(Q_OS_WIN)
4249 QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
4250 if (!doubleSlash.isEmpty() && !parts.isEmpty())
4251 parts[0].prepend(doubleSlash);
4252 if (pathCopy.endsWith(sep))
4253 parts.append(QString());
4255 QStringList parts = pathCopy.split(sep);
4256 if (pathCopy[0] == sep)
4260#if defined(Q_OS_WIN)
4261 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
4263 bool startsFromRoot = pathCopy[0] == sep;
4265 if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
4266 const QFileSystemModel *dirModel;
4268 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4270 dirModel = sourceModel;
4271 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
4272#if defined(Q_OS_WIN)
4273 if (currentLocation.endsWith(u':'))
4274 currentLocation.append(sep);
4276 if (currentLocation.contains(sep) && path != currentLocation) {
4277 QStringList currentLocationList = splitPath(currentLocation);
4278 while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) ==
".."_L1) {
4279 parts.removeFirst();
4280 currentLocationList.removeLast();
4282 if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
4283 currentLocationList.removeLast();
4284 return currentLocationList + parts;
4295#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={})