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
161
162
163
164
165
168
169
170
171
172
173
174
175
176
177
178
179
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
241
242
243
244
245
246
247
248
251
252
253
254
255
256
257
258
261
262
263
264
265
266
267
268
271
272
273
274
275
276
277
278
281
282
283
284
285
286
287
288
291
292
293
294
295
296
297
300
301
302
303
304
305
306
307
310
311
312
313
314
317
318
319
320
321
322
325
326
327
328
330QT_BEGIN_INCLUDE_NAMESPACE
332#if QT_CONFIG(shortcut)
333# include <qshortcut.h>
335QT_END_INCLUDE_NAMESPACE
338
339
340
341
342QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
343 : QDialog(*
new QFileDialogPrivate, parent, f)
346 QFileDialogArgs args;
351
352
353
354
355
356
357QFileDialog::QFileDialog(QWidget *parent,
358 const QString &caption,
359 const QString &directory,
360 const QString &filter)
361 : QDialog(*
new QFileDialogPrivate, parent, { })
364 QFileDialogArgs args(QUrl::fromLocalFile(directory));
365 args.filter = filter;
366 args.caption = caption;
371
372
373QFileDialog::QFileDialog(
const QFileDialogArgs &args)
374 : QDialog(*
new QFileDialogPrivate, args.parent, { })
378 setFileMode(args.mode);
379 setOptions(args.options);
380 selectFile(args.selection);
384
385
386QFileDialog::~QFileDialog()
389#if QT_CONFIG(settings)
392 if (QPlatformFileDialogHelper *platformHelper = d->platformFileDialogHelper()) {
395 QObjectPrivate::disconnect(platformHelper, &QPlatformFileDialogHelper::directoryEntered,
396 d, &QFileDialogPrivate::nativeEnterDirectory);
401
402
403
404
405
406
407
408
409
410
411
412
413void QFileDialog::setSidebarUrls(
const QList<QUrl> &urls)
416 if (!d->nativeDialogInUse)
417 d->qFileDialogUi->sidebar->setUrls(urls);
421
422
423QList<QUrl> QFileDialog::sidebarUrls()
const
425 Q_D(
const QFileDialog);
426 return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
429static const qint32 QFileDialogMagic = 0xbe;
432
433
434
435
436
437QByteArray QFileDialog::saveState()
const
439 Q_D(
const QFileDialog);
442 QDataStream stream(&data, QIODevice::WriteOnly);
443 stream.setVersion(QDataStream::Qt_5_0);
445 stream << qint32(QFileDialogMagic);
446 stream << qint32(version);
447 if (d->usingWidgets()) {
448 stream << d->qFileDialogUi->splitter->saveState();
449 stream << d->qFileDialogUi->sidebar->urls();
451 stream << d->splitterState;
452 stream << d->sidebarUrls;
455 stream << *lastVisitedDir();
456 if (d->usingWidgets())
457 stream << d->qFileDialogUi->treeView->header()->saveState();
459 stream << d->headerData;
460 stream << qint32(viewMode());
465
466
467
468
469
470
471
472bool QFileDialog::restoreState(
const QByteArray &state)
475 QByteArray sd = state;
476 QDataStream stream(&sd, QIODevice::ReadOnly);
477 stream.setVersion(QDataStream::Qt_5_0);
481 QUrl currentDirectory;
488 if (marker != QFileDialogMagic || (v != 3 && v != 4))
491 stream >> d->splitterState
495 QString currentDirectoryString;
496 stream >> currentDirectoryString;
497 currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
499 stream >> currentDirectory;
501 stream >> d->headerData
504 setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
505 setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
507 if (!d->usingWidgets())
510 return d->restoreWidgetState(history, -1);
514
515
516void QFileDialog::changeEvent(QEvent *e)
519 if (e->type() == QEvent::LanguageChange) {
520 d->retranslateWindowTitle();
521 d->retranslateStrings();
523 QDialog::changeEvent(e);
526QFileDialogPrivate::QFileDialogPrivate()
528#if QT_CONFIG(proxymodel)
532 currentHistoryLocation(-1),
533 renameAction(
nullptr),
534 deleteAction(
nullptr),
535 showHiddenAction(
nullptr),
536 useDefaultCaption(
true),
537 qFileDialogUi(
nullptr),
538 options(QFileDialogOptions::create())
542QFileDialogPrivate::~QFileDialogPrivate()
546void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
549 auto *fileDialogHelper =
static_cast<QPlatformFileDialogHelper *>(h);
550 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::fileSelected,
551 this, &QFileDialogPrivate::emitUrlSelected);
552 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::filesSelected,
553 this, &QFileDialogPrivate::emitUrlsSelected);
554 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::currentChanged,
555 this, &QFileDialogPrivate::nativeCurrentChanged);
556 QObjectPrivate::connect(fileDialogHelper, &QPlatformFileDialogHelper::directoryEntered,
557 this, &QFileDialogPrivate::nativeEnterDirectory);
558 QObject::connect(fileDialogHelper, &QPlatformFileDialogHelper::filterSelected,
559 q, &QFileDialog::filterSelected);
560 fileDialogHelper->setOptions(options);
563void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
566 options->setWindowTitle(q->windowTitle());
567 options->setHistory(q->history());
569 options->setSidebarUrls(qFileDialogUi->sidebar->urls());
570 if (options->initiallySelectedNameFilter().isEmpty())
571 options->setInitiallySelectedNameFilter(q->selectedNameFilter());
572 if (options->initiallySelectedFiles().isEmpty())
573 options->setInitiallySelectedFiles(userSelectedFiles());
576void QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
578 if (code == QDialog::Accepted) {
580 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
581 q->setSidebarUrls(options->sidebarUrls());
582 q->setHistory(options->history());
586void QFileDialogPrivate::retranslateWindowTitle()
589 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
591 if (q->acceptMode() == QFileDialog::AcceptOpen) {
592 const QFileDialog::FileMode fileMode = q->fileMode();
593 if (fileMode == QFileDialog::Directory)
594 q->setWindowTitle(QFileDialog::tr(
"Find Directory"));
596 q->setWindowTitle(QFileDialog::tr(
"Open"));
598 q->setWindowTitle(QFileDialog::tr(
"Save As"));
600 setWindowTitle = q->windowTitle();
603void QFileDialogPrivate::setLastVisitedDirectory(
const QUrl &dir)
605 *lastVisitedDir() = dir;
608void QFileDialogPrivate::updateLookInLabel()
610 if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))
611 setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));
614void QFileDialogPrivate::updateFileNameLabel()
616 if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
617 setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
619 switch (q_func()->fileMode()) {
620 case QFileDialog::Directory:
621 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"Directory:"));
624 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr(
"File &name:"));
630void QFileDialogPrivate::updateFileTypeLabel()
632 if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))
633 setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));
636void QFileDialogPrivate::updateOkButtonText(
bool saveAsOnFolder)
640 if (saveAsOnFolder) {
641 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Open"));
642 }
else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
643 setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));
646 switch (q->fileMode()) {
647 case QFileDialog::Directory:
648 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr(
"&Choose"));
651 setLabelTextControl(QFileDialog::Accept,
652 q->acceptMode() == QFileDialog::AcceptOpen ?
653 QFileDialog::tr(
"&Open") :
654 QFileDialog::tr(
"&Save"));
660void QFileDialogPrivate::updateCancelButtonText()
662 if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))
663 setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));
666void QFileDialogPrivate::retranslateStrings()
670 if (options->useDefaultNameFilters())
671 q->setNameFilter(QFileDialogOptions::defaultNameFilterString());
675 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
676 QAbstractItemModel *abstractModel = model;
677#if QT_CONFIG(proxymodel)
679 abstractModel = proxyModel;
681 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
682 for (
int i = 1; i < total; ++i) {
683 actions.at(i - 1)->setText(QFileDialog::tr(
"Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
687 renameAction->setText(QFileDialog::tr(
"&Rename"));
688 deleteAction->setText(QFileDialog::tr(
"&Delete"));
689 showHiddenAction->setText(QFileDialog::tr(
"Show &hidden files"));
690 newFolderAction->setText(QFileDialog::tr(
"&New Folder"));
691 qFileDialogUi->retranslateUi(q);
693 updateFileNameLabel();
694 updateFileTypeLabel();
695 updateCancelButtonText();
698void QFileDialogPrivate::emitFilesSelected(
const QStringList &files)
701 emit q->filesSelected(files);
702 if (files.size() == 1)
703 emit q->fileSelected(files.first());
706bool QFileDialogPrivate::canBeNativeDialog()
const
710 const QDialog *
const q =
static_cast<
const QDialog*>(q_ptr);
711 if (nativeDialogInUse)
713 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
714 || q->testAttribute(Qt::WA_DontShowOnScreen)
715 || (options->options() & QFileDialog::DontUseNativeDialog)) {
719 return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
722bool QFileDialogPrivate::usingWidgets()
const
724 return !nativeDialogInUse && qFileDialogUi;
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743void QFileDialog::setOption(Option option,
bool on)
745 const QFileDialog::Options previousOptions = options();
746 if (!(previousOptions & option) != !on)
747 setOptions(previousOptions ^ option);
751
752
753
754
755
756bool QFileDialog::testOption(Option option)
const
758 Q_D(
const QFileDialog);
759 return d->options->testOption(
static_cast<QFileDialogOptions::FileDialogOption>(option));
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780void QFileDialog::setOptions(Options options)
784 Options changed = (options ^ QFileDialog::options());
788 d->options->setOptions(QFileDialogOptions::FileDialogOptions(
int(options)));
790 if (options & DontUseNativeDialog) {
791 d->nativeDialogInUse =
false;
795 if (d->usingWidgets()) {
796 if (changed & DontResolveSymlinks)
797 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
798 if (changed & ReadOnly) {
799 bool ro = (options & ReadOnly);
800 d->model->setReadOnly(ro);
801 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
802 d->renameAction->setEnabled(!ro);
803 d->deleteAction->setEnabled(!ro);
806 if (changed & DontUseCustomDirectoryIcons) {
807 QFileIconProvider::Options providerOptions = iconProvider()->options();
808 providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons,
809 options & DontUseCustomDirectoryIcons);
810 iconProvider()->setOptions(providerOptions);
814 if (changed & HideNameFilterDetails)
815 setNameFilters(d->options->nameFilters());
817 if (changed & ShowDirsOnly)
818 setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
821QFileDialog::Options QFileDialog::options()
const
823 Q_D(
const QFileDialog);
824 static_assert((
int)QFileDialog::ShowDirsOnly == (
int)QFileDialogOptions::ShowDirsOnly);
825 static_assert((
int)QFileDialog::DontResolveSymlinks == (
int)QFileDialogOptions::DontResolveSymlinks);
826 static_assert((
int)QFileDialog::DontConfirmOverwrite == (
int)QFileDialogOptions::DontConfirmOverwrite);
827 static_assert((
int)QFileDialog::DontUseNativeDialog == (
int)QFileDialogOptions::DontUseNativeDialog);
828 static_assert((
int)QFileDialog::ReadOnly == (
int)QFileDialogOptions::ReadOnly);
829 static_assert((
int)QFileDialog::HideNameFilterDetails == (
int)QFileDialogOptions::HideNameFilterDetails);
830 static_assert((
int)QFileDialog::DontUseCustomDirectoryIcons == (
int)QFileDialogOptions::DontUseCustomDirectoryIcons);
831 return QFileDialog::Options(
int(d->options->options()));
835
836
837
838
839
840
841void QFileDialog::open(QObject *receiver,
const char *member)
844 const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))
845 : SIGNAL(fileSelected(QString));
846 connect(
this, signal, receiver, member);
847 d->signalToDisconnectOnClose = signal;
848 d->receiverToDisconnectOnClose = receiver;
849 d->memberToDisconnectOnClose = member;
856
857
858void QFileDialog::setVisible(
bool visible)
861 QDialog::setVisible(visible);
865
866
867
868
869
870void QFileDialogPrivate::setVisible(
bool visible)
874 const auto q =
static_cast<QDialog *>(q_ptr);
876 if (canBeNativeDialog()){
877 if (setNativeDialogVisible(visible)){
880 q->setAttribute(Qt::WA_DontShowOnScreen);
881#if QT_CONFIG(fscompleter)
883 if (!nativeDialogInUse)
884 completer->setModel(
nullptr);
886 }
else if (visible) {
888 q->setAttribute(Qt::WA_DontShowOnScreen,
false);
889#if QT_CONFIG(fscompleter)
890 if (!nativeDialogInUse) {
891 if (proxyModel !=
nullptr)
892 completer->setModel(proxyModel);
894 completer->setModel(model);
900 if (visible && usingWidgets())
901 qFileDialogUi->fileNameEdit->setFocus();
903 QDialogPrivate::setVisible(visible);
907
908
909
910void QFileDialogPrivate::goToUrl(
const QUrl &url)
914 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(),
true);
915 QModelIndex idx = model->d_func()->index(node);
920
921
922
923
926
927
928
929
930
931
932
933
934
935
936
937void QFileDialog::setDirectory(
const QString &directory)
940 QString newDirectory = directory;
942 if (!directory.isEmpty())
943 newDirectory = QDir::cleanPath(directory);
945 if (!directory.isEmpty() && newDirectory.isEmpty())
948 QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
949 QFileDialogPrivate::setLastVisitedDirectory(newDirUrl);
951 d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
952 if (!d->usingWidgets()) {
953 d->setDirectory_sys(newDirUrl);
956 if (d->rootPath() == newDirectory)
958 QModelIndex root = d->model->setRootPath(newDirectory);
959 if (!d->nativeDialogInUse) {
960 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
961 if (root != d->rootIndex()) {
962#if QT_CONFIG(fscompleter)
963 if (directory.endsWith(u'/'))
964 d->completer->setCompletionPrefix(newDirectory);
966 d->completer->setCompletionPrefix(newDirectory + u'/');
968 d->setRootIndex(root);
970 d->qFileDialogUi->listView->selectionModel()->clear();
975
976
977QDir QFileDialog::directory()
const
979 Q_D(
const QFileDialog);
980 if (d->nativeDialogInUse) {
981 QString dir = d->directory_sys().toLocalFile();
982 return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
984 return d->rootPath();
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004void QFileDialog::setDirectoryUrl(
const QUrl &directory)
1007 if (!directory.isValid())
1010 QFileDialogPrivate::setLastVisitedDirectory(directory);
1011 d->options->setInitialDirectory(directory);
1013 if (d->nativeDialogInUse)
1014 d->setDirectory_sys(directory);
1015 else if (directory.isLocalFile())
1016 setDirectory(directory.toLocalFile());
1017 else if (Q_UNLIKELY(d->usingWidgets()))
1018 qWarning(
"Non-native QFileDialog supports only local files");
1022
1023
1024
1025
1026QUrl QFileDialog::directoryUrl()
const
1028 Q_D(
const QFileDialog);
1029 if (d->nativeDialogInUse)
1030 return d->directory_sys();
1032 return QUrl::fromLocalFile(directory().absolutePath());
1039#if defined(Q_OS_WIN)
1043#elif defined(Q_OS_MACOS)
1044 return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE) == 1;
1054 if (!QFileInfo(path).isAbsolute())
1056 if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
1057 path.remove(0, rootPath.size());
1062 if (path.at(0) == QDir::separator()
1065 || path.at(0) == u'/'
1074
1075
1076
1077
1078void QFileDialog::selectFile(
const QString &filename)
1081 if (filename.isEmpty())
1084 if (!d->usingWidgets()) {
1086 if (QFileInfo(filename).isRelative()) {
1087 url = d->options->initialDirectory();
1088 QString path = url.path();
1089 if (!path.endsWith(u'/'))
1091 url.setPath(path + filename);
1093 url = QUrl::fromLocalFile(filename);
1095 d->selectFile_sys(url);
1096 d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
1100 if (!QDir::isRelativePath(filename)) {
1101 QFileInfo info(filename);
1102 QString filenamePath = info.absoluteDir().path();
1104 if (d->model->rootPath() != filenamePath)
1105 setDirectory(filenamePath);
1108 QModelIndex index = d->model->index(filename);
1109 d->qFileDialogUi->listView->selectionModel()->clear();
1110 if (!isVisible() || !d->lineEdit()->hasFocus())
1111 d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
1115
1116
1117
1118
1119
1120
1121
1122void QFileDialog::selectUrl(
const QUrl &url)
1128 if (d->nativeDialogInUse)
1129 d->selectFile_sys(url);
1130 else if (url.isLocalFile())
1131 selectFile(url.toLocalFile());
1133 qWarning(
"Non-native QFileDialog supports only local files");
1137static QString homeDirFromPasswdEntry(
const QString &path,
const QByteArray &userName)
1139#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1142 long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
1145 QVarLengthArray<
char, 1024> buf(bufSize);
1147# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0
< 199506L
)
1148 tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());
1150 err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);
1154 return QFile::decodeName(pw.pw_dir);
1156 passwd *pw = getpwnam(userName.constData());
1159 return QFile::decodeName(pw->pw_dir);
1163Q_AUTOTEST_EXPORT QString qt_tildeExpansion(
const QString &path)
1165 if (!path.startsWith(u'~'))
1168 if (path.size() == 1)
1169 return QDir::homePath();
1171 QStringView sv(path);
1172 const qsizetype sepIndex = sv.indexOf(QDir::separator());
1174 return QDir::homePath() + sv.sliced(1);
1176#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1178 return QDir::homePath();
1179 return QDir::homePath() + sv.sliced(sepIndex);
1181 const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen(
"~")
1182 : path.size() - strlen(
"~");
1183 const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();
1184 QString homePath = homeDirFromPasswdEntry(path, userName);
1187 return homePath + sv.sliced(sepIndex);
1193
1194
1195QStringList QFileDialogPrivate::typedFiles()
const
1197 Q_Q(
const QFileDialog);
1199 QString editText = lineEdit()->text();
1200 if (!editText.contains(u'"')) {
1202 const QString prefix = q->directory().absolutePath() + QDir::separator();
1203 if (QFile::exists(prefix + editText))
1206 files << qt_tildeExpansion(editText);
1214 QStringList tokens = editText.split(u'\"');
1215 for (
int i=0; i<tokens.size(); ++i) {
1219 const QString token = tokens.at(i);
1220 const QString prefix = q->directory().absolutePath() + QDir::separator();
1221 if (QFile::exists(prefix + token))
1224 files << qt_tildeExpansion(token);
1226 files << toInternal(tokens.at(i));
1230 return addDefaultSuffixToFiles(files);
1236QList<QUrl> QFileDialogPrivate::userSelectedFiles()
const
1240 if (!usingWidgets())
1241 return addDefaultSuffixToUrls(selectedFiles_sys());
1243 const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
1244 files.reserve(selectedRows.size());
1245 for (
const QModelIndex &index : selectedRows)
1246 files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));
1248 if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
1249 const QStringList typedFilesList = typedFiles();
1250 files.reserve(typedFilesList.size());
1251 for (
const QString &path : typedFilesList)
1252 files.append(QUrl::fromLocalFile(path));
1258QStringList QFileDialogPrivate::addDefaultSuffixToFiles(
const QStringList &filesToFix)
const
1261 for (
int i=0; i<filesToFix.size(); ++i) {
1262 QString name = toInternal(filesToFix.at(i));
1263 QFileInfo info(name);
1265 const QString defaultSuffix = options->defaultSuffix();
1266 if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
1267 name += u'.' + defaultSuffix;
1269 if (info.isAbsolute()) {
1275 QString path = rootPath();
1276 if (!path.endsWith(u'/'))
1285QList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(
const QList<QUrl> &urlsToFix)
const
1288 urls.reserve(urlsToFix.size());
1290 const QString defaultSuffix = options->defaultSuffix();
1291 for (QUrl url : urlsToFix) {
1292 if (!defaultSuffix.isEmpty()) {
1293 const QString urlPath = url.path();
1294 const auto idx = urlPath.lastIndexOf(u'/');
1295 if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
1296 url.setPath(urlPath + u'.' + defaultSuffix);
1305
1306
1307
1308
1309
1310
1311QStringList QFileDialog::selectedFiles()
const
1313 Q_D(
const QFileDialog);
1316 const QList<QUrl> userSelectedFiles = d->userSelectedFiles();
1317 files.reserve(userSelectedFiles.size());
1318 for (
const QUrl &file : userSelectedFiles)
1319 files.append(file.toString(QUrl::PreferLocalFile));
1321 if (files.isEmpty() && d->usingWidgets()) {
1322 const FileMode fm = fileMode();
1323 if (fm != ExistingFile && fm != ExistingFiles)
1324 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1330
1331
1332
1333
1334
1335
1336
1337QList<QUrl> QFileDialog::selectedUrls()
const
1339 Q_D(
const QFileDialog);
1340 if (d->nativeDialogInUse) {
1341 return d->userSelectedFiles();
1344 const QStringList selectedFileList = selectedFiles();
1345 urls.reserve(selectedFileList.size());
1346 for (
const QString &file : selectedFileList)
1347 urls.append(QUrl::fromLocalFile(file));
1353
1354
1355
1358 if (filter.isEmpty())
1359 return QStringList();
1362 if (!filter.contains(sep) && filter.contains(u'\n'))
1365 return filter.split(sep);
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383void QFileDialog::setNameFilter(
const QString &filter)
1385 setNameFilters(qt_make_filter_list(filter));
1390
1391
1394#if QT_CONFIG(regularexpression)
1395 QStringList strippedFilters;
1396 static const QRegularExpression r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
1397 strippedFilters.reserve(filters.size());
1398 for (
const QString &filter : filters) {
1400 auto match = r.match(filter);
1401 if (match.hasMatch())
1402 filterName = match.captured(1);
1403 strippedFilters.append(filterName.simplified());
1405 return strippedFilters;
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429void QFileDialog::setNameFilters(
const QStringList &filters)
1432 QStringList cleanedFilters;
1433 cleanedFilters.reserve(filters.size());
1434 for (
const QString &filter : filters)
1435 cleanedFilters << filter.simplified();
1437 d->options->setNameFilters(cleanedFilters);
1439 if (!d->usingWidgets())
1442 d->qFileDialogUi->fileTypeCombo->clear();
1443 if (cleanedFilters.isEmpty())
1446 if (testOption(HideNameFilterDetails))
1447 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1449 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1451 d->useNameFilter(0);
1455
1456
1457
1458QStringList QFileDialog::nameFilters()
const
1460 return d_func()->options->nameFilters();
1464
1465
1466
1467
1468
1469void QFileDialog::selectNameFilter(
const QString &filter)
1472 d->options->setInitiallySelectedNameFilter(filter);
1473 if (!d->usingWidgets()) {
1474 d->selectNameFilter_sys(filter);
1478 if (testOption(HideNameFilterDetails)) {
1479 const QStringList filters = qt_strip_filters(qt_make_filter_list(filter));
1480 if (!filters.isEmpty())
1481 i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());
1483 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1486 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1487 d->useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1492
1493
1494
1495
1496QString QFileDialog::selectedNameFilter()
const
1498 Q_D(
const QFileDialog);
1499 if (!d->usingWidgets())
1500 return d->selectedNameFilter_sys();
1502 if (testOption(HideNameFilterDetails)) {
1503 const auto idx = d->qFileDialogUi->fileTypeCombo->currentIndex();
1504 if (idx >= 0 && idx < d->options->nameFilters().size())
1505 return d->options->nameFilters().at(d->qFileDialogUi->fileTypeCombo->currentIndex());
1507 return d->qFileDialogUi->fileTypeCombo->currentText();
1511
1512
1513
1514
1515QDir::Filters QFileDialog::filter()
const
1517 Q_D(
const QFileDialog);
1518 if (d->usingWidgets())
1519 return d->model->filter();
1520 return d->options->filter();
1524
1525
1526
1527
1528
1530void QFileDialog::setFilter(QDir::Filters filters)
1533 d->options->setFilter(filters);
1534 if (!d->usingWidgets()) {
1539 d->model->setFilter(filters);
1540 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1543#if QT_CONFIG(mimetype)
1545static QString nameFilterForMime(
const QString &mimeType)
1548 QMimeType mime(db.mimeTypeForName(mimeType));
1549 if (mime.isValid()) {
1550 if (mime.isDefault()) {
1551 return QFileDialog::tr(
"All files (*)");
1553 const QString patterns = mime.globPatterns().join(u' ');
1554 return mime.comment() +
" ("_L1 + patterns + u')';
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577void QFileDialog::setMimeTypeFilters(
const QStringList &filters)
1580 QStringList nameFilters;
1581 for (
const QString &mimeType : filters) {
1582 const QString text = nameFilterForMime(mimeType);
1583 if (!text.isEmpty())
1584 nameFilters.append(text);
1586 setNameFilters(nameFilters);
1587 d->options->setMimeTypeFilters(filters);
1591
1592
1593
1594
1595
1596QStringList QFileDialog::mimeTypeFilters()
const
1598 return d_func()->options->mimeTypeFilters();
1602
1603
1604
1605
1606
1607void QFileDialog::selectMimeTypeFilter(
const QString &filter)
1610 d->options->setInitiallySelectedMimeTypeFilter(filter);
1612 const QString filterForMime = nameFilterForMime(filter);
1614 if (!d->usingWidgets()) {
1615 d->selectMimeTypeFilter_sys(filter);
1616 if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
1617 selectNameFilter(filterForMime);
1619 }
else if (!filterForMime.isEmpty()) {
1620 selectNameFilter(filterForMime);
1627
1628
1629
1630QString QFileDialog::selectedMimeTypeFilter()
const
1632 Q_D(
const QFileDialog);
1633 QString mimeTypeFilter;
1634 if (!d->usingWidgets())
1635 mimeTypeFilter = d->selectedMimeTypeFilter_sys();
1637#if QT_CONFIG(mimetype)
1638 if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
1639 const auto nameFilter = selectedNameFilter();
1640 const auto mimeTypes = d->options->mimeTypeFilters();
1641 for (
const auto &mimeType: mimeTypes) {
1642 QString filter = nameFilterForMime(mimeType);
1643 if (testOption(HideNameFilterDetails))
1644 filter = qt_strip_filters({ filter }).constFirst();
1645 if (filter == nameFilter) {
1646 mimeTypeFilter = mimeType;
1653 return mimeTypeFilter;
1657
1658
1659
1660
1661
1662
1663
1664
1665void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
1668 d->options->setViewMode(
static_cast<QFileDialogOptions::ViewMode>(mode));
1669 if (!d->usingWidgets())
1672 d->showDetailsView();
1677QFileDialog::ViewMode QFileDialog::viewMode()
const
1679 Q_D(
const QFileDialog);
1680 if (!d->usingWidgets())
1681 return static_cast<QFileDialog::ViewMode>(d->options->viewMode());
1682 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700void QFileDialog::setFileMode(QFileDialog::FileMode mode)
1703 d->options->setFileMode(
static_cast<QFileDialogOptions::FileMode>(mode));
1704 if (!d->usingWidgets())
1707 d->retranslateWindowTitle();
1710 QAbstractItemView::SelectionMode selectionMode;
1711 if (mode == QFileDialog::ExistingFiles)
1712 selectionMode = QAbstractItemView::ExtendedSelection;
1714 selectionMode = QAbstractItemView::SingleSelection;
1715 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1716 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1718 d->model->setFilter(d->filterForMode(filter()));
1720 if (mode == Directory) {
1721 d->qFileDialogUi->fileTypeCombo->clear();
1722 d->qFileDialogUi->fileTypeCombo->addItem(tr(
"Directories"));
1723 d->qFileDialogUi->fileTypeCombo->setEnabled(
false);
1725 d->updateFileNameLabel();
1726 d->updateOkButtonText();
1727 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1728 d->updateOkButton();
1731QFileDialog::FileMode QFileDialog::fileMode()
const
1733 Q_D(
const QFileDialog);
1734 return static_cast<FileMode>(d->options->fileMode());
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
1750 d->options->setAcceptMode(
static_cast<QFileDialogOptions::AcceptMode>(mode));
1752 setAttribute(Qt::WA_DontShowOnScreen,
false);
1753 if (!d->usingWidgets())
1755 QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
1756 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1757 d->qFileDialogUi->buttonBox->button(button)->setEnabled(
false);
1758 d->updateOkButton();
1759 if (mode == AcceptSave) {
1760 d->qFileDialogUi->lookInCombo->setEditable(
false);
1762 d->retranslateWindowTitle();
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1778void QFileDialog::setSupportedSchemes(
const QStringList &schemes)
1781 d->options->setSupportedSchemes(schemes);
1784QStringList QFileDialog::supportedSchemes()
const
1786 return d_func()->options->supportedSchemes();
1790
1791
1792
1793QModelIndex QFileDialogPrivate::rootIndex()
const {
1794 return mapToSource(qFileDialogUi->listView->rootIndex());
1797QAbstractItemView *QFileDialogPrivate::currentView()
const {
1798 if (!qFileDialogUi->stackedWidget)
1800 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1801 return qFileDialogUi->listView;
1802 return qFileDialogUi->treeView;
1805QLineEdit *QFileDialogPrivate::lineEdit()
const {
1806 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1809long QFileDialogPrivate::maxNameLength(
const QString &path)
1811#if defined(Q_OS_UNIX)
1812 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1813#elif defined(Q_OS_WIN)
1815 const QString drive = path.left(3);
1816 if (::GetVolumeInformation(
reinterpret_cast<
const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) ==
false)
1826
1827
1828void QFileDialogPrivate::setRootIndex(
const QModelIndex &index)
const {
1829 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1830 QModelIndex idx = mapFromSource(index);
1831 qFileDialogUi->treeView->setRootIndex(idx);
1832 qFileDialogUi->listView->setRootIndex(idx);
1835
1836
1837
1838QModelIndex QFileDialogPrivate::select(
const QModelIndex &index)
const {
1839 Q_ASSERT(index.isValid() ? index.model() == model :
true);
1841 QModelIndex idx = mapFromSource(index);
1842 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1843 qFileDialogUi->listView->selectionModel()->select(idx,
1844 QItemSelectionModel::Select | QItemSelectionModel::Rows);
1848QFileDialog::AcceptMode QFileDialog::acceptMode()
const
1850 Q_D(
const QFileDialog);
1851 return static_cast<AcceptMode>(d->options->acceptMode());
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865void QFileDialog::setDefaultSuffix(
const QString &suffix)
1868 d->options->setDefaultSuffix(suffix);
1871QString QFileDialog::defaultSuffix()
const
1873 Q_D(
const QFileDialog);
1874 return d->options->defaultSuffix();
1878
1879
1880
1881void QFileDialog::setHistory(
const QStringList &paths)
1884 if (d->usingWidgets())
1885 d->qFileDialogUi->lookInCombo->setHistory(paths);
1893 const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1895 const QUrl url = idx.isValid()
1896 ? QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()))
1900 urlModel->setUrls(list);
1904
1905
1906QStringList QFileDialog::history()
const
1908 Q_D(
const QFileDialog);
1909 if (!d->usingWidgets())
1910 return QStringList();
1911 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1913 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1914 if (!currentHistory.contains(newHistory))
1915 currentHistory << newHistory;
1916 return currentHistory;
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
1940 if (!d->usingWidgets())
1942 d->qFileDialogUi->listView->setItemDelegate(delegate);
1943 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1947
1948
1949QAbstractItemDelegate *QFileDialog::itemDelegate()
const
1951 Q_D(
const QFileDialog);
1952 if (!d->usingWidgets())
1954 return d->qFileDialogUi->listView->itemDelegate();
1958
1959
1960void QFileDialog::setIconProvider(QAbstractFileIconProvider *provider)
1963 if (!d->usingWidgets())
1965 d->model->setIconProvider(provider);
1967 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1971
1972
1973QAbstractFileIconProvider *QFileDialog::iconProvider()
const
1975 Q_D(
const QFileDialog);
1978 return d->model->iconProvider();
1981void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label,
const QString &text)
1986 case QFileDialog::LookIn:
1987 qFileDialogUi->lookInLabel->setText(text);
1989 case QFileDialog::FileName:
1990 qFileDialogUi->fileNameLabel->setText(text);
1992 case QFileDialog::FileType:
1993 qFileDialogUi->fileTypeLabel->setText(text);
1995 case QFileDialog::Accept:
1996 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
1997 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
1998 button->setText(text);
2000 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
2001 button->setText(text);
2004 case QFileDialog::Reject:
2005 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
2006 button->setText(text);
2012
2013
2015void QFileDialog::setLabelText(DialogLabel label,
const QString &text)
2018 d->options->setLabelText(
static_cast<QFileDialogOptions::DialogLabel>(label), text);
2019 d->setLabelTextControl(label, text);
2023
2024
2025QString QFileDialog::labelText(DialogLabel label)
const
2027 Q_D(
const QFileDialog);
2028 if (!d->usingWidgets())
2029 return d->options->labelText(
static_cast<QFileDialogOptions::DialogLabel>(label));
2030 QPushButton *button;
2033 return d->qFileDialogUi->lookInLabel->text();
2035 return d->qFileDialogUi->fileNameLabel->text();
2037 return d->qFileDialogUi->fileTypeLabel->text();
2039 if (acceptMode() == AcceptOpen)
2040 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
2042 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
2044 return button->text();
2047 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
2049 return button->text();
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097QString QFileDialog::getOpenFileName(QWidget *parent,
2098 const QString &caption,
2100 const QString &filter,
2101 QString *selectedFilter,
2104 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2105 const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2106 selectedFilter, options, schemes);
2107 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2108 return selectedUrl.toLocalFile();
2110 return selectedUrl.toString();
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
2141 const QString &caption,
2143 const QString &filter,
2144 QString *selectedFilter,
2146 const QStringList &supportedSchemes)
2148 QFileDialogArgs args(dir);
2149 args.parent = parent;
2150 args.caption = caption;
2151 args.filter = filter;
2152 args.mode = ExistingFile;
2153 args.options = options;
2155 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2156 dialog->setSupportedSchemes(supportedSchemes);
2157 if (selectedFilter && !selectedFilter->isEmpty())
2158 dialog->selectNameFilter(*selectedFilter);
2159 const int execResult = dialog->exec();
2160 if (
bool(dialog) && execResult == QDialog::Accepted) {
2162 *selectedFilter = dialog->selectedNameFilter();
2163 return dialog->selectedUrls().value(0);
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207QStringList QFileDialog::getOpenFileNames(QWidget *parent,
2208 const QString &caption,
2210 const QString &filter,
2211 QString *selectedFilter,
2214 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2215 const QList<QUrl> selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),
2216 filter, selectedFilter, options, schemes);
2217 QStringList fileNames;
2218 fileNames.reserve(selectedUrls.size());
2219 for (
const QUrl &url : selectedUrls)
2220 fileNames.append(url.toString(QUrl::PreferLocalFile));
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
2253 const QString &caption,
2255 const QString &filter,
2256 QString *selectedFilter,
2258 const QStringList &supportedSchemes)
2260 QFileDialogArgs args(dir);
2261 args.parent = parent;
2262 args.caption = caption;
2263 args.filter = filter;
2264 args.mode = ExistingFiles;
2265 args.options = options;
2267 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2268 dialog->setSupportedSchemes(supportedSchemes);
2269 if (selectedFilter && !selectedFilter->isEmpty())
2270 dialog->selectNameFilter(*selectedFilter);
2271 const int execResult = dialog->exec();
2272 if (
bool(dialog) && execResult == QDialog::Accepted) {
2274 *selectedFilter = dialog->selectedNameFilter();
2275 return dialog->selectedUrls();
2277 return QList<QUrl>();
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299void QFileDialog::getOpenFileContent(
const QString &nameFilter,
const std::function<
void(
const QString &,
const QByteArray &)> &fileOpenCompleted, QWidget *parent)
2303 auto openFileImpl = std::make_shared<std::function<
void(
void)>>();
2305 QByteArray fileContent;
2306 *openFileImpl = [=]()
mutable {
2307 auto fileDialogClosed = [&](
bool fileSelected) {
2308 if (!fileSelected) {
2309 fileOpenCompleted(fileName, fileContent);
2310 openFileImpl.reset();
2313 auto acceptFile = [&](uint64_t size,
const std::string name) ->
char * {
2314 const uint64_t twoGB = 1ULL << 31;
2318 fileName = QString::fromStdString(name);
2319 fileContent.resize(size);
2320 return fileContent.data();
2322 auto fileContentReady = [&]()
mutable {
2323 fileOpenCompleted(fileName, fileContent);
2324 openFileImpl.reset();
2327 QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
2332 QFileDialog *dialog =
new QFileDialog(parent);
2333 dialog->setFileMode(QFileDialog::ExistingFile);
2334 dialog->setNameFilter(nameFilter);
2335 dialog->setAttribute(Qt::WA_DeleteOnClose);
2337 auto fileSelected = [=](
const QString &fileName) {
2338 QByteArray fileContent;
2339 if (!fileName.isNull()) {
2340 QFile selectedFile(fileName);
2341 if (selectedFile.open(QIODevice::ReadOnly))
2342 fileContent = selectedFile.readAll();
2344 fileOpenCompleted(fileName, fileContent);
2347 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370void QFileDialog::saveFileContent(
const QByteArray &fileContent,
const QString &fileNameHint, QWidget *parent)
2374 QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
2376 QFileDialog *dialog =
new QFileDialog(parent);
2377 dialog->setAcceptMode(QFileDialog::AcceptSave);
2378 dialog->setFileMode(QFileDialog::AnyFile);
2379 dialog->selectFile(fileNameHint);
2381 auto fileSelected = [=](
const QString &fileName) {
2382 if (!fileName.isNull()) {
2383 QFile selectedFile(fileName);
2384 if (selectedFile.open(QIODevice::WriteOnly))
2385 selectedFile.write(fileContent);
2389 connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected);
2390 dialog->setAttribute(Qt::WA_DeleteOnClose);
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439QString QFileDialog::getSaveFileName(QWidget *parent,
2440 const QString &caption,
2442 const QString &filter,
2443 QString *selectedFilter,
2446 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2447 const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2448 selectedFilter, options, schemes);
2449 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2450 return selectedUrl.toLocalFile();
2452 return selectedUrl.toString();
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
2483 const QString &caption,
2485 const QString &filter,
2486 QString *selectedFilter,
2488 const QStringList &supportedSchemes)
2490 QFileDialogArgs args(dir);
2491 args.parent = parent;
2492 args.caption = caption;
2493 args.filter = filter;
2494 args.mode = AnyFile;
2495 args.options = options;
2497 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2498 dialog->setSupportedSchemes(supportedSchemes);
2499 dialog->setAcceptMode(AcceptSave);
2500 if (selectedFilter && !selectedFilter->isEmpty())
2501 dialog->selectNameFilter(*selectedFilter);
2502 const int execResult = dialog->exec();
2503 if (
bool(dialog) && execResult == QDialog::Accepted) {
2505 *selectedFilter = dialog->selectedNameFilter();
2506 return dialog->selectedUrls().value(0);
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551QString QFileDialog::getExistingDirectory(QWidget *parent,
2552 const QString &caption,
2556 const QStringList schemes = QStringList(QStringLiteral(
"file"));
2557 const QUrl selectedUrl =
2558 getExistingDirectoryUrl(parent, caption, QUrl::fromLocalFile(dir), options, schemes);
2559 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2560 return selectedUrl.toLocalFile();
2562 return selectedUrl.toString();
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
2593 const QString &caption,
2596 const QStringList &supportedSchemes)
2598 QFileDialogArgs args(dir);
2599 args.parent = parent;
2600 args.caption = caption;
2601 args.mode = Directory;
2602 args.options = options;
2604 QAutoPointer<QFileDialog> dialog(
new QFileDialog(args));
2605 dialog->setSupportedSchemes(supportedSchemes);
2606 const int execResult = dialog->exec();
2607 if (
bool(dialog) && execResult == QDialog::Accepted)
2608 return dialog->selectedUrls().value(0);
2614 if (url.isLocalFile()) {
2615 QFileInfo info = local;
2616 if (!local.isAbsolute())
2617 info = QFileInfo(QDir::current(), url.toLocalFile());
2618 const QFileInfo pathInfo(info.absolutePath());
2619 if (!pathInfo.exists() || !pathInfo.isDir())
2621 if (info.exists() && info.isDir())
2622 return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));
2623 return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
2630#if QT_CONFIG(settings)
2631 if (lastVisitedDir()->isEmpty()) {
2632 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2633 const QString &lastVisisted = settings.value(
"FileDialog/lastVisited", QString()).toString();
2634 *lastVisitedDir() = QUrl::fromLocalFile(lastVisisted);
2640
2641
2645 const QFileInfo local(url.toLocalFile());
2648 directory = _qt_get_directory(url, local);
2649 if (directory.isEmpty()) {
2651 const QUrl lastVisited = *lastVisitedDir();
2652 if (lastVisited != url)
2653 directory = _qt_get_directory(lastVisited, QFileInfo());
2655 if (directory.isEmpty())
2656 directory = QUrl::fromLocalFile(QDir::currentPath());
2659
2660
2661
2662 if (selection.isEmpty() && !url.isEmpty()) {
2663 if (url.isLocalFile()) {
2665 selection = local.fileName();
2668 selection = url.fileName();
2674
2675
2676void QFileDialog::done(
int result)
2680 QDialog::done(result);
2682 if (d->receiverToDisconnectOnClose) {
2683 disconnect(
this, d->signalToDisconnectOnClose,
2684 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2685 d->receiverToDisconnectOnClose =
nullptr;
2687 d->memberToDisconnectOnClose.clear();
2688 d->signalToDisconnectOnClose.clear();
2691bool QFileDialogPrivate::itemAlreadyExists(
const QString &fileName)
2693#if QT_CONFIG(messagebox)
2695 const QString msg = QFileDialog::tr(
"%1 already exists.\nDo you want to replace it?").arg(fileName);
2696 using B = QMessageBox;
2697 const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
2698 return res == B::Yes;
2703void QFileDialogPrivate::itemNotFound(
const QString &fileName, QFileDialog::FileMode mode)
2705#if QT_CONFIG(messagebox)
2707 const QString message = mode == QFileDialog::Directory
2708 ? QFileDialog::tr(
"%1\nDirectory not found.\n"
2709 "Please verify the correct directory name was given.")
2710 : QFileDialog::tr(
"%1\nFile not found.\nPlease verify the "
2711 "correct file name was given.");
2713 QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
2718
2719
2720void QFileDialog::accept()
2723 if (!d->usingWidgets()) {
2724 const QList<QUrl> urls = selectedUrls();
2727 d->emitUrlsSelected(urls);
2728 if (urls.size() == 1)
2729 d->emitUrlSelected(urls.first());
2734 const QStringList files = selectedFiles();
2735 if (files.isEmpty())
2737 QString lineEditText = d->lineEdit()->text();
2740 if (lineEditText ==
".."_L1) {
2741 d->navigateToParent();
2742 const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
2743 d->lineEdit()->selectAll();
2747 const auto mode = fileMode();
2750 QString fn = files.first();
2753 info = QFileInfo(d->getEnvironmentVariable(fn));
2754 if (!info.exists()) {
2755 d->itemNotFound(info.fileName(), mode);
2759 d->emitFilesSelected(files);
2766 QString fn = files.first();
2769 setDirectory(info.absoluteFilePath());
2773 if (!info.exists()) {
2774 const long maxNameLength = d->maxNameLength(info.path());
2775 if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
2780 if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {
2781 d->emitFilesSelected(QStringList(fn));
2784 if (d->itemAlreadyExists(info.fileName())) {
2785 d->emitFilesSelected(QStringList(fn));
2794 for (
const auto &file : files) {
2795 QFileInfo info(file);
2797 info = QFileInfo(d->getEnvironmentVariable(file));
2798 if (!info.exists()) {
2799 d->itemNotFound(info.fileName(), mode);
2803 setDirectory(info.absoluteFilePath());
2804 d->lineEdit()->clear();
2808 d->emitFilesSelected(files);
2814#if QT_CONFIG(settings)
2815void QFileDialogPrivate::saveSettings()
2818 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2819 settings.beginGroup(
"FileDialog");
2821 if (usingWidgets()) {
2822 settings.setValue(
"sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
2823 settings.setValue(
"shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
2824 settings.setValue(
"treeViewHeader", qFileDialogUi->treeView->header()->saveState());
2826 QStringList historyUrls;
2827 const QStringList history = q->history();
2828 historyUrls.reserve(history.size());
2829 for (
const QString &path : history)
2830 historyUrls << QUrl::fromLocalFile(path).toString();
2831 settings.setValue(
"history", historyUrls);
2832 settings.setValue(
"lastVisited", lastVisitedDir()->toString());
2833 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2834 settings.setValue(
"viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
2835 settings.setValue(
"qtVersion", QT_VERSION_STR
""_L1);
2838bool QFileDialogPrivate::restoreFromSettings()
2841 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2842 if (!settings.childGroups().contains(
"FileDialog"_L1))
2844 settings.beginGroup(
"FileDialog");
2846 q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value(
"lastVisited").toUrl() : *lastVisitedDir());
2848 QByteArray viewModeStr = settings.value(
"viewMode").toString().toLatin1();
2849 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator(
"ViewMode"));
2851 int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
2853 viewMode = QFileDialog::List;
2854 q->setViewMode(
static_cast<QFileDialog::ViewMode>(viewMode));
2856 sidebarUrls = QUrl::fromStringList(settings.value(
"shortcuts").toStringList());
2857 headerData = settings.value(
"treeViewHeader").toByteArray();
2859 if (!usingWidgets())
2862 QStringList history;
2863 const auto urlStrings = settings.value(
"history").toStringList();
2864 for (
const QString &urlStr : urlStrings) {
2866 if (url.isLocalFile())
2867 history << url.toLocalFile();
2870 return restoreWidgetState(history, settings.value(
"sidebarWidth", -1).toInt());
2874bool QFileDialogPrivate::restoreWidgetState(QStringList &history,
int splitterPosition)
2877 if (splitterPosition >= 0) {
2878 QList<
int> splitterSizes;
2879 splitterSizes.append(splitterPosition);
2880 splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
2881 qFileDialogUi->splitter->setSizes(splitterSizes);
2883 if (!qFileDialogUi->splitter->restoreState(splitterState))
2885 QList<
int> list = qFileDialogUi->splitter->sizes();
2886 if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
2887 for (
int i = 0; i < list.size(); ++i)
2888 list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
2889 qFileDialogUi->splitter->setSizes(list);
2893 qFileDialogUi->sidebar->setUrls(sidebarUrls);
2895 static const int MaxHistorySize = 5;
2896 if (history.size() > MaxHistorySize)
2897 history.erase(history.begin(), history.end() - MaxHistorySize);
2898 q->setHistory(history);
2900 QHeaderView *headerView = qFileDialogUi->treeView->header();
2901 if (!headerView->restoreState(headerData))
2904 QList<QAction*> actions = headerView->actions();
2905 QAbstractItemModel *abstractModel = model;
2906#if QT_CONFIG(proxymodel)
2908 abstractModel = proxyModel;
2910 const int total = qMin(abstractModel->columnCount(QModelIndex()),
int(actions.size() + 1));
2911 for (
int i = 1; i < total; ++i)
2912 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
2918
2919
2920
2921
2922void QFileDialogPrivate::init(
const QFileDialogArgs &args)
2925 if (!args.caption.isEmpty()) {
2926 useDefaultCaption =
false;
2927 setWindowTitle = args.caption;
2928 q->setWindowTitle(args.caption);
2931 q->setAcceptMode(QFileDialog::AcceptOpen);
2932 nativeDialogInUse = platformFileDialogHelper() !=
nullptr;
2933 if (!nativeDialogInUse)
2935 q->setFileMode(QFileDialog::AnyFile);
2936 if (!args.filter.isEmpty())
2937 q->setNameFilter(args.filter);
2938 q->setDirectoryUrl(args.directory);
2939 if (args.directory.isLocalFile())
2940 q->selectFile(args.selection);
2942 q->selectUrl(args.directory);
2944#if QT_CONFIG(settings)
2947 if (!restoreFromSettings()) {
2948 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
2949 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
2953#if defined(Q_EMBEDDED_SMALLSCREEN)
2954 qFileDialogUi->lookInLabel->setVisible(
false);
2955 qFileDialogUi->fileNameLabel->setVisible(
false);
2956 qFileDialogUi->fileTypeLabel->setVisible(
false);
2957 qFileDialogUi->sidebar->hide();
2960 const QSize sizeHint = q->sizeHint();
2961 if (sizeHint.isValid())
2962 q->resize(sizeHint);
2966
2967
2968
2969
2970void QFileDialogPrivate::createWidgets()
2979 QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
2980 Qt::WindowStates preState = q->windowState();
2982 model =
new QFileSystemModel(q);
2983 model->setIconProvider(&defaultIconProvider);
2984 model->setFilter(options->filter());
2985 model->setObjectName(
"qt_filesystem_model"_L1);
2986 if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
2987 model->setNameFilterDisables(helper->defaultNameFilterDisables());
2989 model->setNameFilterDisables(
false);
2990 model->d_func()->disableRecursiveSort =
true;
2991 QObjectPrivate::connect(model, &QFileSystemModel::fileRenamed,
2992 this, &QFileDialogPrivate::fileRenamed);
2993 QObjectPrivate::connect(model, &QFileSystemModel::rootPathChanged,
2994 this, &QFileDialogPrivate::pathChanged);
2995 QObjectPrivate::connect(model, &QFileSystemModel::rowsInserted,
2996 this, &QFileDialogPrivate::rowsInserted);
2997 model->setReadOnly(
false);
2999 qFileDialogUi.reset(
new Ui_QFileDialog());
3000 qFileDialogUi->setupUi(q);
3002 QList<QUrl> initialBookmarks;
3003 initialBookmarks << QUrl(
"file:"_L1)
3004 << QUrl::fromLocalFile(QDir::homePath());
3005 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
3006 QObjectPrivate::connect(qFileDialogUi->sidebar, &QSidebar::goToUrl,
3007 this, &QFileDialogPrivate::goToUrl);
3009 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::accepted,
3010 q, &QFileDialog::accept);
3011 QObject::connect(qFileDialogUi->buttonBox, &QDialogButtonBox::rejected,
3012 q, &QFileDialog::reject);
3014 qFileDialogUi->lookInCombo->setFileDialogPrivate(
this);
3015 QObjectPrivate::connect(qFileDialogUi->lookInCombo, &QComboBox::textActivated,
3016 this, &QFileDialogPrivate::goToDirectory);
3018 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
3019 qFileDialogUi->lookInCombo->setDuplicatesEnabled(
false);
3022#ifndef QT_NO_SHORTCUT
3023 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
3025#if QT_CONFIG(fscompleter)
3026 completer =
new QFSCompleter(model, q);
3027 qFileDialogUi->fileNameEdit->setCompleter(completer);
3030 qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
3032 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3033 this, &QFileDialogPrivate::autoCompleteFileName);
3034 QObjectPrivate::connect(qFileDialogUi->fileNameEdit, &QLineEdit::textChanged,
3035 this, &QFileDialogPrivate::updateOkButton);
3036 QObject::connect(qFileDialogUi->fileNameEdit, &QLineEdit::returnPressed,
3037 q, &QFileDialog::accept);
3040 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(
false);
3041 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
3042 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
3043 QObjectPrivate::connect(qFileDialogUi->fileTypeCombo, &QComboBox::activated,
3044 this, &QFileDialogPrivate::useNameFilter);
3045 QObject::connect(qFileDialogUi->fileTypeCombo, &QComboBox::textActivated,
3046 q, &QFileDialog::filterSelected);
3048 qFileDialogUi->listView->setFileDialogPrivate(
this);
3049 qFileDialogUi->listView->setModel(model);
3050 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::activated,
3051 this, &QFileDialogPrivate::enterDirectory);
3052 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::customContextMenuRequested,
3053 this, &QFileDialogPrivate::showContextMenu);
3054#ifndef QT_NO_SHORTCUT
3055 QShortcut *shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);
3056 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3057 this, &QFileDialogPrivate::deleteCurrent);
3060 qFileDialogUi->treeView->setFileDialogPrivate(
this);
3061 qFileDialogUi->treeView->setModel(model);
3062 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
3063 QFontMetrics fm(q->font());
3064 treeHeader->resizeSection(0, fm.horizontalAdvance(
"wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
3065 treeHeader->resizeSection(1, fm.horizontalAdvance(
"128.88 GB"_L1));
3066 treeHeader->resizeSection(2, fm.horizontalAdvance(
"mp3Folder"_L1));
3067 treeHeader->resizeSection(3, fm.horizontalAdvance(
"10/29/81 02:02PM"_L1));
3068 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
3070 QActionGroup *showActionGroup =
new QActionGroup(q);
3071 showActionGroup->setExclusive(
false);
3072 QObjectPrivate::connect(showActionGroup, &QActionGroup::triggered,
3073 this, &QFileDialogPrivate::showHeader);
3075 QAbstractItemModel *abstractModel = model;
3076#if QT_CONFIG(proxymodel)
3078 abstractModel = proxyModel;
3080 for (
int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
3081 QAction *showHeader =
new QAction(showActionGroup);
3082 showHeader->setCheckable(
true);
3083 showHeader->setChecked(
true);
3084 treeHeader->addAction(showHeader);
3087 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
3088 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
3090 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::activated,
3091 this, &QFileDialogPrivate::enterDirectory);
3092 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::customContextMenuRequested,
3093 this, &QFileDialogPrivate::showContextMenu);
3094#ifndef QT_NO_SHORTCUT
3095 shortcut =
new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);
3096 QObjectPrivate::connect(shortcut, &QShortcut::activated,
3097 this, &QFileDialogPrivate::deleteCurrent);
3101 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
3102 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3103 this, &QFileDialogPrivate::selectionChanged);
3104 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3105 this, &QFileDialogPrivate::currentChanged);
3106 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
3108 createToolButtons();
3109 createMenuActions();
3111#if QT_CONFIG(settings)
3114 if (!restoreFromSettings()) {
3115 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
3116 q->restoreState(settings.value(
"Qt/filedialog").toByteArray());
3121 q->setFileMode(
static_cast<QFileDialog::FileMode>(options->fileMode()));
3122 q->setAcceptMode(
static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
3123 q->setViewMode(
static_cast<QFileDialog::ViewMode>(options->viewMode()));
3124 q->setOptions(
static_cast<QFileDialog::Options>(
static_cast<
int>(options->options())));
3125 if (!options->sidebarUrls().isEmpty())
3126 q->setSidebarUrls(options->sidebarUrls());
3127 q->setDirectoryUrl(options->initialDirectory());
3128#if QT_CONFIG(mimetype)
3129 if (!options->mimeTypeFilters().isEmpty())
3130 q->setMimeTypeFilters(options->mimeTypeFilters());
3133 if (!options->nameFilters().isEmpty())
3134 q->setNameFilters(options->nameFilters());
3135 q->selectNameFilter(options->initiallySelectedNameFilter());
3136 q->setDefaultSuffix(options->defaultSuffix());
3137 q->setHistory(options->history());
3138 const auto initiallySelectedFiles = options->initiallySelectedFiles();
3139 if (initiallySelectedFiles.size() == 1)
3140 q->selectFile(initiallySelectedFiles.first().fileName());
3141 for (
const QUrl &url : initiallySelectedFiles)
3143 lineEdit()->selectAll();
3145 retranslateStrings();
3146 q->resize(preSize.isValid() ? preSize : q->sizeHint());
3147 q->setWindowState(preState);
3150void QFileDialogPrivate::showHeader(QAction *action)
3153 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
3154 qFileDialogUi->treeView->header()->setSectionHidden(
int(actionGroup->actions().indexOf(action) + 1),
3155 !action->isChecked());
3158#if QT_CONFIG(proxymodel)
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
3172 if (!d->usingWidgets())
3174 if ((!proxyModel && !d->proxyModel)
3175 || (proxyModel == d->proxyModel))
3178 QModelIndex idx = d->rootIndex();
3180 QObjectPrivate::disconnect(d->proxyModel, &QAbstractProxyModel::rowsInserted,
3181 d, &QFileDialogPrivate::rowsInserted);
3183 QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsInserted,
3184 d, &QFileDialogPrivate::rowsInserted);
3186 if (proxyModel !=
nullptr) {
3187 proxyModel->setParent(
this);
3188 d->proxyModel = proxyModel;
3189 proxyModel->setSourceModel(d->model);
3190 d->qFileDialogUi->listView->setModel(d->proxyModel);
3191 d->qFileDialogUi->treeView->setModel(d->proxyModel);
3192#if QT_CONFIG(fscompleter)
3193 d->completer->setModel(d->proxyModel);
3194 d->completer->proxyModel = d->proxyModel;
3196 QObjectPrivate::connect(d->proxyModel, &QAbstractItemModel::rowsInserted,
3197 d, &QFileDialogPrivate::rowsInserted);
3199 d->proxyModel =
nullptr;
3200 d->qFileDialogUi->listView->setModel(d->model);
3201 d->qFileDialogUi->treeView->setModel(d->model);
3202#if QT_CONFIG(fscompleter)
3203 d->completer->setModel(d->model);
3204 d->completer->sourceModel = d->model;
3205 d->completer->proxyModel =
nullptr;
3207 QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted,
3208 d, &QFileDialogPrivate::rowsInserted);
3210 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
3211 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
3213 d->setRootIndex(idx);
3216 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
3217 QObjectPrivate::connect(selections, &QItemSelectionModel::selectionChanged,
3218 d, &QFileDialogPrivate::selectionChanged);
3219 QObjectPrivate::connect(selections, &QItemSelectionModel::currentChanged,
3220 d, &QFileDialogPrivate::currentChanged);
3224
3225
3226
3227
3228QAbstractProxyModel *QFileDialog::proxyModel()
const
3230 Q_D(
const QFileDialog);
3231 return d->proxyModel;
3236
3237
3238
3239
3240void QFileDialogPrivate::createToolButtons()
3243 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack,
nullptr, q));
3244 qFileDialogUi->backButton->setAutoRaise(
true);
3245 qFileDialogUi->backButton->setEnabled(
false);
3246 QObjectPrivate::connect(qFileDialogUi->backButton, &QPushButton::clicked,
3247 this, &QFileDialogPrivate::navigateBackward);
3249 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward,
nullptr, q));
3250 qFileDialogUi->forwardButton->setAutoRaise(
true);
3251 qFileDialogUi->forwardButton->setEnabled(
false);
3252 QObjectPrivate::connect(qFileDialogUi->forwardButton, &QPushButton::clicked,
3253 this, &QFileDialogPrivate::navigateForward);
3255 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent,
nullptr, q));
3256 qFileDialogUi->toParentButton->setAutoRaise(
true);
3257 qFileDialogUi->toParentButton->setEnabled(
false);
3258 QObjectPrivate::connect(qFileDialogUi->toParentButton, &QPushButton::clicked,
3259 this, &QFileDialogPrivate::navigateToParent);
3261 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView,
nullptr, q));
3262 qFileDialogUi->listModeButton->setAutoRaise(
true);
3263 qFileDialogUi->listModeButton->setDown(
true);
3264 QObjectPrivate::connect(qFileDialogUi->listModeButton, &QPushButton::clicked,
3265 this, &QFileDialogPrivate::showListView);
3267 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView,
nullptr, q));
3268 qFileDialogUi->detailModeButton->setAutoRaise(
true);
3269 QObjectPrivate::connect(qFileDialogUi->detailModeButton, &QPushButton::clicked,
3270 this, &QFileDialogPrivate::showDetailsView);
3272 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
3273 qFileDialogUi->backButton->setFixedSize(toolSize);
3274 qFileDialogUi->listModeButton->setFixedSize(toolSize);
3275 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
3276 qFileDialogUi->forwardButton->setFixedSize(toolSize);
3277 qFileDialogUi->toParentButton->setFixedSize(toolSize);
3279 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder,
nullptr, q));
3280 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
3281 qFileDialogUi->newFolderButton->setAutoRaise(
true);
3282 qFileDialogUi->newFolderButton->setEnabled(
false);
3283 QObjectPrivate::connect(qFileDialogUi->newFolderButton, &QPushButton::clicked,
3284 this, &QFileDialogPrivate::createDirectory);
3288
3289
3290
3291
3292void QFileDialogPrivate::createMenuActions()
3296 QAction *goHomeAction =
new QAction(q);
3297#ifndef QT_NO_SHORTCUT
3298 goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
3300 QObjectPrivate::connect(goHomeAction, &QAction::triggered,
3301 this, &QFileDialogPrivate::goHome);
3302 q->addAction(goHomeAction);
3306 QAction *goToParent =
new QAction(q);
3307 goToParent->setObjectName(
"qt_goto_parent_action"_L1);
3308#ifndef QT_NO_SHORTCUT
3309 goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
3311 QObjectPrivate::connect(goToParent, &QAction::triggered,
3312 this, &QFileDialogPrivate::navigateToParent);
3313 q->addAction(goToParent);
3315 renameAction =
new QAction(q);
3316 renameAction->setEnabled(
false);
3317 renameAction->setObjectName(
"qt_rename_action"_L1);
3318 QObjectPrivate::connect(renameAction, &QAction::triggered,
3319 this, &QFileDialogPrivate::renameCurrent);
3321 deleteAction =
new QAction(q);
3322 deleteAction->setEnabled(
false);
3323 deleteAction->setObjectName(
"qt_delete_action"_L1);
3324 QObjectPrivate::connect(deleteAction, &QAction::triggered,
3325 this, &QFileDialogPrivate::deleteCurrent);
3327 showHiddenAction =
new QAction(q);
3328 showHiddenAction->setObjectName(
"qt_show_hidden_action"_L1);
3329 showHiddenAction->setCheckable(
true);
3330 QObjectPrivate::connect(showHiddenAction, &QAction::triggered,
3331 this, &QFileDialogPrivate::showHidden);
3333 newFolderAction =
new QAction(q);
3334 newFolderAction->setObjectName(
"qt_new_folder_action"_L1);
3335 QObjectPrivate::connect(newFolderAction, &QAction::triggered,
3336 this, &QFileDialogPrivate::createDirectory);
3339void QFileDialogPrivate::goHome()
3342 q->setDirectory(QDir::homePath());
3346void QFileDialogPrivate::saveHistorySelection()
3348 if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
3350 auto &item = currentHistory[currentHistoryLocation];
3351 item.selection.clear();
3352 const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3353 for (
const auto &index : selectedIndexes)
3354 item.selection.append(QPersistentModelIndex(index));
3358
3359
3360
3361
3362void QFileDialogPrivate::pathChanged(
const QString &newPath)
3365 qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
3366 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
3367 q->setHistory(qFileDialogUi->lookInCombo->history());
3369 const QString newNativePath = QDir::toNativeSeparators(newPath);
3372 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
3373 if (currentHistoryLocation >= 0)
3374 saveHistorySelection();
3375 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
3376 currentHistory.removeLast();
3378 currentHistory.append({newNativePath, PersistentModelIndexList()});
3379 ++currentHistoryLocation;
3381 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
3382 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
3385void QFileDialogPrivate::navigate(HistoryItem &historyItem)
3388 q->setDirectory(historyItem.path);
3390 if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
3392 if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
3393 [](
const QPersistentModelIndex &i) {
return !i.isValid(); })) {
3394 historyItem.selection.clear();
3398 QAbstractItemView *view = q->viewMode() == QFileDialog::List
3399 ?
static_cast<QAbstractItemView *>(qFileDialogUi->listView)
3400 :
static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
3401 auto selectionModel = view->selectionModel();
3402 const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
3403 | QItemSelectionModel::Rows;
3404 selectionModel->select(historyItem.selection.constFirst(),
3405 flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);
3406 auto it = historyItem.selection.cbegin() + 1;
3407 const auto end = historyItem.selection.cend();
3408 for (; it != end; ++it)
3409 selectionModel->select(*it, flags);
3411 view->scrollTo(historyItem.selection.constFirst());
3415
3416
3417
3418
3419void QFileDialogPrivate::navigateBackward()
3421 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
3422 saveHistorySelection();
3423 navigate(currentHistory[--currentHistoryLocation]);
3428
3429
3430
3431
3432void QFileDialogPrivate::navigateForward()
3434 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
3435 saveHistorySelection();
3436 navigate(currentHistory[++currentHistoryLocation]);
3441
3442
3443
3444
3445
3446void QFileDialogPrivate::navigateToParent()
3449 QDir dir(model->rootDirectory());
3450 QString newDirectory;
3452 newDirectory = model->myComputer().toString();
3455 newDirectory = dir.absolutePath();
3457 q->setDirectory(newDirectory);
3458 emit q->directoryEntered(newDirectory);
3462
3463
3464
3465
3466void QFileDialogPrivate::createDirectory()
3469 qFileDialogUi->listView->clearSelection();
3471 QString newFolderString = QFileDialog::tr(
"New Folder");
3472 QString folderName = newFolderString;
3473 QString prefix = q->directory().absolutePath() + QDir::separator();
3474 if (QFile::exists(prefix + folderName)) {
3475 qlonglong suffix = 2;
3476 while (QFile::exists(prefix + folderName)) {
3477 folderName = newFolderString + QString::number(suffix++);
3481 QModelIndex parent = rootIndex();
3482 QModelIndex index = model->mkdir(parent, folderName);
3483 if (!index.isValid())
3486 index = select(index);
3487 if (index.isValid()) {
3488 qFileDialogUi->treeView->setCurrentIndex(index);
3489 currentView()->edit(index);
3493void QFileDialogPrivate::showListView()
3495 qFileDialogUi->listModeButton->setDown(
true);
3496 qFileDialogUi->detailModeButton->setDown(
false);
3497 qFileDialogUi->treeView->hide();
3498 qFileDialogUi->listView->show();
3499 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
3500 qFileDialogUi->listView->doItemsLayout();
3503void QFileDialogPrivate::showDetailsView()
3505 qFileDialogUi->listModeButton->setDown(
false);
3506 qFileDialogUi->detailModeButton->setDown(
true);
3507 qFileDialogUi->listView->hide();
3508 qFileDialogUi->treeView->show();
3509 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
3510 qFileDialogUi->treeView->doItemsLayout();
3514
3515
3516
3517
3518void QFileDialogPrivate::showContextMenu(
const QPoint &position)
3524 QAbstractItemView *view =
nullptr;
3525 if (q->viewMode() == QFileDialog::Detail)
3526 view = qFileDialogUi->treeView;
3528 view = qFileDialogUi->listView;
3529 QModelIndex index = view->indexAt(position);
3530 index = mapToSource(index.sibling(index.row(), 0));
3532 QMenu *menu =
new QMenu(view);
3533 menu->setAttribute(Qt::WA_DeleteOnClose);
3535 if (index.isValid()) {
3537 const bool ro = model && model->isReadOnly();
3538 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3539 renameAction->setEnabled(!ro && p & QFile::WriteUser);
3540 menu->addAction(renameAction);
3541 deleteAction->setEnabled(!ro && p & QFile::WriteUser);
3542 menu->addAction(deleteAction);
3543 menu->addSeparator();
3545 menu->addAction(showHiddenAction);
3546 if (qFileDialogUi->newFolderButton->isVisible()) {
3547 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
3548 menu->addAction(newFolderAction);
3550 menu->popup(view->viewport()->mapToGlobal(position));
3556
3557
3558void QFileDialogPrivate::renameCurrent()
3561 QModelIndex index = qFileDialogUi->listView->currentIndex();
3562 index = index.sibling(index.row(), 0);
3563 if (q->viewMode() == QFileDialog::List)
3564 qFileDialogUi->listView->edit(index);
3566 qFileDialogUi->treeView->edit(index);
3569bool QFileDialogPrivate::removeDirectory(
const QString &path)
3571 QModelIndex modelIndex = model->index(path);
3572 return model->remove(modelIndex);
3576
3577
3578
3579
3580void QFileDialogPrivate::deleteCurrent()
3582 if (model->isReadOnly())
3585 const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
3586 for (
auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
3587 QPersistentModelIndex index = *it;
3588 if (index == qFileDialogUi->listView->rootIndex())
3591 index = mapToSource(index.sibling(index.row(), 0));
3592 if (!index.isValid())
3595 QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
3596 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
3598 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3599#if QT_CONFIG(messagebox)
3601 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3602 QFileDialog::tr(
"'%1' is write protected.\nDo you want to delete it anyway?")
3604 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
3606 else if (QMessageBox::warning(q_func(), QFileDialog::tr(
"Delete"),
3607 QFileDialog::tr(
"Are you sure you want to delete '%1'?")
3609 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
3613 if (!index.isValid())
3617 if (!(p & QFile::WriteUser))
3621 if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
3622 if (!removeDirectory(filePath)) {
3623#if QT_CONFIG(messagebox)
3624 QMessageBox::warning(q, q->windowTitle(),
3625 QFileDialog::tr(
"Could not delete directory."));
3629 model->remove(index);
3634void QFileDialogPrivate::autoCompleteFileName(
const QString &text)
3636 if (text.startsWith(
"//"_L1) || text.startsWith(u'\\')) {
3637 qFileDialogUi->listView->selectionModel()->clearSelection();
3641 const QStringList multipleFiles = typedFiles();
3642 if (multipleFiles.size() > 0) {
3643 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
3644 QList<QModelIndex> newFiles;
3645 for (
const auto &file : multipleFiles) {
3646 QModelIndex idx = model->index(file);
3647 if (oldFiles.removeAll(idx) == 0)
3648 newFiles.append(idx);
3650 for (
const auto &newFile : std::as_const(newFiles))
3652 if (lineEdit()->hasFocus()) {
3653 auto *sm = qFileDialogUi->listView->selectionModel();
3654 for (
const auto &oldFile : std::as_const(oldFiles))
3655 sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
3661
3662
3663void QFileDialogPrivate::updateOkButton()
3666 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
3667 ? QDialogButtonBox::Open : QDialogButtonBox::Save);
3670 const QFileDialog::FileMode fileMode = q->fileMode();
3672 bool enableButton =
true;
3673 bool isOpenDirectory =
false;
3675 const QStringList files = q->selectedFiles();
3676 QString lineEditText = lineEdit()->text();
3678 if (lineEditText.startsWith(
"//"_L1) || lineEditText.startsWith(u'\\')) {
3679 button->setEnabled(
true);
3680 updateOkButtonText();
3684 if (files.isEmpty()) {
3685 enableButton =
false;
3686 }
else if (lineEditText ==
".."_L1) {
3687 isOpenDirectory =
true;
3690 case QFileDialog::Directory: {
3691 QString fn = files.first();
3692 QModelIndex idx = model->index(fn);
3694 idx = model->index(getEnvironmentVariable(fn));
3695 if (!idx.isValid() || !model->isDir(idx))
3696 enableButton =
false;
3699 case QFileDialog::AnyFile: {
3700 QString fn = files.first();
3702 QModelIndex idx = model->index(fn);
3706 fileDir = info.canonicalFilePath();
3708 fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
3709 fileName = fn.mid(fileDir.size() + 1);
3711 if (lineEditText.contains(
".."_L1)) {
3712 fileDir = info.canonicalFilePath();
3713 fileName = info.fileName();
3716 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
3717 enableButton =
false;
3720 if (idx.isValid() && model->isDir(idx)) {
3721 isOpenDirectory =
true;
3722 enableButton =
true;
3725 if (!idx.isValid()) {
3726 const long maxLength = maxNameLength(fileDir);
3727 enableButton = maxLength < 0 || fileName.size() <= maxLength;
3731 case QFileDialog::ExistingFile:
3732 case QFileDialog::ExistingFiles:
3733 for (
const auto &file : files) {
3734 QModelIndex idx = model->index(file);
3736 idx = model->index(getEnvironmentVariable(file));
3737 if (!idx.isValid()) {
3738 enableButton =
false;
3741 if (idx.isValid() && model->isDir(idx)) {
3742 isOpenDirectory =
true;
3752 button->setEnabled(enableButton);
3753 updateOkButtonText(isOpenDirectory);
3757
3758
3759void QFileDialogPrivate::currentChanged(
const QModelIndex &index)
3762 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
3766
3767
3768
3769
3770
3771void QFileDialogPrivate::enterDirectory(
const QModelIndex &index)
3775 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
3776 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
3777 if (path.isEmpty() || model->isDir(sourceIndex)) {
3778 if (q->directory().path() == path)
3781 const QFileDialog::FileMode fileMode = q->fileMode();
3782 q->setDirectory(path);
3783 emit q->directoryEntered(path);
3784 if (fileMode == QFileDialog::Directory) {
3786 lineEdit()->setText(QString());
3787 lineEdit()->clear();
3791 if ((!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick,
nullptr, qFileDialogUi->treeView)
3792 || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL))
3793 && index.model()->flags(index) & Qt::ItemIsEnabled) {
3800
3801
3802
3803
3804
3805void QFileDialogPrivate::goToDirectory(
const QString &path)
3807 enum { UrlRole = Qt::UserRole + 1 };
3809 #if QT_CONFIG(messagebox)
3812 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
3813 qFileDialogUi->lookInCombo->modelColumn(),
3814 qFileDialogUi->lookInCombo->rootModelIndex());
3815 QString path2 = path;
3816 if (!index.isValid())
3817 index = mapFromSource(model->index(getEnvironmentVariable(path)));
3819 path2 = index.data(UrlRole).toUrl().toLocalFile();
3820 index = mapFromSource(model->index(path2));
3824 dir.setPath(getEnvironmentVariable(path2));
3826 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
3827 enterDirectory(index);
3828#if QT_CONFIG(messagebox)
3830 QString message = QFileDialog::tr(
"%1\nDirectory not found.\nPlease verify the "
3831 "correct directory name was given.");
3832 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
3838
3839
3840
3841
3842
3843void QFileDialogPrivate::useNameFilter(
int index)
3845 QStringList nameFilters = options->nameFilters();
3846 if (index == nameFilters.size()) {
3847 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3848 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3849 options->setNameFilters(nameFilters);
3852 QString nameFilter = nameFilters.at(index);
3853 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3854 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3855 QString newNameFilterExtension;
3856 if (newNameFilters.size() > 0)
3857 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3859 QString fileName = lineEdit()->text();
3860 const QString fileNameExtension = QFileInfo(fileName).suffix();
3861 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3862 const qsizetype fileNameExtensionLength = fileNameExtension.size();
3863 fileName.replace(fileName.size() - fileNameExtensionLength,
3864 fileNameExtensionLength, newNameFilterExtension);
3865 qFileDialogUi->listView->clearSelection();
3866 lineEdit()->setText(fileName);
3870 model->setNameFilters(newNameFilters);
3874
3875
3876
3877
3878
3879void QFileDialogPrivate::selectionChanged()
3881 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3882 const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3883 bool stripDirs = fileMode != QFileDialog::Directory;
3885 QStringList allFiles;
3886 for (
const auto &index : indexes) {
3887 if (stripDirs && model->isDir(mapToSource(index)))
3889 allFiles.append(index.data().toString());
3891 if (allFiles.size() > 1)
3892 for (qsizetype i = 0; i < allFiles.size(); ++i) {
3893 allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
3896 QString finalFiles = allFiles.join(u' ');
3897 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3898 lineEdit()->setText(finalFiles);
3904
3905
3906
3907
3908void QFileDialogPrivate::showHidden()
3911 QDir::Filters dirFilters = q->filter();
3912 dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
3913 q->setFilter(dirFilters);
3917
3918
3919
3920
3921
3922void QFileDialogPrivate::rowsInserted(
const QModelIndex &parent)
3924 if (!qFileDialogUi->treeView
3925 || parent != qFileDialogUi->treeView->rootIndex()
3926 || !qFileDialogUi->treeView->selectionModel()
3927 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3928 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3932void QFileDialogPrivate::fileRenamed(
const QString &path,
const QString &oldName,
const QString &newName)
3934 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3935 if (fileMode == QFileDialog::Directory) {
3936 if (path == rootPath() && lineEdit()->text() == oldName)
3937 lineEdit()->setText(newName);
3941void QFileDialogPrivate::emitUrlSelected(
const QUrl &file)
3944 emit q->urlSelected(file);
3945 if (file.isLocalFile())
3946 emit q->fileSelected(file.toLocalFile());
3949void QFileDialogPrivate::emitUrlsSelected(
const QList<QUrl> &files)
3952 emit q->urlsSelected(files);
3953 QStringList localFiles;
3954 for (
const QUrl &file : files)
3955 if (file.isLocalFile())
3956 localFiles.append(file.toLocalFile());
3957 if (!localFiles.isEmpty())
3958 emit q->filesSelected(localFiles);
3961void QFileDialogPrivate::nativeCurrentChanged(
const QUrl &file)
3964 emit q->currentUrlChanged(file);
3965 if (file.isLocalFile())
3966 emit q->currentChanged(file.toLocalFile());
3969void QFileDialogPrivate::nativeEnterDirectory(
const QUrl &directory)
3972 emit q->directoryUrlEntered(directory);
3973 if (!directory.isEmpty()) {
3974 *lastVisitedDir() = directory;
3975 if (directory.isLocalFile())
3976 emit q->directoryEntered(directory.toLocalFile());
3981
3982
3983
3984
3985
3986
3987bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
3989#if QT_CONFIG(shortcut)
3991 if (event->matches(QKeySequence::Cancel)) {
3996 switch (event->key()) {
3997 case Qt::Key_Backspace:
4001#ifdef QT_KEYPAD_NAVIGATION
4002 if (QApplicationPrivate::keypadNavigationEnabled())
4006 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
4017QString QFileDialogPrivate::getEnvironmentVariable(
const QString &string)
4020 if (string.size() > 1 && string.startsWith(u'$')) {
4021 return qEnvironmentVariable(QStringView{string}.mid(1).toLatin1().constData());
4024 if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
4025 return qEnvironmentVariable(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData());
4033 urlModel =
new QUrlModel(
this);
4034 urlModel->showFullPath =
true;
4035 urlModel->setFileSystemModel(d_ptr->model);
4041 if (model()->rowCount() > 1)
4042 QComboBox::showPopup();
4044 urlModel->setUrls(QList<QUrl>());
4046 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
4047 while (idx.isValid()) {
4048 QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
4054 list.append(QUrl(
"file:"_L1));
4055 urlModel->addUrls(list, 0);
4056 idx = model()->index(model()->rowCount() - 1, 0);
4060 for (
int i = 0; i < m_history.size(); ++i) {
4061 QUrl path = QUrl::fromLocalFile(m_history.at(i));
4062 if (!urls.contains(path))
4065 if (urls.size() > 0) {
4066 model()->insertRow(model()->rowCount());
4067 idx = model()->index(model()->rowCount()-1, 0);
4069 model()->setData(idx, QFileDialog::tr(
"Recent Places"));
4070 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
4072 Qt::ItemFlags flags = m->flags(idx);
4073 flags &= ~Qt::ItemIsEnabled;
4074 m->item(idx.row(), idx.column())->setFlags(flags);
4076 urlModel->addUrls(urls, -1,
false);
4080 QComboBox::showPopup();
4086 QStylePainter painter(
this);
4087 painter.setPen(palette().color(QPalette::Text));
4090 QStyleOptionComboBox opt;
4091 initStyleOption(&opt);
4093 QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
4094 QStyle::SC_ComboBoxEditField,
this);
4095 int size = editRect.width() - opt.iconSize.width() - 4;
4096 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
4097 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
4100 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
4106 setSelectionBehavior(QAbstractItemView::SelectRows);
4108 setResizeMode(QListView::Adjust);
4109 setEditTriggers(QAbstractItemView::EditKeyPressed);
4110 setContextMenuPolicy(Qt::CustomContextMenu);
4111#if QT_CONFIG(draganddrop)
4112 setDragDropMode(QAbstractItemView::InternalMove);
4118 int height = qMax(10, sizeHintForRow(0));
4119 return QSize(QListView::sizeHint().width() * 2, height * 30);
4124#ifdef QT_KEYPAD_NAVIGATION
4125 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4126 QListView::keyPressEvent(e);
4131 if (!d_ptr->itemViewKeyboardEvent(e))
4132 QListView::keyPressEvent(e);
4139 setSelectionBehavior(QAbstractItemView::SelectRows);
4140 setRootIsDecorated(
false);
4141 setItemsExpandable(
false);
4142 setSortingEnabled(
true);
4143 header()->setSortIndicator(0, Qt::AscendingOrder);
4144 header()->setStretchLastSection(
false);
4145 setTextElideMode(Qt::ElideMiddle);
4146 setEditTriggers(QAbstractItemView::EditKeyPressed);
4147 setContextMenuPolicy(Qt::CustomContextMenu);
4148#if QT_CONFIG(draganddrop)
4149 setDragDropMode(QAbstractItemView::InternalMove);
4155#ifdef QT_KEYPAD_NAVIGATION
4156 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4157 QTreeView::keyPressEvent(e);
4162 if (!d_ptr->itemViewKeyboardEvent(e))
4163 QTreeView::keyPressEvent(e);
4169 int height = qMax(10, sizeHintForRow(0));
4170 QSize sizeHint = header()->sizeHint();
4171 return QSize(sizeHint.width() * 4, height * 30);
4175
4176
4177
4178
4181
4182
4183
4186#ifdef QT_KEYPAD_NAVIGATION
4187 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4188 QLineEdit::keyPressEvent(e);
4193#if QT_CONFIG(shortcut)
4196 QLineEdit::keyPressEvent(e);
4197#if QT_CONFIG(shortcut)
4198 if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
4203#if QT_CONFIG(fscompleter)
4205QString QFSCompleter::pathFromIndex(
const QModelIndex &index)
const
4207 const QFileSystemModel *dirModel;
4209 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4211 dirModel = sourceModel;
4212 QString currentLocation = dirModel->rootPath();
4213 QString path = index.data(QFileSystemModel::FilePathRole).toString();
4214 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
4215#if defined(Q_OS_UNIX)
4216 if (currentLocation == QDir::separator())
4217 return path.remove(0, currentLocation.size());
4219 if (currentLocation.endsWith(u'/'))
4220 return path.remove(0, currentLocation.size());
4222 return path.remove(0, currentLocation.size()+1);
4224 return index.data(QFileSystemModel::FilePathRole).toString();
4227QStringList QFSCompleter::splitPath(
const QString &path)
const
4230 return QStringList(completionPrefix());
4232 QString pathCopy = QDir::toNativeSeparators(path);
4233 QChar sep = QDir::separator();
4234#if defined(Q_OS_WIN)
4235 if (pathCopy ==
"\\"_L1 || pathCopy ==
"\\\\"_L1)
4236 return QStringList(pathCopy);
4237 QString doubleSlash(
"\\\\"_L1);
4238 if (pathCopy.startsWith(doubleSlash))
4239 pathCopy = pathCopy.mid(2);
4241 doubleSlash.clear();
4242#elif defined(Q_OS_UNIX)
4244 QString tildeExpanded = qt_tildeExpansion(pathCopy);
4245 if (tildeExpanded != pathCopy) {
4246 QFileSystemModel *dirModel;
4248 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
4250 dirModel = sourceModel;
4251 dirModel->fetchMore(dirModel->index(tildeExpanded));
4253 pathCopy = std::move(tildeExpanded);
4257#if defined(Q_OS_WIN)
4258 QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
4259 if (!doubleSlash.isEmpty() && !parts.isEmpty())
4260 parts[0].prepend(doubleSlash);
4261 if (pathCopy.endsWith(sep))
4262 parts.append(QString());
4264 QStringList parts = pathCopy.split(sep);
4265 if (pathCopy[0] == sep)
4269#if defined(Q_OS_WIN)
4270 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
4272 bool startsFromRoot = pathCopy[0] == sep;
4274 if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
4275 const QFileSystemModel *dirModel;
4277 dirModel = qobject_cast<
const QFileSystemModel *>(proxyModel->sourceModel());
4279 dirModel = sourceModel;
4280 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
4281#if defined(Q_OS_WIN)
4282 if (currentLocation.endsWith(u':'))
4283 currentLocation.append(sep);
4285 if (currentLocation.contains(sep) && path != currentLocation) {
4286 QStringList currentLocationList = splitPath(currentLocation);
4287 while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) ==
".."_L1) {
4288 parts.removeFirst();
4289 currentLocationList.removeLast();
4291 if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
4292 currentLocationList.removeLast();
4293 return currentLocationList + parts;
4304#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={})