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