Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qfiledialog.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#define QT_NO_URL_CAST_FROM_STRING
5
6#include <qvariant.h>
7#include <private/qwidgetitemdata_p.h>
8#include "qfiledialog.h"
9
10#include "qfiledialog_p.h"
11#include <private/qapplication_p.h>
12#include <private/qguiapplication_p.h>
13#include <qfontmetrics.h>
14#include <qaction.h>
15#include <qactiongroup.h>
16#include <qheaderview.h>
17#if QT_CONFIG(shortcut)
18# include <qshortcut.h>
19#endif
20#include <qgridlayout.h>
21#if QT_CONFIG(menu)
22#include <qmenu.h>
23#endif
24#if QT_CONFIG(messagebox)
25#include <qmessagebox.h>
26#endif
27#include <stdlib.h>
28#if QT_CONFIG(settings)
29#include <qsettings.h>
30#endif
31#include <qdebug.h>
32#if QT_CONFIG(mimetype)
33#include <qmimedatabase.h>
34#endif
35#if QT_CONFIG(regularexpression)
36#include <qregularexpression.h>
37#endif
38#include <qapplication.h>
39#include <qstylepainter.h>
40#include "ui_qfiledialog.h"
41#if defined(Q_OS_UNIX)
42#include <pwd.h>
43#include <unistd.h> // for pathconf() on OS X
44#elif defined(Q_OS_WIN)
45# include <QtCore/qt_windows.h>
46#endif
47#if defined(Q_OS_WASM)
48#include <private/qwasmlocalfileaccess_p.h>
49#endif
50
51#include <algorithm>
52
54
55using namespace Qt::StringLiterals;
56
57Q_GLOBAL_STATIC(QUrl, lastVisitedDir)
58
59
311#include <QMetaEnum>
312#if QT_CONFIG(shortcut)
313# include <qshortcut.h>
314#endif
316
324{
325 Q_D(QFileDialog);
327 d->init(args);
328}
329
338 const QString &caption,
339 const QString &directory,
340 const QString &filter)
341 : QDialog(*new QFileDialogPrivate, parent, { })
342{
343 Q_D(QFileDialog);
345 args.filter = filter;
346 args.caption = caption;
347 d->init(args);
348}
349
355{
356 Q_D(QFileDialog);
357 d->init(args);
358 setFileMode(args.mode);
359 setOptions(args.options);
360 selectFile(args.selection);
361}
362
367{
368#if QT_CONFIG(settings)
369 Q_D(QFileDialog);
370 d->saveSettings();
371#endif
372}
373
389{
390 Q_D(QFileDialog);
391 if (!d->nativeDialogInUse)
392 d->qFileDialogUi->sidebar->setUrls(urls);
393}
394
400{
401 Q_D(const QFileDialog);
402 return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
403}
404
405static const qint32 QFileDialogMagic = 0xbe;
406
415{
416 Q_D(const QFileDialog);
417 int version = 4;
420 stream.setVersion(QDataStream::Qt_5_0);
421
423 stream << qint32(version);
424 if (d->usingWidgets()) {
425 stream << d->qFileDialogUi->splitter->saveState();
426 stream << d->qFileDialogUi->sidebar->urls();
427 } else {
428 stream << d->splitterState;
429 stream << d->sidebarUrls;
430 }
431 stream << history();
432 stream << *lastVisitedDir();
433 if (d->usingWidgets())
434 stream << d->qFileDialogUi->treeView->header()->saveState();
435 else
436 stream << d->headerData;
437 stream << qint32(viewMode());
438 return data;
439}
440
451{
452 Q_D(QFileDialog);
453 QByteArray sd = state;
455 stream.setVersion(QDataStream::Qt_5_0);
456 if (stream.atEnd())
457 return false;
459 QUrl currentDirectory;
461 qint32 v;
463 stream >> marker;
464 stream >> v;
465 // the code below only supports versions 3 and 4
466 if (marker != QFileDialogMagic || (v != 3 && v != 4))
467 return false;
468
469 stream >> d->splitterState
470 >> d->sidebarUrls
471 >> history;
472 if (v == 3) {
473 QString currentDirectoryString;
474 stream >> currentDirectoryString;
475 currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
476 } else {
477 stream >> currentDirectory;
478 }
479 stream >> d->headerData
480 >> viewMode;
481
482 setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
484
485 if (!d->usingWidgets())
486 return true;
487
488 return d->restoreWidgetState(history, -1);
489}
490
495{
496 Q_D(QFileDialog);
497 if (e->type() == QEvent::LanguageChange) {
498 d->retranslateWindowTitle();
499 d->retranslateStrings();
500 }
502}
503
505 :
506#if QT_CONFIG(proxymodel)
507 proxyModel(nullptr),
508#endif
509 model(nullptr),
510 currentHistoryLocation(-1),
511 renameAction(nullptr),
512 deleteAction(nullptr),
513 showHiddenAction(nullptr),
514 useDefaultCaption(true),
515 qFileDialogUi(nullptr),
516 options(QFileDialogOptions::create())
517{
518}
519
521{
522}
523
525{
526 QFileDialog *d = q_func();
531 QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
532 static_cast<QPlatformFileDialogHelper *>(h)->setOptions(options);
533}
534
536{
537 Q_Q(QFileDialog);
538 options->setWindowTitle(q->windowTitle());
539 options->setHistory(q->history());
540 if (usingWidgets())
541 options->setSidebarUrls(qFileDialogUi->sidebar->urls());
543 options->setInitiallySelectedNameFilter(q->selectedNameFilter());
546}
547
549{
550 if (code == QDialog::Accepted) {
551 Q_Q(QFileDialog);
552 q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
553 q->setSidebarUrls(options->sidebarUrls());
554 q->setHistory(options->history());
555 }
556}
557
559{
560 Q_Q(QFileDialog);
561 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
562 return;
563 if (q->acceptMode() == QFileDialog::AcceptOpen) {
564 const QFileDialog::FileMode fileMode = q->fileMode();
565 if (fileMode == QFileDialog::Directory)
566 q->setWindowTitle(QFileDialog::tr("Find Directory"));
567 else
568 q->setWindowTitle(QFileDialog::tr("Open"));
569 } else
570 q->setWindowTitle(QFileDialog::tr("Save As"));
571
572 setWindowTitle = q->windowTitle();
573}
574
576{
577 *lastVisitedDir() = dir;
578}
579
581{
584}
585
587{
590 } else {
591 switch (q_func()->fileMode()) {
593 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("Directory:"));
594 break;
595 default:
596 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("File &name:"));
597 break;
598 }
599 }
600}
601
603{
606}
607
609{
610 Q_Q(QFileDialog);
611 // 'Save as' at a folder: Temporarily change to "Open".
612 if (saveAsOnFolder) {
613 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Open"));
616 return;
617 } else {
618 switch (q->fileMode()) {
620 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Choose"));
621 break;
622 default:
624 q->acceptMode() == QFileDialog::AcceptOpen ?
625 QFileDialog::tr("&Open") :
626 QFileDialog::tr("&Save"));
627 break;
628 }
629 }
630}
631
633{
636}
637
639{
640 Q_Q(QFileDialog);
641 /* WIDGETS */
644 if (!usingWidgets())
645 return;
646
647 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
648 QAbstractItemModel *abstractModel = model;
649#if QT_CONFIG(proxymodel)
650 if (proxyModel)
651 abstractModel = proxyModel;
652#endif
653 const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
654 for (int i = 1; i < total; ++i) {
655 actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
656 }
657
658 /* MENU ACTIONS */
659 renameAction->setText(QFileDialog::tr("&Rename"));
660 deleteAction->setText(QFileDialog::tr("&Delete"));
661 showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
662 newFolderAction->setText(QFileDialog::tr("&New Folder"));
663 qFileDialogUi->retranslateUi(q);
668}
669
671{
672 Q_Q(QFileDialog);
673 emit q->filesSelected(files);
674 if (files.size() == 1)
675 emit q->fileSelected(files.first());
676}
677
679{
680 // Don't use Q_Q here! This function is called from ~QDialog,
681 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
682 const QDialog * const q = static_cast<const QDialog*>(q_ptr);
684 return true;
686 || q->testAttribute(Qt::WA_DontShowOnScreen)
688 return false;
689 }
690
691 return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
692}
693
695{
697}
698
717{
718 const QFileDialog::Options previousOptions = options();
719 if (!(previousOptions & option) != !on)
720 setOptions(previousOptions ^ option);
721}
722
732{
733 Q_D(const QFileDialog);
734 return d->options->testOption(static_cast<QFileDialogOptions::FileDialogOption>(option));
735}
736
757{
758 Q_D(QFileDialog);
759
760 Options changed = (options ^ QFileDialog::options());
761 if (!changed)
762 return;
763
764 d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));
765
767 d->nativeDialogInUse = false;
768 d->createWidgets();
769 }
770
771 if (d->usingWidgets()) {
772 if (changed & DontResolveSymlinks)
773 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
774 if (changed & ReadOnly) {
775 bool ro = (options & ReadOnly);
776 d->model->setReadOnly(ro);
777 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
778 d->renameAction->setEnabled(!ro);
779 d->deleteAction->setEnabled(!ro);
780 }
781
782 if (changed & DontUseCustomDirectoryIcons) {
783 QFileIconProvider::Options providerOptions = iconProvider()->options();
786 iconProvider()->setOptions(providerOptions);
787 }
788 }
789
790 if (changed & HideNameFilterDetails)
791 setNameFilters(d->options->nameFilters());
792
793 if (changed & ShowDirsOnly)
795}
796
797QFileDialog::Options QFileDialog::options() const
798{
799 Q_D(const QFileDialog);
804 static_assert((int)QFileDialog::ReadOnly == (int)QFileDialogOptions::ReadOnly);
807 return QFileDialog::Options(int(d->options->options()));
808}
809
819void QFileDialog::open(QObject *receiver, const char *member)
820{
821 Q_D(QFileDialog);
824 connect(this, signal, receiver, member);
825 d->signalToDisconnectOnClose = signal;
826 d->receiverToDisconnectOnClose = receiver;
827 d->memberToDisconnectOnClose = member;
828
830}
831
832
836void QFileDialog::setVisible(bool visible)
837{
838 Q_D(QFileDialog);
839 if (visible){
841 return;
843 return;
844
845 if (d->canBeNativeDialog()){
846 if (d->setNativeDialogVisible(visible)){
847 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
848 // updates the state correctly, but skips showing the non-native version:
850#if QT_CONFIG(fscompleter)
851 // So the completer doesn't try to complete and therefore show a popup
852 if (!d->nativeDialogInUse)
853 d->completer->setModel(nullptr);
854#endif
855 } else {
856 d->createWidgets();
858#if QT_CONFIG(fscompleter)
859 if (!d->nativeDialogInUse) {
860 if (d->proxyModel != nullptr)
861 d->completer->setModel(d->proxyModel);
862 else
863 d->completer->setModel(d->model);
864 }
865#endif
866 }
867 }
868
869 if (visible && d->usingWidgets())
870 d->qFileDialogUi->fileNameEdit->setFocus();
871
873}
874
880{
881 //The shortcut in the side bar may have a parent that is not fetched yet (e.g. an hidden file)
882 //so we force the fetching
883 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(), true);
884 QModelIndex idx = model->d_func()->index(node);
886}
887
907{
908 Q_D(QFileDialog);
909 QString newDirectory = directory;
910 //we remove .. and . from the given path if exist
911 if (!directory.isEmpty())
912 newDirectory = QDir::cleanPath(directory);
913
914 if (!directory.isEmpty() && newDirectory.isEmpty())
915 return;
916
917 QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
919
920 d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
921 if (!d->usingWidgets()) {
922 d->setDirectory_sys(newDirUrl);
923 return;
924 }
925 if (d->rootPath() == newDirectory)
926 return;
927 QModelIndex root = d->model->setRootPath(newDirectory);
928 if (!d->nativeDialogInUse) {
929 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
930 if (root != d->rootIndex()) {
931#if QT_CONFIG(fscompleter)
932 if (directory.endsWith(u'/'))
933 d->completer->setCompletionPrefix(newDirectory);
934 else
935 d->completer->setCompletionPrefix(newDirectory + u'/');
936#endif
937 d->setRootIndex(root);
938 }
939 d->qFileDialogUi->listView->selectionModel()->clear();
940 }
941}
942
947{
948 Q_D(const QFileDialog);
949 if (d->nativeDialogInUse) {
950 QString dir = d->directory_sys().toLocalFile();
951 return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
952 }
953 return d->rootPath();
954}
955
974{
975 Q_D(QFileDialog);
976 if (!directory.isValid())
977 return;
978
980 d->options->setInitialDirectory(directory);
981
982 if (d->nativeDialogInUse)
983 d->setDirectory_sys(directory);
984 else if (directory.isLocalFile())
985 setDirectory(directory.toLocalFile());
986 else if (Q_UNLIKELY(d->usingWidgets()))
987 qWarning("Non-native QFileDialog supports only local files");
988}
989
996{
997 Q_D(const QFileDialog);
998 if (d->nativeDialogInUse)
999 return d->directory_sys();
1000 else
1002}
1003
1004// FIXME Qt 5.4: Use upcoming QVolumeInfo class to determine this information?
1005static inline bool isCaseSensitiveFileSystem(const QString &path)
1006{
1007 Q_UNUSED(path);
1008#if defined(Q_OS_WIN)
1009 // Return case insensitive unconditionally, even if someone has a case sensitive
1010 // file system mounted, wrongly capitalized drive letters will cause mismatches.
1011 return false;
1012#elif defined(Q_OS_MACOS)
1013 return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE);
1014#else
1015 return true;
1016#endif
1017}
1018
1019// Determine the file name to be set on the line edit from the path
1020// passed to selectFile() in mode QFileDialog::AcceptSave.
1021static inline QString fileFromPath(const QString &rootPath, QString path)
1022{
1023 if (!QFileInfo(path).isAbsolute())
1024 return path;
1025 if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
1026 path.remove(0, rootPath.size());
1027
1028 if (path.isEmpty())
1029 return path;
1030
1031 if (path.at(0) == QDir::separator()
1032#ifdef Q_OS_WIN
1033 //On Windows both cases can happen
1034 || path.at(0) == u'/'
1035#endif
1036 ) {
1037 path.remove(0, 1);
1038 }
1039 return path;
1040}
1041
1048{
1049 Q_D(QFileDialog);
1050 if (filename.isEmpty())
1051 return;
1052
1053 if (!d->usingWidgets()) {
1054 QUrl url;
1055 if (QFileInfo(filename).isRelative()) {
1056 url = d->options->initialDirectory();
1057 QString path = url.path();
1058 if (!path.endsWith(u'/'))
1059 path += u'/';
1060 url.setPath(path + filename);
1061 } else {
1062 url = QUrl::fromLocalFile(filename);
1063 }
1064 d->selectFile_sys(url);
1065 d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
1066 return;
1067 }
1068
1069 if (!QDir::isRelativePath(filename)) {
1070 QFileInfo info(filename);
1071 QString filenamePath = info.absoluteDir().path();
1072
1073 if (d->model->rootPath() != filenamePath)
1074 setDirectory(filenamePath);
1075 }
1076
1077 QModelIndex index = d->model->index(filename);
1078 d->qFileDialogUi->listView->selectionModel()->clear();
1079 if (!isVisible() || !d->lineEdit()->hasFocus())
1080 d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
1081}
1082
1092{
1093 Q_D(QFileDialog);
1094 if (!url.isValid())
1095 return;
1096
1097 if (d->nativeDialogInUse)
1098 d->selectFile_sys(url);
1099 else if (url.isLocalFile())
1101 else
1102 qWarning("Non-native QFileDialog supports only local files");
1103}
1104
1105#ifdef Q_OS_UNIX
1106static QString homeDirFromPasswdEntry(const QString &path, const QByteArray &userName)
1107{
1108#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1109 passwd pw;
1110 passwd *tmpPw;
1111 long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
1112 if (bufSize == -1)
1113 bufSize = 1024;
1115 int err = 0;
1116# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
1117 tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());
1118# else
1119 err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);
1120# endif
1121 if (err || !tmpPw)
1122 return path;
1123 return QFile::decodeName(pw.pw_dir);
1124#else
1125 passwd *pw = getpwnam(userName.constData());
1126 if (!pw)
1127 return path;
1128 return QFile::decodeName(pw->pw_dir);
1129#endif // defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1130}
1131
1132Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)
1133{
1134 if (!path.startsWith(u'~'))
1135 return path;
1136
1137 if (path.size() == 1) // '~'
1138 return QDir::homePath();
1139
1140 QStringView sv(path);
1141 const qsizetype sepIndex = sv.indexOf(QDir::separator());
1142 if (sepIndex == 1) // '~/' or '~/a/b/c'
1143 return QDir::homePath() + sv.sliced(1);
1144
1145#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1146 if (sepIndex == -1)
1147 return QDir::homePath();
1148 return QDir::homePath() + sv.sliced(sepIndex);
1149#else
1150 const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen("~") // '~user/a/b'
1151 : path.size() - strlen("~"); // '~user'
1152 const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();
1153 QString homePath = homeDirFromPasswdEntry(path, userName);
1154 if (sepIndex == -1)
1155 return homePath;
1156 return homePath + sv.sliced(sepIndex);
1157#endif // defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1158}
1159#endif
1160
1165{
1166 Q_Q(const QFileDialog);
1168 QString editText = lineEdit()->text();
1169 if (!editText.contains(u'"')) {
1170#ifdef Q_OS_UNIX
1171 const QString prefix = q->directory().absolutePath() + QDir::separator();
1172 if (QFile::exists(prefix + editText))
1173 files << editText;
1174 else
1175 files << qt_tildeExpansion(editText);
1176#else
1177 files << editText;
1178 Q_UNUSED(q);
1179#endif
1180 } else {
1181 // " is used to separate files like so: "file1" "file2" "file3" ...
1182 // ### need escape character for filenames with quotes (")
1183 QStringList tokens = editText.split(u'\"');
1184 for (int i=0; i<tokens.size(); ++i) {
1185 if ((i % 2) == 0)
1186 continue; // Every even token is a separator
1187#ifdef Q_OS_UNIX
1188 const QString token = tokens.at(i);
1189 const QString prefix = q->directory().absolutePath() + QDir::separator();
1190 if (QFile::exists(prefix + token))
1191 files << token;
1192 else
1193 files << qt_tildeExpansion(token);
1194#else
1195 files << toInternal(tokens.at(i));
1196#endif
1197 }
1198 }
1200}
1201
1202// Return selected files without defaulting to the root of the file system model
1203// used for initializing QFileDialogOptions for native dialogs. The default is
1204// not suitable for native dialogs since it mostly equals directory().
1206{
1208
1209 if (!usingWidgets())
1211
1212 const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
1213 files.reserve(selectedRows.size());
1214 for (const QModelIndex &index : selectedRows)
1216
1217 if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
1218 const QStringList typedFilesList = typedFiles();
1219 files.reserve(typedFilesList.size());
1220 for (const QString &path : typedFilesList)
1222 }
1223
1224 return files;
1225}
1226
1228{
1230 for (int i=0; i<filesToFix.size(); ++i) {
1231 QString name = toInternal(filesToFix.at(i));
1233 // if the filename has no suffix, add the default suffix
1234 const QString defaultSuffix = options->defaultSuffix();
1235 if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
1236 name += u'.' + defaultSuffix;
1237
1238 if (info.isAbsolute()) {
1239 files.append(name);
1240 } else {
1241 // at this point the path should only have Qt path separators.
1242 // This check is needed since we might be at the root directory
1243 // and on Windows it already ends with slash.
1244 QString path = rootPath();
1245 if (!path.endsWith(u'/'))
1246 path += u'/';
1247 path += name;
1248 files.append(path);
1249 }
1250 }
1251 return files;
1252}
1253
1255{
1256 QList<QUrl> urls;
1257 urls.reserve(urlsToFix.size());
1258 // if the filename has no suffix, add the default suffix
1259 const QString defaultSuffix = options->defaultSuffix();
1260 for (QUrl url : urlsToFix) {
1261 if (!defaultSuffix.isEmpty()) {
1262 const QString urlPath = url.path();
1263 const auto idx = urlPath.lastIndexOf(u'/');
1264 if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
1265 url.setPath(urlPath + u'.' + defaultSuffix);
1266 }
1267 urls.append(url);
1268 }
1269 return urls;
1270}
1271
1272
1281{
1282 Q_D(const QFileDialog);
1283
1285 const QList<QUrl> userSelectedFiles = d->userSelectedFiles();
1286 files.reserve(userSelectedFiles.size());
1287 for (const QUrl &file : userSelectedFiles)
1288 files.append(file.toString(QUrl::PreferLocalFile));
1289
1290 if (files.isEmpty() && d->usingWidgets()) {
1291 const FileMode fm = fileMode();
1292 if (fm != ExistingFile && fm != ExistingFiles)
1293 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1294 }
1295 return files;
1296}
1297
1307{
1308 Q_D(const QFileDialog);
1309 if (d->nativeDialogInUse) {
1310 return d->userSelectedFiles();
1311 } else {
1312 QList<QUrl> urls;
1313 const QStringList selectedFileList = selectedFiles();
1314 urls.reserve(selectedFileList.size());
1315 for (const QString &file : selectedFileList)
1317 return urls;
1318 }
1319}
1320
1321/*
1322 Makes a list of filters from ;;-separated text.
1323 Used by the mac and windows implementations
1324*/
1326{
1327 if (filter.isEmpty())
1328 return QStringList();
1329
1330 auto sep = ";;"_L1;
1331 if (!filter.contains(sep) && filter.contains(u'\n'))
1332 sep = "\n"_L1;
1333
1334 return filter.split(sep);
1335}
1336
1355{
1357}
1358
1359
1360/*
1361 Strip the filters by removing the details, e.g. (*.*).
1362*/
1364{
1365#if QT_CONFIG(regularexpression)
1366 QStringList strippedFilters;
1368 strippedFilters.reserve(filters.size());
1369 for (const QString &filter : filters) {
1370 QString filterName;
1371 auto match = r.match(filter);
1372 if (match.hasMatch())
1373 filterName = match.captured(1);
1374 strippedFilters.append(filterName.simplified());
1375 }
1376 return strippedFilters;
1377#else
1378 return filters;
1379#endif
1380}
1381
1382
1403{
1404 Q_D(QFileDialog);
1405 QStringList cleanedFilters;
1406 cleanedFilters.reserve(filters.size());
1407 for (const QString &filter : filters)
1408 cleanedFilters << filter.simplified();
1409
1410 d->options->setNameFilters(cleanedFilters);
1411
1412 if (!d->usingWidgets())
1413 return;
1414
1415 d->qFileDialogUi->fileTypeCombo->clear();
1416 if (cleanedFilters.isEmpty())
1417 return;
1418
1420 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1421 else
1422 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1423
1424 d->_q_useNameFilter(0);
1425}
1426
1434{
1435 return d_func()->options->nameFilters();
1436}
1437
1447{
1448 Q_D(QFileDialog);
1449 d->options->setInitiallySelectedNameFilter(filter);
1450 if (!d->usingWidgets()) {
1451 d->selectNameFilter_sys(filter);
1452 return;
1453 }
1454 int i = -1;
1457 if (!filters.isEmpty())
1458 i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());
1459 } else {
1460 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1461 }
1462 if (i >= 0) {
1463 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1464 d->_q_useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1465 }
1466}
1467
1476{
1477 Q_D(const QFileDialog);
1478 if (!d->usingWidgets())
1479 return d->selectedNameFilter_sys();
1480
1481 return d->qFileDialogUi->fileTypeCombo->currentText();
1482}
1483
1491QDir::Filters QFileDialog::filter() const
1492{
1493 Q_D(const QFileDialog);
1494 if (d->usingWidgets())
1495 return d->model->filter();
1496 return d->options->filter();
1497}
1498
1509{
1510 Q_D(QFileDialog);
1511 d->options->setFilter(filters);
1512 if (!d->usingWidgets()) {
1513 d->setFilter_sys();
1514 return;
1515 }
1516
1517 d->model->setFilter(filters);
1518 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1519}
1520
1521#if QT_CONFIG(mimetype)
1522
1523static QString nameFilterForMime(const QString &mimeType)
1524{
1527 if (mime.isValid()) {
1528 if (mime.isDefault()) {
1529 return QFileDialog::tr("All files (*)");
1530 } else {
1531 const QString patterns = mime.globPatterns().join(u' ');
1532 return mime.comment() + " ("_L1 + patterns + u')';
1533 }
1534 }
1535 return QString();
1536}
1537
1555void QFileDialog::setMimeTypeFilters(const QStringList &filters)
1556{
1557 Q_D(QFileDialog);
1559 for (const QString &mimeType : filters) {
1560 const QString text = nameFilterForMime(mimeType);
1561 if (!text.isEmpty())
1562 nameFilters.append(text);
1563 }
1565 d->options->setMimeTypeFilters(filters);
1566}
1567
1574QStringList QFileDialog::mimeTypeFilters() const
1575{
1576 return d_func()->options->mimeTypeFilters();
1577}
1578
1585void QFileDialog::selectMimeTypeFilter(const QString &filter)
1586{
1587 Q_D(QFileDialog);
1588 d->options->setInitiallySelectedMimeTypeFilter(filter);
1589
1590 const QString filterForMime = nameFilterForMime(filter);
1591
1592 if (!d->usingWidgets()) {
1593 d->selectMimeTypeFilter_sys(filter);
1594 if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
1595 selectNameFilter(filterForMime);
1596 }
1597 } else if (!filterForMime.isEmpty()) {
1598 selectNameFilter(filterForMime);
1599 }
1600}
1601
1602#endif // mimetype
1603
1609{
1610 Q_D(const QFileDialog);
1611 QString mimeTypeFilter;
1612 if (!d->usingWidgets())
1613 mimeTypeFilter = d->selectedMimeTypeFilter_sys();
1614
1615#if QT_CONFIG(mimetype)
1616 if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
1617 const auto nameFilter = selectedNameFilter();
1618 const auto mimeTypes = d->options->mimeTypeFilters();
1619 for (const auto &mimeType: mimeTypes) {
1620 QString filter = nameFilterForMime(mimeType);
1623 if (filter == nameFilter) {
1624 mimeTypeFilter = mimeType;
1625 break;
1626 }
1627 }
1628 }
1629#endif
1630
1631 return mimeTypeFilter;
1632}
1633
1644{
1645 Q_D(QFileDialog);
1646 d->options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(mode));
1647 if (!d->usingWidgets())
1648 return;
1649 if (mode == Detail)
1650 d->_q_showDetailsView();
1651 else
1652 d->_q_showListView();
1653}
1654
1656{
1657 Q_D(const QFileDialog);
1658 if (!d->usingWidgets())
1659 return static_cast<QFileDialog::ViewMode>(d->options->viewMode());
1660 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1661}
1662
1679{
1680 Q_D(QFileDialog);
1681 d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));
1682 if (!d->usingWidgets())
1683 return;
1684
1685 d->retranslateWindowTitle();
1686
1687 // set selection mode and behavior
1691 else
1692 selectionMode = QAbstractItemView::SingleSelection;
1693 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1694 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1695 // set filter
1696 d->model->setFilter(d->filterForMode(filter()));
1697 // setup file type for directory
1698 if (mode == Directory) {
1699 d->qFileDialogUi->fileTypeCombo->clear();
1700 d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
1701 d->qFileDialogUi->fileTypeCombo->setEnabled(false);
1702 }
1703 d->updateFileNameLabel();
1704 d->updateOkButtonText();
1705 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1706 d->_q_updateOkButton();
1707}
1708
1710{
1711 Q_D(const QFileDialog);
1712 return static_cast<FileMode>(d->options->fileMode());
1713}
1714
1726{
1727 Q_D(QFileDialog);
1728 d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode));
1729 // clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
1731 if (!d->usingWidgets())
1732 return;
1734 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1735 d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
1736 d->_q_updateOkButton();
1737 if (mode == AcceptSave) {
1738 d->qFileDialogUi->lookInCombo->setEditable(false);
1739 }
1740 d->retranslateWindowTitle();
1741}
1742
1757{
1758 Q_D(QFileDialog);
1759 d->options->setSupportedSchemes(schemes);
1760}
1761
1763{
1764 return d_func()->options->supportedSchemes();
1765}
1766
1767/*
1768 Returns the file system model index that is the root index in the
1769 views
1770*/
1772 return mapToSource(qFileDialogUi->listView->rootIndex());
1773}
1774
1776 if (!qFileDialogUi->stackedWidget)
1777 return nullptr;
1778 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1779 return qFileDialogUi->listView;
1780 return qFileDialogUi->treeView;
1781}
1782
1784 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1785}
1786
1788{
1789#if defined(Q_OS_UNIX)
1790 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1791#elif defined(Q_OS_WIN)
1792 DWORD maxLength;
1793 const QString drive = path.left(3);
1794 if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == false)
1795 return -1;
1796 return maxLength;
1797#else
1798 Q_UNUSED(path);
1799#endif
1800 return -1;
1801}
1802
1803/*
1804 Sets the view root index to be the file system model index
1805*/
1807 Q_ASSERT(index.isValid() ? index.model() == model : true);
1809 qFileDialogUi->treeView->setRootIndex(idx);
1810 qFileDialogUi->listView->setRootIndex(idx);
1811}
1812/*
1813 Select a file system model index
1814 returns the index that was selected (or not depending upon sortfilterproxymodel)
1815*/
1817 Q_ASSERT(index.isValid() ? index.model() == model : true);
1818
1820 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1821 qFileDialogUi->listView->selectionModel()->select(idx,
1823 return idx;
1824}
1825
1827{
1828 Q_D(const QFileDialog);
1829 return static_cast<AcceptMode>(d->options->acceptMode());
1830}
1831
1844{
1845 Q_D(QFileDialog);
1846 d->options->setDefaultSuffix(suffix);
1847}
1848
1850{
1851 Q_D(const QFileDialog);
1852 return d->options->defaultSuffix();
1853}
1854
1860{
1861 Q_D(QFileDialog);
1862 if (d->usingWidgets())
1863 d->qFileDialogUi->lookInCombo->setHistory(paths);
1864}
1865
1867{
1868 m_history = paths;
1869 // Only populate the first item, showPopup will populate the rest if needed
1871 const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1872 //On windows the popup display the "C:\", convert to nativeSeparators
1873 const QUrl url = idx.isValid()
1875 : QUrl("file:"_L1);
1876 if (url.isValid())
1877 list.append(url);
1878 urlModel->setUrls(list);
1879}
1880
1885{
1886 Q_D(const QFileDialog);
1887 if (!d->usingWidgets())
1888 return QStringList();
1889 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1890 //On windows the popup display the "C:\", convert to nativeSeparators
1891 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1892 if (!currentHistory.contains(newHistory))
1893 currentHistory << newHistory;
1894 return currentHistory;
1895}
1896
1916{
1917 Q_D(QFileDialog);
1918 if (!d->usingWidgets())
1919 return;
1920 d->qFileDialogUi->listView->setItemDelegate(delegate);
1921 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1922}
1923
1928{
1929 Q_D(const QFileDialog);
1930 if (!d->usingWidgets())
1931 return nullptr;
1932 return d->qFileDialogUi->listView->itemDelegate();
1933}
1934
1939{
1940 Q_D(QFileDialog);
1941 if (!d->usingWidgets())
1942 return;
1943 d->model->setIconProvider(provider);
1944 //It forces the refresh of all entries in the side bar, then we can get new icons
1945 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1946}
1947
1952{
1953 Q_D(const QFileDialog);
1954 if (!d->model)
1955 return nullptr;
1956 return d->model->iconProvider();
1957}
1958
1960{
1961 if (!qFileDialogUi)
1962 return;
1963 switch (label) {
1965 qFileDialogUi->lookInLabel->setText(text);
1966 break;
1968 qFileDialogUi->fileNameLabel->setText(text);
1969 break;
1971 qFileDialogUi->fileTypeLabel->setText(text);
1972 break;
1974 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
1975 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
1977 } else {
1978 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
1980 }
1981 break;
1983 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
1985 break;
1986 }
1987}
1988
1994{
1995 Q_D(QFileDialog);
1996 d->options->setLabelText(static_cast<QFileDialogOptions::DialogLabel>(label), text);
1997 d->setLabelTextControl(label, text);
1998}
1999
2004{
2005 Q_D(const QFileDialog);
2006 if (!d->usingWidgets())
2007 return d->options->labelText(static_cast<QFileDialogOptions::DialogLabel>(label));
2009 switch (label) {
2010 case LookIn:
2011 return d->qFileDialogUi->lookInLabel->text();
2012 case FileName:
2013 return d->qFileDialogUi->fileNameLabel->text();
2014 case FileType:
2015 return d->qFileDialogUi->fileTypeLabel->text();
2016 case Accept:
2017 if (acceptMode() == AcceptOpen)
2018 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
2019 else
2020 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
2021 if (button)
2022 return button->text();
2023 break;
2024 case Reject:
2025 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
2026 if (button)
2027 return button->text();
2028 break;
2029 }
2030 return QString();
2031}
2032
2080 const QString &caption,
2081 const QString &dir,
2082 const QString &filter,
2083 QString *selectedFilter,
2084 Options options)
2085{
2086 const QStringList schemes = QStringList(QStringLiteral("file"));
2087 const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2088 selectedFilter, options, schemes);
2089 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2090 return selectedUrl.toLocalFile();
2091 else
2092 return selectedUrl.toString();
2093}
2094
2123 const QString &caption,
2124 const QUrl &dir,
2125 const QString &filter,
2126 QString *selectedFilter,
2127 Options options,
2128 const QStringList &supportedSchemes)
2129{
2131 args.parent = parent;
2132 args.caption = caption;
2133 args.filter = filter;
2134 args.mode = ExistingFile;
2135 args.options = options;
2136
2139 if (selectedFilter && !selectedFilter->isEmpty())
2140 dialog.selectNameFilter(*selectedFilter);
2141 if (dialog.exec() == QDialog::Accepted) {
2142 if (selectedFilter)
2143 *selectedFilter = dialog.selectedNameFilter();
2144 return dialog.selectedUrls().value(0);
2145 }
2146 return QUrl();
2147}
2148
2193 const QString &caption,
2194 const QString &dir,
2195 const QString &filter,
2196 QString *selectedFilter,
2197 Options options)
2198{
2199 const QStringList schemes = QStringList(QStringLiteral("file"));
2201 filter, selectedFilter, options, schemes);
2203 fileNames.reserve(selectedUrls.size());
2204 for (const QUrl &url : selectedUrls)
2206 return fileNames;
2207}
2208
2238 const QString &caption,
2239 const QUrl &dir,
2240 const QString &filter,
2241 QString *selectedFilter,
2242 Options options,
2243 const QStringList &supportedSchemes)
2244{
2246 args.parent = parent;
2247 args.caption = caption;
2248 args.filter = filter;
2249 args.mode = ExistingFiles;
2250 args.options = options;
2251
2254 if (selectedFilter && !selectedFilter->isEmpty())
2255 dialog.selectNameFilter(*selectedFilter);
2256 if (dialog.exec() == QDialog::Accepted) {
2257 if (selectedFilter)
2258 *selectedFilter = dialog.selectedNameFilter();
2259 return dialog.selectedUrls();
2260 }
2261 return QList<QUrl>();
2262}
2263
2282void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted)
2283{
2284#ifdef Q_OS_WASM
2285 auto openFileImpl = std::make_shared<std::function<void(void)>>();
2287 QByteArray fileContent;
2288 *openFileImpl = [=]() mutable {
2289 auto fileDialogClosed = [&](bool fileSelected) {
2290 if (!fileSelected) {
2291 fileOpenCompleted(fileName, fileContent);
2292 openFileImpl.reset();
2293 }
2294 };
2295 auto acceptFile = [&](uint64_t size, const std::string name) -> char * {
2296 const uint64_t twoGB = 1ULL << 31; // QByteArray limit
2297 if (size > twoGB)
2298 return nullptr;
2299
2301 fileContent.resize(size);
2302 return fileContent.data();
2303 };
2304 auto fileContentReady = [&]() mutable {
2305 fileOpenCompleted(fileName, fileContent);
2306 openFileImpl.reset();
2307 };
2308
2309 QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
2310 };
2311
2312 (*openFileImpl)();
2313#else
2316 dialog->setNameFilter(nameFilter);
2317
2318 auto fileSelected = [=](const QString &fileName) {
2319 QByteArray fileContent;
2320 if (!fileName.isNull()) {
2321 QFile selectedFile(fileName);
2322 if (selectedFile.open(QIODevice::ReadOnly))
2323 fileContent = selectedFile.readAll();
2324 }
2325 fileOpenCompleted(fileName, fileContent);
2326 };
2327
2330 dialog->show();
2331#endif
2332}
2333
2350void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint)
2351{
2352#ifdef Q_OS_WASM
2353 QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
2354#else
2358 dialog->selectFile(fileNameHint);
2359
2360 auto fileSelected = [=](const QString &fileName) {
2361 if (!fileName.isNull()) {
2362 QFile selectedFile(fileName);
2363 if (selectedFile.open(QIODevice::WriteOnly))
2364 selectedFile.write(fileContent);
2365 }
2366 };
2367
2370 dialog->show();
2371#endif
2372}
2373
2423 const QString &caption,
2424 const QString &dir,
2425 const QString &filter,
2426 QString *selectedFilter,
2427 Options options)
2428{
2429 const QStringList schemes = QStringList(QStringLiteral("file"));
2430 const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2431 selectedFilter, options, schemes);
2432 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2433 return selectedUrl.toLocalFile();
2434 else
2435 return selectedUrl.toString();
2436}
2437
2466 const QString &caption,
2467 const QUrl &dir,
2468 const QString &filter,
2469 QString *selectedFilter,
2470 Options options,
2471 const QStringList &supportedSchemes)
2472{
2474 args.parent = parent;
2475 args.caption = caption;
2476 args.filter = filter;
2477 args.mode = AnyFile;
2478 args.options = options;
2479
2483 if (selectedFilter && !selectedFilter->isEmpty())
2484 dialog.selectNameFilter(*selectedFilter);
2485 if (dialog.exec() == QDialog::Accepted) {
2486 if (selectedFilter)
2487 *selectedFilter = dialog.selectedNameFilter();
2488 return dialog.selectedUrls().value(0);
2489 }
2490 return QUrl();
2491}
2492
2537 const QString &caption,
2538 const QString &dir,
2539 Options options)
2540{
2541 const QStringList schemes = QStringList(QStringLiteral("file"));
2542 const QUrl selectedUrl =
2544 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2545 return selectedUrl.toLocalFile();
2546 else
2547 return selectedUrl.toString();
2548}
2549
2578 const QString &caption,
2579 const QUrl &dir,
2580 Options options,
2581 const QStringList &supportedSchemes)
2582{
2584 args.parent = parent;
2585 args.caption = caption;
2586 args.mode = Directory;
2587 args.options = options;
2588
2591 if (dialog.exec() == QDialog::Accepted)
2592 return dialog.selectedUrls().value(0);
2593 return QUrl();
2594}
2595
2596inline static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)
2597{
2598 if (url.isLocalFile()) {
2599 QFileInfo info = local;
2600 if (!local.isAbsolute())
2602 const QFileInfo pathInfo(info.absolutePath());
2603 if (!pathInfo.exists() || !pathInfo.isDir())
2604 return QUrl();
2605 if (info.exists() && info.isDir())
2607 return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
2608 } else {
2609 return url;
2610 }
2611}
2612
2613/*
2614 Initialize working directory and selection from \a url.
2615*/
2617{
2618 // default case, re-use QFileInfo to avoid stat'ing
2619 const QFileInfo local(url.toLocalFile());
2620 // Get the initial directory URL
2621 if (!url.isEmpty())
2623 if (directory.isEmpty()) {
2624 const QUrl lastVisited = *lastVisitedDir();
2625 if (lastVisited != url)
2626 directory = _qt_get_directory(lastVisited, QFileInfo());
2627 }
2628 if (directory.isEmpty())
2630
2631 /*
2632 The initial directory can contain both the initial directory
2633 and initial selection, e.g. /home/user/foo.txt
2634 */
2635 if (selection.isEmpty() && !url.isEmpty()) {
2636 if (url.isLocalFile()) {
2637 if (!local.isDir())
2638 selection = local.fileName();
2639 } else {
2640 // With remote URLs we can only assume.
2642 }
2643 }
2644}
2645
2650{
2651 Q_D(QFileDialog);
2652
2654
2655 if (d->receiverToDisconnectOnClose) {
2656 disconnect(this, d->signalToDisconnectOnClose,
2657 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2658 d->receiverToDisconnectOnClose = nullptr;
2659 }
2660 d->memberToDisconnectOnClose.clear();
2661 d->signalToDisconnectOnClose.clear();
2662}
2663
2664bool QFileDialogPrivate::itemAlreadyExists(const QString &fileName)
2665{
2666#if QT_CONFIG(messagebox)
2667 Q_Q(QFileDialog);
2668 const QString msg = QFileDialog::tr("%1 already exists.\nDo you want to replace it?").arg(fileName);
2669 using B = QMessageBox;
2670 const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
2671 return res == B::Yes;
2672#endif
2673 return false;
2674}
2675
2676void QFileDialogPrivate::itemNotFound(const QString &fileName, QFileDialog::FileMode mode)
2677{
2678#if QT_CONFIG(messagebox)
2679 Q_Q(QFileDialog);
2681 ? QFileDialog::tr("%1\nDirectory not found.\n"
2682 "Please verify the correct directory name was given.")
2683 : QFileDialog::tr("%1\nFile not found.\nPlease verify the "
2684 "correct file name was given.");
2685
2686 QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
2687#endif // QT_CONFIG(messagebox)
2688}
2689
2694{
2695 Q_D(QFileDialog);
2696 if (!d->usingWidgets()) {
2697 const QList<QUrl> urls = selectedUrls();
2698 if (urls.isEmpty())
2699 return;
2700 d->_q_emitUrlsSelected(urls);
2701 if (urls.size() == 1)
2702 d->_q_emitUrlSelected(urls.first());
2704 return;
2705 }
2706
2708 if (files.isEmpty())
2709 return;
2710 QString lineEditText = d->lineEdit()->text();
2711 // "hidden feature" type .. and then enter, and it will move up a dir
2712 // special case for ".."
2713 if (lineEditText == ".."_L1) {
2714 d->_q_navigateToParent();
2715 const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
2716 d->lineEdit()->selectAll();
2717 return;
2718 }
2719
2720 const auto mode = fileMode();
2721 switch (mode) {
2722 case Directory: {
2723 QString fn = files.first();
2724 QFileInfo info(fn);
2725 if (!info.exists())
2726 info = QFileInfo(d->getEnvironmentVariable(fn));
2727 if (!info.exists()) {
2728 d->itemNotFound(info.fileName(), mode);
2729 return;
2730 }
2731 if (info.isDir()) {
2732 d->emitFilesSelected(files);
2734 }
2735 return;
2736 }
2737
2738 case AnyFile: {
2739 QString fn = files.first();
2740 QFileInfo info(fn);
2741 if (info.isDir()) {
2743 return;
2744 }
2745
2746 if (!info.exists()) {
2747 const long maxNameLength = d->maxNameLength(info.path());
2748 if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
2749 return;
2750 }
2751
2752 // check if we have to ask for permission to overwrite the file
2754 d->emitFilesSelected(QStringList(fn));
2756 } else {
2757 if (d->itemAlreadyExists(info.fileName())) {
2758 d->emitFilesSelected(QStringList(fn));
2760 }
2761 }
2762 return;
2763 }
2764
2765 case ExistingFile:
2766 case ExistingFiles:
2767 for (const auto &file : files) {
2769 if (!info.exists())
2770 info = QFileInfo(d->getEnvironmentVariable(file));
2771 if (!info.exists()) {
2772 d->itemNotFound(info.fileName(), mode);
2773 return;
2774 }
2775 if (info.isDir()) {
2777 d->lineEdit()->clear();
2778 return;
2779 }
2780 }
2781 d->emitFilesSelected(files);
2783 return;
2784 }
2785}
2786
2787#if QT_CONFIG(settings)
2788void QFileDialogPrivate::saveSettings()
2789{
2790 Q_Q(QFileDialog);
2791 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2792 settings.beginGroup("FileDialog");
2793
2794 if (usingWidgets()) {
2795 settings.setValue("sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
2796 settings.setValue("shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
2797 settings.setValue("treeViewHeader", qFileDialogUi->treeView->header()->saveState());
2798 }
2799 QStringList historyUrls;
2800 const QStringList history = q->history();
2801 historyUrls.reserve(history.size());
2802 for (const QString &path : history)
2803 historyUrls << QUrl::fromLocalFile(path).toString();
2804 settings.setValue("history", historyUrls);
2805 settings.setValue("lastVisited", lastVisitedDir()->toString());
2806 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
2807 settings.setValue("viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
2808 settings.setValue("qtVersion", QT_VERSION_STR ""_L1);
2809}
2810
2811bool QFileDialogPrivate::restoreFromSettings()
2812{
2813 Q_Q(QFileDialog);
2814 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2815 if (!settings.childGroups().contains("FileDialog"_L1))
2816 return false;
2817 settings.beginGroup("FileDialog");
2818
2819 q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value("lastVisited").toUrl() : *lastVisitedDir());
2820
2821 QByteArray viewModeStr = settings.value("viewMode").toString().toLatin1();
2822 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
2823 bool ok = false;
2824 int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
2825 if (!ok)
2826 viewMode = QFileDialog::List;
2827 q->setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));
2828
2830 headerData = settings.value("treeViewHeader").toByteArray();
2831
2832 if (!usingWidgets())
2833 return true;
2834
2835 QStringList history;
2836 const auto urlStrings = settings.value("history").toStringList();
2837 for (const QString &urlStr : urlStrings) {
2838 QUrl url(urlStr);
2839 if (url.isLocalFile())
2840 history << url.toLocalFile();
2841 }
2842
2843 return restoreWidgetState(history, settings.value("sidebarWidth", -1).toInt());
2844}
2845#endif // settings
2846
2847bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPosition)
2848{
2849 Q_Q(QFileDialog);
2850 if (splitterPosition >= 0) {
2851 QList<int> splitterSizes;
2852 splitterSizes.append(splitterPosition);
2853 splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
2854 qFileDialogUi->splitter->setSizes(splitterSizes);
2855 } else {
2856 if (!qFileDialogUi->splitter->restoreState(splitterState))
2857 return false;
2858 QList<int> list = qFileDialogUi->splitter->sizes();
2859 if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
2860 for (int i = 0; i < list.size(); ++i)
2861 list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
2862 qFileDialogUi->splitter->setSizes(list);
2863 }
2864 }
2865
2866 qFileDialogUi->sidebar->setUrls(sidebarUrls);
2867
2868 static const int MaxHistorySize = 5;
2869 if (history.size() > MaxHistorySize)
2870 history.erase(history.begin(), history.end() - MaxHistorySize);
2871 q->setHistory(history);
2872
2873 QHeaderView *headerView = qFileDialogUi->treeView->header();
2874 if (!headerView->restoreState(headerData))
2875 return false;
2876
2877 QList<QAction*> actions = headerView->actions();
2878 QAbstractItemModel *abstractModel = model;
2879#if QT_CONFIG(proxymodel)
2880 if (proxyModel)
2881 abstractModel = proxyModel;
2882#endif
2883 const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
2884 for (int i = 1; i < total; ++i)
2885 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
2886
2887 return true;
2888}
2889
2896{
2897 Q_Q(QFileDialog);
2898 if (!args.caption.isEmpty()) {
2899 useDefaultCaption = false;
2900 setWindowTitle = args.caption;
2901 q->setWindowTitle(args.caption);
2902 }
2903
2904 q->setAcceptMode(QFileDialog::AcceptOpen);
2906 if (!nativeDialogInUse)
2907 createWidgets();
2908 q->setFileMode(QFileDialog::AnyFile);
2909 if (!args.filter.isEmpty())
2910 q->setNameFilter(args.filter);
2911 // QTBUG-70798, prevent the default blocking the restore logic.
2912 const bool dontStoreDir = !args.directory.isValid() && !lastVisitedDir()->isValid();
2913 q->setDirectoryUrl(args.directory);
2914 if (dontStoreDir)
2915 lastVisitedDir()->clear();
2916 if (args.directory.isLocalFile())
2917 q->selectFile(args.selection);
2918 else
2919 q->selectUrl(args.directory);
2920
2921#if QT_CONFIG(settings)
2922 // Try to restore from the FileDialog settings group; if it fails, fall back
2923 // to the pre-5.5 QByteArray serialized settings.
2924 if (!restoreFromSettings()) {
2925 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
2926 q->restoreState(settings.value("Qt/filedialog").toByteArray());
2927 }
2928#endif
2929
2930#if defined(Q_EMBEDDED_SMALLSCREEN)
2931 qFileDialogUi->lookInLabel->setVisible(false);
2932 qFileDialogUi->fileNameLabel->setVisible(false);
2933 qFileDialogUi->fileTypeLabel->setVisible(false);
2934 qFileDialogUi->sidebar->hide();
2935#endif
2936
2937 const QSize sizeHint = q->sizeHint();
2938 if (sizeHint.isValid())
2939 q->resize(sizeHint);
2940}
2941
2948{
2949 if (qFileDialogUi)
2950 return;
2951 Q_Q(QFileDialog);
2952
2953 // This function is sometimes called late (e.g as a fallback from setVisible). In that case we
2954 // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly
2955 // set window state or geometry.
2956 QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
2957 Qt::WindowStates preState = q->windowState();
2958
2959 model = new QFileSystemModel(q);
2962 model->setObjectName("qt_filesystem_model"_L1);
2964 model->setNameFilterDisables(helper->defaultNameFilterDisables());
2965 else
2967 model->d_func()->disableRecursiveSort = true;
2969 QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)),
2971 QFileDialog::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
2973 model->setReadOnly(false);
2974
2975 qFileDialogUi.reset(new Ui_QFileDialog());
2976 qFileDialogUi->setupUi(q);
2977
2978 QList<QUrl> initialBookmarks;
2979 initialBookmarks << QUrl("file:"_L1)
2981 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
2982 QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(QUrl)),
2983 q, SLOT(_q_goToUrl(QUrl)));
2984
2985 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
2986 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
2987
2988 qFileDialogUi->lookInCombo->setFileDialogPrivate(this);
2989 QObject::connect(qFileDialogUi->lookInCombo, SIGNAL(textActivated(QString)), q, SLOT(_q_goToDirectory(QString)));
2990
2991 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
2992 qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
2993
2994 // filename
2995 qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);
2996#ifndef QT_NO_SHORTCUT
2997 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
2998#endif
2999#if QT_CONFIG(fscompleter)
3000 completer = new QFSCompleter(model, q);
3001 qFileDialogUi->fileNameEdit->setCompleter(completer);
3002#endif // QT_CONFIG(fscompleter)
3003
3004 qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
3005
3010
3011 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(returnPressed()), q, SLOT(accept()));
3012
3013 // filetype
3014 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
3015 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
3016 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
3017 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(int)),
3018 q, SLOT(_q_useNameFilter(int)));
3019 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(textActivated(QString)),
3020 q, SIGNAL(filterSelected(QString)));
3021
3022 qFileDialogUi->listView->setFileDialogPrivate(this);
3023 qFileDialogUi->listView->setModel(model);
3024 QObject::connect(qFileDialogUi->listView, SIGNAL(activated(QModelIndex)),
3026 QObject::connect(qFileDialogUi->listView, SIGNAL(customContextMenuRequested(QPoint)),
3028#ifndef QT_NO_SHORTCUT
3031#endif
3032
3033 qFileDialogUi->treeView->setFileDialogPrivate(this);
3034 qFileDialogUi->treeView->setModel(model);
3035 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
3036 QFontMetrics fm(q->font());
3037 treeHeader->resizeSection(0, fm.horizontalAdvance("wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
3038 treeHeader->resizeSection(1, fm.horizontalAdvance("128.88 GB"_L1));
3039 treeHeader->resizeSection(2, fm.horizontalAdvance("mp3Folder"_L1));
3040 treeHeader->resizeSection(3, fm.horizontalAdvance("10/29/81 02:02PM"_L1));
3041 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
3042
3043 QActionGroup *showActionGroup = new QActionGroup(q);
3044 showActionGroup->setExclusive(false);
3045 QObject::connect(showActionGroup, SIGNAL(triggered(QAction*)),
3047
3048 QAbstractItemModel *abstractModel = model;
3049#if QT_CONFIG(proxymodel)
3050 if (proxyModel)
3051 abstractModel = proxyModel;
3052#endif
3053 for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
3054 QAction *showHeader = new QAction(showActionGroup);
3055 showHeader->setCheckable(true);
3056 showHeader->setChecked(true);
3057 treeHeader->addAction(showHeader);
3058 }
3059
3060 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
3061 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
3062
3063 QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
3065 QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
3067#ifndef QT_NO_SHORTCUT
3070#endif
3071
3072 // Selections
3073 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
3074 QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
3076 QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
3078 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
3079
3082
3083#if QT_CONFIG(settings)
3084 // Try to restore from the FileDialog settings group; if it fails, fall back
3085 // to the pre-5.5 QByteArray serialized settings.
3086 if (!restoreFromSettings()) {
3087 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
3088 q->restoreState(settings.value("Qt/filedialog").toByteArray());
3089 }
3090#endif
3091
3092 // Initial widget states from options
3093 q->setFileMode(static_cast<QFileDialog::FileMode>(options->fileMode()));
3094 q->setAcceptMode(static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
3095 q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
3096 q->setOptions(static_cast<QFileDialog::Options>(static_cast<int>(options->options())));
3097 if (!options->sidebarUrls().isEmpty())
3098 q->setSidebarUrls(options->sidebarUrls());
3099 q->setDirectoryUrl(options->initialDirectory());
3100#if QT_CONFIG(mimetype)
3101 if (!options->mimeTypeFilters().isEmpty())
3102 q->setMimeTypeFilters(options->mimeTypeFilters());
3103 else
3104#endif
3105 if (!options->nameFilters().isEmpty())
3106 q->setNameFilters(options->nameFilters());
3107 q->selectNameFilter(options->initiallySelectedNameFilter());
3108 q->setDefaultSuffix(options->defaultSuffix());
3109 q->setHistory(options->history());
3110 const auto initiallySelectedFiles = options->initiallySelectedFiles();
3111 if (initiallySelectedFiles.size() == 1)
3112 q->selectFile(initiallySelectedFiles.first().fileName());
3113 for (const QUrl &url : initiallySelectedFiles)
3114 q->selectUrl(url);
3115 lineEdit()->selectAll();
3118 q->resize(preSize.isValid() ? preSize : q->sizeHint());
3119 q->setWindowState(preState);
3120}
3121
3123{
3124 Q_Q(QFileDialog);
3125 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
3126 qFileDialogUi->treeView->header()->setSectionHidden(int(actionGroup->actions().indexOf(action) + 1),
3127 !action->isChecked());
3128}
3129
3130#if QT_CONFIG(proxymodel)
3143void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
3144{
3145 Q_D(QFileDialog);
3146 if (!d->usingWidgets())
3147 return;
3148 if ((!proxyModel && !d->proxyModel)
3149 || (proxyModel == d->proxyModel))
3150 return;
3151
3152 QModelIndex idx = d->rootIndex();
3153 if (d->proxyModel) {
3154 disconnect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
3155 this, SLOT(_q_rowsInserted(QModelIndex)));
3156 } else {
3157 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
3158 this, SLOT(_q_rowsInserted(QModelIndex)));
3159 }
3160
3161 if (proxyModel != nullptr) {
3162 proxyModel->setParent(this);
3163 d->proxyModel = proxyModel;
3164 proxyModel->setSourceModel(d->model);
3165 d->qFileDialogUi->listView->setModel(d->proxyModel);
3166 d->qFileDialogUi->treeView->setModel(d->proxyModel);
3167#if QT_CONFIG(fscompleter)
3168 d->completer->setModel(d->proxyModel);
3169 d->completer->proxyModel = d->proxyModel;
3170#endif
3171 connect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
3172 this, SLOT(_q_rowsInserted(QModelIndex)));
3173 } else {
3174 d->proxyModel = nullptr;
3175 d->qFileDialogUi->listView->setModel(d->model);
3176 d->qFileDialogUi->treeView->setModel(d->model);
3177#if QT_CONFIG(fscompleter)
3178 d->completer->setModel(d->model);
3179 d->completer->sourceModel = d->model;
3180 d->completer->proxyModel = nullptr;
3181#endif
3182 connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
3183 this, SLOT(_q_rowsInserted(QModelIndex)));
3184 }
3185 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
3186 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
3187
3188 d->setRootIndex(idx);
3189
3190 // reconnect selection
3191 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
3192 QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
3193 this, SLOT(_q_selectionChanged()));
3195 this, SLOT(_q_currentChanged(QModelIndex)));
3196}
3197
3203QAbstractProxyModel *QFileDialog::proxyModel() const
3204{
3205 Q_D(const QFileDialog);
3206 return d->proxyModel;
3207}
3208#endif // QT_CONFIG(proxymodel)
3209
3216{
3217 Q_Q(QFileDialog);
3218 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, nullptr, q));
3219 qFileDialogUi->backButton->setAutoRaise(true);
3220 qFileDialogUi->backButton->setEnabled(false);
3221 QObject::connect(qFileDialogUi->backButton, SIGNAL(clicked()), q, SLOT(_q_navigateBackward()));
3222
3223 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, nullptr, q));
3224 qFileDialogUi->forwardButton->setAutoRaise(true);
3225 qFileDialogUi->forwardButton->setEnabled(false);
3226 QObject::connect(qFileDialogUi->forwardButton, SIGNAL(clicked()), q, SLOT(_q_navigateForward()));
3227
3228 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, nullptr, q));
3229 qFileDialogUi->toParentButton->setAutoRaise(true);
3230 qFileDialogUi->toParentButton->setEnabled(false);
3231 QObject::connect(qFileDialogUi->toParentButton, SIGNAL(clicked()), q, SLOT(_q_navigateToParent()));
3232
3233 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, nullptr, q));
3234 qFileDialogUi->listModeButton->setAutoRaise(true);
3235 qFileDialogUi->listModeButton->setDown(true);
3236 QObject::connect(qFileDialogUi->listModeButton, SIGNAL(clicked()), q, SLOT(_q_showListView()));
3237
3238 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, nullptr, q));
3239 qFileDialogUi->detailModeButton->setAutoRaise(true);
3240 QObject::connect(qFileDialogUi->detailModeButton, SIGNAL(clicked()), q, SLOT(_q_showDetailsView()));
3241
3242 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
3243 qFileDialogUi->backButton->setFixedSize(toolSize);
3244 qFileDialogUi->listModeButton->setFixedSize(toolSize);
3245 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
3246 qFileDialogUi->forwardButton->setFixedSize(toolSize);
3247 qFileDialogUi->toParentButton->setFixedSize(toolSize);
3248
3249 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, nullptr, q));
3250 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
3251 qFileDialogUi->newFolderButton->setAutoRaise(true);
3252 qFileDialogUi->newFolderButton->setEnabled(false);
3253 QObject::connect(qFileDialogUi->newFolderButton, SIGNAL(clicked()), q, SLOT(_q_createDirectory()));
3254}
3255
3262{
3263 Q_Q(QFileDialog);
3264
3265 QAction *goHomeAction = new QAction(q);
3266#ifndef QT_NO_SHORTCUT
3267 goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
3268#endif
3269 QObject::connect(goHomeAction, SIGNAL(triggered()), q, SLOT(_q_goHome()));
3270 q->addAction(goHomeAction);
3271
3272 // ### TODO add Desktop & Computer actions
3273
3274 QAction *goToParent = new QAction(q);
3275 goToParent->setObjectName("qt_goto_parent_action"_L1);
3276#ifndef QT_NO_SHORTCUT
3277 goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
3278#endif
3279 QObject::connect(goToParent, SIGNAL(triggered()), q, SLOT(_q_navigateToParent()));
3280 q->addAction(goToParent);
3281
3282 renameAction = new QAction(q);
3283 renameAction->setEnabled(false);
3284 renameAction->setObjectName("qt_rename_action"_L1);
3286
3287 deleteAction = new QAction(q);
3288 deleteAction->setEnabled(false);
3289 deleteAction->setObjectName("qt_delete_action"_L1);
3291
3292 showHiddenAction = new QAction(q);
3293 showHiddenAction->setObjectName("qt_show_hidden_action"_L1);
3296
3297 newFolderAction = new QAction(q);
3298 newFolderAction->setObjectName("qt_new_folder_action"_L1);
3300}
3301
3303{
3304 Q_Q(QFileDialog);
3305 q->setDirectory(QDir::homePath());
3306}
3307
3308
3310{
3311 if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
3312 return;
3314 item.selection.clear();
3315 const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3316 for (const auto &index : selectedIndexes)
3317 item.selection.append(QPersistentModelIndex(index));
3318}
3319
3326{
3327 Q_Q(QFileDialog);
3328 qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
3329 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
3330 q->setHistory(qFileDialogUi->lookInCombo->history());
3331
3332 const QString newNativePath = QDir::toNativeSeparators(newPath);
3333
3334 // equal paths indicate this was invoked by _q_navigateBack/Forward()
3335 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
3336 if (currentHistoryLocation >= 0)
3338 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
3339 currentHistory.removeLast();
3340 }
3341 currentHistory.append({newNativePath, PersistentModelIndexList()});
3343 }
3344 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
3345 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
3346}
3347
3349{
3350 Q_Q(QFileDialog);
3351 q->setDirectory(historyItem.path);
3352 // Restore selection unless something has changed in the file system
3353 if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
3354 return;
3355 if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
3356 [](const QPersistentModelIndex &i) { return !i.isValid(); })) {
3357 historyItem.selection.clear();
3358 return;
3359 }
3360
3361 QAbstractItemView *view = q->viewMode() == QFileDialog::List
3362 ? static_cast<QAbstractItemView *>(qFileDialogUi->listView)
3363 : static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
3364 auto selectionModel = view->selectionModel();
3365 const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
3367 selectionModel->select(historyItem.selection.constFirst(),
3369 auto it = historyItem.selection.cbegin() + 1;
3370 const auto end = historyItem.selection.cend();
3371 for (; it != end; ++it)
3372 selectionModel->select(*it, flags);
3373
3374 view->scrollTo(historyItem.selection.constFirst());
3375}
3376
3383{
3384 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
3387 }
3388}
3389
3396{
3397 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
3400 }
3401}
3402
3410{
3411 Q_Q(QFileDialog);
3413 QString newDirectory;
3414 if (dir.isRoot()) {
3415 newDirectory = model->myComputer().toString();
3416 } else {
3417 dir.cdUp();
3418 newDirectory = dir.absolutePath();
3419 }
3420 q->setDirectory(newDirectory);
3421 emit q->directoryEntered(newDirectory);
3422}
3423
3430{
3431 Q_Q(QFileDialog);
3432 qFileDialogUi->listView->clearSelection();
3433
3434 QString newFolderString = QFileDialog::tr("New Folder");
3435 QString folderName = newFolderString;
3436 QString prefix = q->directory().absolutePath() + QDir::separator();
3437 if (QFile::exists(prefix + folderName)) {
3438 qlonglong suffix = 2;
3439 while (QFile::exists(prefix + folderName)) {
3440 folderName = newFolderString + QString::number(suffix++);
3441 }
3442 }
3443
3445 QModelIndex index = model->mkdir(parent, folderName);
3446 if (!index.isValid())
3447 return;
3448
3449 index = select(index);
3450 if (index.isValid()) {
3451 qFileDialogUi->treeView->setCurrentIndex(index);
3453 }
3454}
3455
3457{
3458 qFileDialogUi->listModeButton->setDown(true);
3459 qFileDialogUi->detailModeButton->setDown(false);
3460 qFileDialogUi->treeView->hide();
3461 qFileDialogUi->listView->show();
3462 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
3463 qFileDialogUi->listView->doItemsLayout();
3464}
3465
3467{
3468 qFileDialogUi->listModeButton->setDown(false);
3469 qFileDialogUi->detailModeButton->setDown(true);
3470 qFileDialogUi->listView->hide();
3471 qFileDialogUi->treeView->show();
3472 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
3473 qFileDialogUi->treeView->doItemsLayout();
3474}
3475
3482{
3483#if !QT_CONFIG(menu)
3485#else
3486 Q_Q(QFileDialog);
3487 QAbstractItemView *view = nullptr;
3488 if (q->viewMode() == QFileDialog::Detail)
3489 view = qFileDialogUi->treeView;
3490 else
3491 view = qFileDialogUi->listView;
3492 QModelIndex index = view->indexAt(position);
3493 index = mapToSource(index.sibling(index.row(), 0));
3494
3495 QMenu *menu = new QMenu(view);
3497
3498 if (index.isValid()) {
3499 // file context menu
3500 const bool ro = model && model->isReadOnly();
3501 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3506 menu->addSeparator();
3507 }
3509 if (qFileDialogUi->newFolderButton->isVisible()) {
3510 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
3512 }
3513 menu->popup(view->viewport()->mapToGlobal(position));
3514
3515#endif // QT_CONFIG(menu)
3516}
3517
3522{
3523 Q_Q(QFileDialog);
3524 QModelIndex index = qFileDialogUi->listView->currentIndex();
3525 index = index.sibling(index.row(), 0);
3526 if (q->viewMode() == QFileDialog::List)
3527 qFileDialogUi->listView->edit(index);
3528 else
3529 qFileDialogUi->treeView->edit(index);
3530}
3531
3533{
3534 QModelIndex modelIndex = model->index(path);
3535 return model->remove(modelIndex);
3536}
3537
3544{
3545 if (model->isReadOnly())
3546 return;
3547
3548 const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
3549 for (auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
3551 if (index == qFileDialogUi->listView->rootIndex())
3552 continue;
3553
3554 index = mapToSource(index.sibling(index.row(), 0));
3555 if (!index.isValid())
3556 continue;
3557
3559 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
3560
3561 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3562#if QT_CONFIG(messagebox)
3563 Q_Q(QFileDialog);
3564 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
3565 QFileDialog::tr("'%1' is write protected.\nDo you want to delete it anyway?")
3566 .arg(fileName),
3568 return;
3569 else if (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
3570 QFileDialog::tr("Are you sure you want to delete '%1'?")
3571 .arg(fileName),
3573 return;
3574
3575 // the event loop has run, we have to validate if the index is valid because the model might have removed it.
3576 if (!index.isValid())
3577 return;
3578
3579#else
3580 if (!(p & QFile::WriteUser))
3581 return;
3582#endif // QT_CONFIG(messagebox)
3583
3584 if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
3585 if (!removeDirectory(filePath)) {
3586#if QT_CONFIG(messagebox)
3587 QMessageBox::warning(q, q->windowTitle(),
3588 QFileDialog::tr("Could not delete directory."));
3589#endif
3590 }
3591 } else {
3592 model->remove(index);
3593 }
3594 }
3595}
3596
3598{
3599 if (text.startsWith("//"_L1) || text.startsWith(u'\\')) {
3600 qFileDialogUi->listView->selectionModel()->clearSelection();
3601 return;
3602 }
3603
3604 const QStringList multipleFiles = typedFiles();
3605 if (multipleFiles.size() > 0) {
3606 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
3607 QList<QModelIndex> newFiles;
3608 for (const auto &file : multipleFiles) {
3609 QModelIndex idx = model->index(file);
3610 if (oldFiles.removeAll(idx) == 0)
3611 newFiles.append(idx);
3612 }
3613 for (const auto &newFile : std::as_const(newFiles))
3614 select(newFile);
3615 if (lineEdit()->hasFocus()) {
3616 auto *sm = qFileDialogUi->listView->selectionModel();
3617 for (const auto &oldFile : std::as_const(oldFiles))
3619 }
3620 }
3621}
3622
3627{
3628 Q_Q(QFileDialog);
3629 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
3631 if (!button)
3632 return;
3633 const QFileDialog::FileMode fileMode = q->fileMode();
3634
3635 bool enableButton = true;
3636 bool isOpenDirectory = false;
3637
3638 const QStringList files = q->selectedFiles();
3639 QString lineEditText = lineEdit()->text();
3640
3641 if (lineEditText.startsWith("//"_L1) || lineEditText.startsWith(u'\\')) {
3642 button->setEnabled(true);
3644 return;
3645 }
3646
3647 if (files.isEmpty()) {
3648 enableButton = false;
3649 } else if (lineEditText == ".."_L1) {
3650 isOpenDirectory = true;
3651 } else {
3652 switch (fileMode) {
3654 QString fn = files.first();
3655 QModelIndex idx = model->index(fn);
3656 if (!idx.isValid())
3658 if (!idx.isValid() || !model->isDir(idx))
3659 enableButton = false;
3660 break;
3661 }
3662 case QFileDialog::AnyFile: {
3663 QString fn = files.first();
3664 QFileInfo info(fn);
3665 QModelIndex idx = model->index(fn);
3666 QString fileDir;
3668 if (info.isDir()) {
3669 fileDir = info.canonicalFilePath();
3670 } else {
3671 fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
3672 fileName = fn.mid(fileDir.size() + 1);
3673 }
3674 if (lineEditText.contains(".."_L1)) {
3675 fileDir = info.canonicalFilePath();
3677 }
3678
3679 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
3680 enableButton = false;
3681 break;
3682 }
3683 if (idx.isValid() && model->isDir(idx)) {
3684 isOpenDirectory = true;
3685 enableButton = true;
3686 break;
3687 }
3688 if (!idx.isValid()) {
3689 const long maxLength = maxNameLength(fileDir);
3690 enableButton = maxLength < 0 || fileName.size() <= maxLength;
3691 }
3692 break;
3693 }
3696 for (const auto &file : files) {
3697 QModelIndex idx = model->index(file);
3698 if (!idx.isValid())
3700 if (!idx.isValid()) {
3701 enableButton = false;
3702 break;
3703 }
3704 if (idx.isValid() && model->isDir(idx)) {
3705 isOpenDirectory = true;
3706 break;
3707 }
3708 }
3709 break;
3710 default:
3711 break;
3712 }
3713 }
3714
3715 button->setEnabled(enableButton);
3716 updateOkButtonText(isOpenDirectory);
3717}
3718
3723{
3725 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
3726}
3727
3735{
3736 Q_Q(QFileDialog);
3737 // My Computer or a directory
3738 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
3740 if (path.isEmpty() || model->isDir(sourceIndex)) {
3741 const QFileDialog::FileMode fileMode = q->fileMode();
3742 q->setDirectory(path);
3743 emit q->directoryEntered(path);
3744 if (fileMode == QFileDialog::Directory) {
3745 // ### find out why you have to do both of these.
3746 lineEdit()->setText(QString());
3747 lineEdit()->clear();
3748 }
3749 } else {
3750 // Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE)
3751 if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, qFileDialogUi->treeView)
3753 q->accept();
3754 }
3755 }
3756}
3757
3765{
3766 enum { UrlRole = Qt::UserRole + 1 };
3767
3768 #if QT_CONFIG(messagebox)
3769 Q_Q(QFileDialog);
3770#endif
3771 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
3772 qFileDialogUi->lookInCombo->modelColumn(),
3773 qFileDialogUi->lookInCombo->rootModelIndex());
3774 QString path2 = path;
3775 if (!index.isValid())
3777 else {
3778 path2 = index.data(UrlRole).toUrl().toLocalFile();
3779 index = mapFromSource(model->index(path2));
3780 }
3781 QDir dir(path2);
3782 if (!dir.exists())
3783 dir.setPath(getEnvironmentVariable(path2));
3784
3785 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
3787#if QT_CONFIG(messagebox)
3788 } else {
3789 QString message = QFileDialog::tr("%1\nDirectory not found.\nPlease verify the "
3790 "correct directory name was given.");
3791 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
3792#endif // QT_CONFIG(messagebox)
3793 }
3794}
3795
3803{
3804 QStringList nameFilters = options->nameFilters();
3805 if (index == nameFilters.size()) {
3806 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3807 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3808 options->setNameFilters(nameFilters);
3809 }
3810
3811 QString nameFilter = nameFilters.at(index);
3812 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3813 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3814 QString newNameFilterExtension;
3815 if (newNameFilters.size() > 0)
3816 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3817
3819 const QString fileNameExtension = QFileInfo(fileName).suffix();
3820 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3821 const qsizetype fileNameExtensionLength = fileNameExtension.size();
3822 fileName.replace(fileName.size() - fileNameExtensionLength,
3823 fileNameExtensionLength, newNameFilterExtension);
3824 qFileDialogUi->listView->clearSelection();
3826 }
3827 }
3828
3829 model->setNameFilters(newNameFilters);
3830}
3831
3839{
3840 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3841 const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3842 bool stripDirs = fileMode != QFileDialog::Directory;
3843
3844 QStringList allFiles;
3845 for (const auto &index : indexes) {
3846 if (stripDirs && model->isDir(mapToSource(index)))
3847 continue;
3848 allFiles.append(index.data().toString());
3849 }
3850 if (allFiles.size() > 1)
3851 for (qsizetype i = 0; i < allFiles.size(); ++i) {
3852 allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
3853 }
3854
3855 QString finalFiles = allFiles.join(u' ');
3856 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3857 lineEdit()->setText(finalFiles);
3858 else
3860}
3861
3868{
3869 Q_Q(QFileDialog);
3870 QDir::Filters dirFilters = q->filter();
3871 dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
3872 q->setFilter(dirFilters);
3873}
3874
3882{
3883 if (!qFileDialogUi->treeView
3884 || parent != qFileDialogUi->treeView->rootIndex()
3885 || !qFileDialogUi->treeView->selectionModel()
3886 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3887 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3888 return;
3889}
3890
3891void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString &oldName, const QString &newName)
3892{
3893 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3894 if (fileMode == QFileDialog::Directory) {
3895 if (path == rootPath() && lineEdit()->text() == oldName)
3896 lineEdit()->setText(newName);
3897 }
3898}
3899
3901{
3902 Q_Q(QFileDialog);
3903 emit q->urlSelected(file);
3904 if (file.isLocalFile())
3905 emit q->fileSelected(file.toLocalFile());
3906}
3907
3909{
3910 Q_Q(QFileDialog);
3911 emit q->urlsSelected(files);
3912 QStringList localFiles;
3913 for (const QUrl &file : files)
3914 if (file.isLocalFile())
3915 localFiles.append(file.toLocalFile());
3916 if (!localFiles.isEmpty())
3917 emit q->filesSelected(localFiles);
3918}
3919
3921{
3922 Q_Q(QFileDialog);
3923 emit q->currentUrlChanged(file);
3924 if (file.isLocalFile())
3925 emit q->currentChanged(file.toLocalFile());
3926}
3927
3929{
3930 Q_Q(QFileDialog);
3931 emit q->directoryUrlEntered(directory);
3932 if (!directory.isEmpty()) { // Windows native dialogs occasionally emit signals with empty strings.
3933 *lastVisitedDir() = directory;
3934 if (directory.isLocalFile())
3935 emit q->directoryEntered(directory.toLocalFile());
3936 }
3937}
3938
3947
3948#if QT_CONFIG(shortcut)
3949 Q_Q(QFileDialog);
3950 if (event->matches(QKeySequence::Cancel)) {
3951 q->reject();
3952 return true;
3953 }
3954#endif
3955 switch (event->key()) {
3956 case Qt::Key_Backspace:
3958 return true;
3959 case Qt::Key_Back:
3960#ifdef QT_KEYPAD_NAVIGATION
3961 if (QApplicationPrivate::keypadNavigationEnabled())
3962 return false;
3963#endif
3964 case Qt::Key_Left:
3965 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
3967 return true;
3968 }
3969 break;
3970 default:
3971 break;
3972 }
3973 return false;
3974}
3975
3977{
3978#ifdef Q_OS_UNIX
3979 if (string.size() > 1 && string.startsWith(u'$')) {
3980 return QString::fromLocal8Bit(qgetenv(QStringView{string}.mid(1).toLatin1().constData()));
3981 }
3982#else
3983 if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
3984 return QString::fromLocal8Bit(qgetenv(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData()));
3985 }
3986#endif
3987 return string;
3988}
3989
3991 d_ptr = d_pointer;
3992 urlModel = new QUrlModel(this);
3993 urlModel->showFullPath = true;
3994 urlModel->setFileSystemModel(d_ptr->model);
3995 setModel(urlModel);
3996}
3997
3999{
4000 if (model()->rowCount() > 1)
4002
4003 urlModel->setUrls(QList<QUrl>());
4005 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
4006 while (idx.isValid()) {
4008 if (url.isValid())
4009 list.append(url);
4010 idx = idx.parent();
4011 }
4012 // add "my computer"
4013 list.append(QUrl("file:"_L1));
4014 urlModel->addUrls(list, 0);
4015 idx = model()->index(model()->rowCount() - 1, 0);
4016
4017 // append history
4018 QList<QUrl> urls;
4019 for (int i = 0; i < m_history.size(); ++i) {
4020 QUrl path = QUrl::fromLocalFile(m_history.at(i));
4021 if (!urls.contains(path))
4022 urls.prepend(path);
4023 }
4024 if (urls.size() > 0) {
4025 model()->insertRow(model()->rowCount());
4026 idx = model()->index(model()->rowCount()-1, 0);
4027 // ### TODO maybe add a horizontal line before this
4028 model()->setData(idx, QFileDialog::tr("Recent Places"));
4029 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
4030 if (m) {
4031 Qt::ItemFlags flags = m->flags(idx);
4032 flags &= ~Qt::ItemIsEnabled;
4033 m->item(idx.row(), idx.column())->setFlags(flags);
4034 }
4035 urlModel->addUrls(urls, -1, false);
4036 }
4037 setCurrentIndex(0);
4038
4040}
4041
4042// Exact same as QComboBox::paintEvent(), except we elide the text.
4044{
4045 QStylePainter painter(this);
4047
4048 // draw the combobox frame, focusrect and selected etc.
4051
4054 int size = editRect.width() - opt.iconSize.width() - 4;
4055 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
4056 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
4057
4058 // draw the icon and text
4059 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
4060}
4061
4063{
4064 d_ptr = d_pointer;
4066 setWrapping(true);
4069 setContextMenuPolicy(Qt::CustomContextMenu);
4070#if QT_CONFIG(draganddrop)
4071 setDragDropMode(QAbstractItemView::InternalMove);
4072#endif
4073}
4074
4076{
4077 int height = qMax(10, sizeHintForRow(0));
4078 return QSize(QListView::sizeHint().width() * 2, height * 30);
4079}
4080
4082{
4083#ifdef QT_KEYPAD_NAVIGATION
4084 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4086 return;
4087 }
4088#endif // QT_KEYPAD_NAVIGATION
4089
4090 if (!d_ptr->itemViewKeyboardEvent(e))
4092 e->accept();
4093}
4094
4096{
4097 d_ptr = d_pointer;
4099 setRootIsDecorated(false);
4100 setItemsExpandable(false);
4101 setSortingEnabled(true);
4103 header()->setStretchLastSection(false);
4106 setContextMenuPolicy(Qt::CustomContextMenu);
4107#if QT_CONFIG(draganddrop)
4108 setDragDropMode(QAbstractItemView::InternalMove);
4109#endif
4110}
4111
4113{
4114#ifdef QT_KEYPAD_NAVIGATION
4115 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4117 return;
4118 }
4119#endif // QT_KEYPAD_NAVIGATION
4120
4121 if (!d_ptr->itemViewKeyboardEvent(e))
4123 e->accept();
4124}
4125
4127{
4128 int height = qMax(10, sizeHintForRow(0));
4130 return QSize(sizeHint.width() * 4, height * 30);
4131}
4132
4138{
4139#ifdef QT_KEYPAD_NAVIGATION
4140 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4142 return;
4143 }
4144#endif // QT_KEYPAD_NAVIGATION
4145
4146#if QT_CONFIG(shortcut)
4147 int key = e->key();
4148#endif
4150#if QT_CONFIG(shortcut)
4151 if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
4152#endif
4153 e->accept();
4154}
4155
4156#if QT_CONFIG(fscompleter)
4157
4159{
4160 const QFileSystemModel *dirModel;
4161 if (proxyModel)
4162 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
4163 else
4164 dirModel = sourceModel;
4165 QString currentLocation = dirModel->rootPath();
4167 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
4168#if defined(Q_OS_UNIX)
4169 if (currentLocation == QDir::separator())
4170 return path.remove(0, currentLocation.size());
4171#endif
4172 if (currentLocation.endsWith(u'/'))
4173 return path.remove(0, currentLocation.size());
4174 else
4175 return path.remove(0, currentLocation.size()+1);
4176 }
4177 return index.data(QFileSystemModel::FilePathRole).toString();
4178}
4179
4181{
4182 if (path.isEmpty())
4183 return QStringList(completionPrefix());
4184
4187#if defined(Q_OS_WIN)
4188 if (pathCopy == "\\"_L1 || pathCopy == "\\\\"_L1)
4189 return QStringList(pathCopy);
4190 QString doubleSlash("\\\\"_L1);
4191 if (pathCopy.startsWith(doubleSlash))
4192 pathCopy = pathCopy.mid(2);
4193 else
4194 doubleSlash.clear();
4195#elif defined(Q_OS_UNIX)
4196 {
4197 QString tildeExpanded = qt_tildeExpansion(pathCopy);
4198 if (tildeExpanded != pathCopy) {
4199 QFileSystemModel *dirModel;
4200 if (proxyModel)
4201 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
4202 else
4203 dirModel = sourceModel;
4204 dirModel->fetchMore(dirModel->index(tildeExpanded));
4205 }
4206 pathCopy = std::move(tildeExpanded);
4207 }
4208#endif
4209
4210#if defined(Q_OS_WIN)
4211 QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
4212 if (!doubleSlash.isEmpty() && !parts.isEmpty())
4213 parts[0].prepend(doubleSlash);
4214 if (pathCopy.endsWith(sep))
4215 parts.append(QString());
4216#else
4217 QStringList parts = pathCopy.split(sep);
4218 if (pathCopy[0] == sep) // read the "/" at the beginning as the split removed it
4219 parts[0] = sep;
4220#endif
4221
4222#if defined(Q_OS_WIN)
4223 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
4224#else
4225 bool startsFromRoot = pathCopy[0] == sep;
4226#endif
4227 if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
4228 const QFileSystemModel *dirModel;
4229 if (proxyModel)
4230 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
4231 else
4232 dirModel = sourceModel;
4233 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
4234#if defined(Q_OS_WIN)
4235 if (currentLocation.endsWith(u':'))
4236 currentLocation.append(sep);
4237#endif
4238 if (currentLocation.contains(sep) && path != currentLocation) {
4239 QStringList currentLocationList = splitPath(currentLocation);
4240 while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) == ".."_L1) {
4241 parts.removeFirst();
4242 currentLocationList.removeLast();
4243 }
4244 if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
4245 currentLocationList.removeLast();
4246 return currentLocationList + parts;
4247 }
4248 }
4249 return parts;
4250}
4251
4252#endif // QT_CONFIG(completer)
4253
4254
4256
4257#include "moc_qfiledialog.cpp"
void setText(const QString &text)
QString text
the text shown on the button
virtual void setOptions(Options)
Sets options that affect the icon provider.
virtual Options options() const
Returns all the options that affect the icon provider.
The QAbstractItemDelegate class is used to display and edit data items from a model.
virtual Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
virtual Q_INVOKABLE bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
Sets the role data for the item at index to value.
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of columns for the children of the given parent.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
The QAbstractItemView class provides the basic functionality for item view classes.
SelectionMode
This enum indicates how the view responds to user selections:
void setEditTriggers(EditTriggers triggers)
void setTextElideMode(Qt::TextElideMode mode)
void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
void keyPressEvent(QKeyEvent *event) override
This function is called with the given event when a key event is sent to the widget.
void edit(const QModelIndex &index)
Starts editing the item corresponding to the given index if it is editable.
virtual int sizeHintForRow(int row) const
Returns the height size hint for the specified row or -1 if there is no model.
The QAbstractProxyModel class provides a base class for proxy item models that can do sorting,...
QAbstractItemModel * sourceModel
the source model of this proxy model.
virtual void setSourceModel(QAbstractItemModel *sourceModel)
Sets the given sourceModel to be processed by the proxy model.
The QActionGroup class groups actions together.
QList< QAction * > actions() const
Returns the list of this groups's actions.
void setExclusive(bool)
Enable or disable the group exclusion checking.
The QAction class provides an abstraction for user commands that can be added to different user inter...
Definition qaction.h:30
void setChecked(bool)
Definition qaction.cpp:877
void setText(const QString &text)
Definition qaction.cpp:611
void setEnabled(bool)
Definition qaction.cpp:927
void setCheckable(bool)
Definition qaction.cpp:832
bool isChecked() const
Definition qaction.cpp:892
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
QByteArray sliced(qsizetype pos) const
Definition qbytearray.h:163
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore
Definition qchar.h:48
virtual void initStyleOption(QStyleOptionComboBox *option) const
Initialize option with the values from this QComboBox.
@ AdjustToContentsOnFirstShow
Definition qcombobox.h:83
virtual void setModel(QAbstractItemModel *model)
Sets the model to be model.
QAbstractItemModel * model() const
Returns the model used by the combobox.
virtual void showPopup()
Displays the list of items in the combobox.
void setCurrentIndex(int index)
QString completionPrefix
the completion prefix used to provide completions.
Definition qcompleter.h:26
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
\inmodule QtCore\reentrant
Definition qdatastream.h:30
StandardButton
These enums describe flags for standard buttons.
bool nativeDialogInUse
Definition qdialog_p.h:86
The QDialog class is the base class of dialog windows.
Definition qdialog.h:19
virtual int exec()
Shows the dialog as a \l{QDialog::Modal Dialogs}{modal dialog}, blocking until the user closes it.
Definition qdialog.cpp:539
DialogCode
The value returned by a modal dialog.
Definition qdialog.h:30
@ Accepted
Definition qdialog.h:30
virtual void done(int)
Closes the dialog and sets its result code to r.
Definition qdialog.cpp:598
virtual void open()
Definition qdialog.cpp:499
virtual void accept()
Hides the modal dialog and sets the result code to Accepted.
Definition qdialog.cpp:624
\inmodule QtCore
Definition qdir.h:19
static bool isRelativePath(const QString &path)
Returns true if path is relative; returns false if it is absolute.
Definition qdir.cpp:2409
QString path() const
Returns the path.
Definition qdir.cpp:653
static QDir current()
Returns the application's current directory.
Definition qdir.h:216
static QChar separator()
Returns the native directory separator: "/" under Unix and "\\" under Windows.
Definition qdir.h:206
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2395
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
static QString homePath()
Returns the absolute path of the user's home directory.
Definition qdir.cpp:2100
bool isEmpty(Filters filters=Filters(AllEntries|NoDotAndDotDot)) const
Returns whether the directory is empty.
Definition qdir.cpp:1967
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2051
@ Files
Definition qdir.h:22
@ Hidden
Definition qdir.h:34
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
QCompleter that can deal with QFileSystemModel.
QStringList splitPath(const QString &path) const override
Splits the given path into strings that are used to match at each level in the model().
QString pathFromIndex(const QModelIndex &index) const override
Returns the path for the given index.
QAbstractProxyModel * proxyModel
QFileSystemModel * sourceModel
void setHistory(const QStringList &paths)
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
void showPopup() override
Displays the list of items in the combobox.
void paintEvent(QPaintEvent *) override
\reimp
void keyPressEvent(QKeyEvent *e) override
FIXME: this is a hack to avoid propagating key press events to the dialog and from there to the "Ok" ...
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
QSize sizeHint() const override
void keyPressEvent(QKeyEvent *e) override
QStringList mimeTypeFilters() const
QList< QUrl > initiallySelectedFiles() const
void setHistory(const QStringList &paths)
bool isLabelExplicitlySet(DialogLabel label)
QDir::Filters filter() const
QString initiallySelectedNameFilter() const
void setWindowTitle(const QString &)
QString labelText(DialogLabel label) const
void setNameFilters(const QStringList &filters)
AcceptMode acceptMode() const
void setInitiallySelectedNameFilter(const QString &)
QList< QUrl > sidebarUrls() const
QStringList nameFilters() const
FileDialogOptions options() const
QStringList history() const
void setSidebarUrls(const QList< QUrl > &urls)
static QString defaultNameFilterString()
void setInitiallySelectedFiles(const QList< QUrl > &)
QModelIndex select(const QModelIndex &index) const
QModelIndex mapFromSource(const QModelIndex &index) const
void emitFilesSelected(const QStringList &files)
void _q_nativeEnterDirectory(const QUrl &directory)
static void setLastVisitedDirectory(const QUrl &dir)
void navigate(HistoryItem &)
QList< QPersistentModelIndex > PersistentModelIndexList
void _q_currentChanged(const QModelIndex &index)
void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)
QString getEnvironmentVariable(const QString &string)
void _q_fileRenamed(const QString &path, const QString &oldName, const QString &newName)
static long maxNameLength(const QString &path)
bool removeDirectory(const QString &path)
QAbstractItemView * currentView() const
QScopedPointer< Ui_QFileDialog > qFileDialogUi
void _q_rowsInserted(const QModelIndex &parent)
void _q_useNameFilter(int index)
QFileSystemModel * model
void _q_emitUrlsSelected(const QList< QUrl > &files)
QAction * showHiddenAction
void _q_enterDirectory(const QModelIndex &index)
void _q_pathChanged(const QString &)
QList< QUrl > sidebarUrls
static QString toInternal(const QString &path)
void _q_emitUrlSelected(const QUrl &file)
QLineEdit * lineEdit() const
QStringList typedFiles() const
QList< QUrl > selectedFiles_sys() const
QFileIconProvider defaultIconProvider
QAction * newFolderAction
QList< HistoryItem > currentHistory
virtual void helperPrepareShow(QPlatformDialogHelper *) override
void setRootIndex(const QModelIndex &index) const
QList< QUrl > userSelectedFiles() const
QList< QUrl > addDefaultSuffixToUrls(const QList< QUrl > &urlsToFix) const
bool restoreWidgetState(QStringList &history, int splitterPosition)
QString rootPath() const
QModelIndex rootIndex() const
QModelIndex mapToSource(const QModelIndex &index) const
void _q_showContextMenu(const QPoint &position)
bool canBeNativeDialog() const override
void updateOkButtonText(bool saveAsOnFolder=false)
QPlatformFileDialogHelper * platformFileDialogHelper() const
void _q_showHeader(QAction *)
bool itemViewKeyboardEvent(QKeyEvent *event)
void init(const QFileDialogArgs &args)
virtual void initHelper(QPlatformDialogHelper *) override
void _q_autoCompleteFileName(const QString &)
virtual void helperDone(QDialog::DialogCode, QPlatformDialogHelper *) override
void _q_goToDirectory(const QString &)
QSharedPointer< QFileDialogOptions > options
void _q_nativeCurrentChanged(const QUrl &file)
void _q_goToUrl(const QUrl &url)
QStringList addDefaultSuffixToFiles(const QStringList &filesToFix) const
QByteArray splitterState
bool usingWidgets() const
void keyPressEvent(QKeyEvent *e) override
QSize sizeHint() const override
void setFileDialogPrivate(QFileDialogPrivate *d_pointer)
The QFileDialog class provides a dialog that allow users to select files or directories.
Definition qfiledialog.h:28
QList< QUrl > sidebarUrls() const
Options options
the various options that affect the look and feel of the dialog
Definition qfiledialog.h:34
void setFilter(QDir::Filters filters)
FileMode
This enum is used to indicate what the user may select in the file dialog; i.e.
Definition qfiledialog.h:40
static QString getExistingDirectory(QWidget *parent=nullptr, const QString &caption=QString(), const QString &dir=QString(), Options options=ShowDirsOnly)
This is a convenience static function that will return an existing directory selected by the user.
static QList< QUrl > getOpenFileUrls(QWidget *parent=nullptr, const QString &caption=QString(), const QUrl &dir=QUrl(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options(), const QStringList &supportedSchemes=QStringList())
This is a convenience static function that will return one or more existing files selected by the use...
bool restoreState(const QByteArray &state)
~QFileDialog()
Destroys the file dialog.
void currentChanged(const QString &path)
When the current file changes for local operations, this signal is emitted with the new file name as ...
QString selectedNameFilter() const
void selectFile(const QString &filename)
Selects the given filename in the file dialog.
QFileDialog(QWidget *parent, Qt::WindowFlags f)
bool testOption(Option option) const
QStringList nameFilters() const
static QString getSaveFileName(QWidget *parent=nullptr, const QString &caption=QString(), const QString &dir=QString(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options())
This is a convenience static function that will return a file name selected by the user.
void setDefaultSuffix(const QString &suffix)
void filesSelected(const QStringList &files)
When the selection changes for local operations and the dialog is accepted, this signal is emitted wi...
void setSupportedSchemes(const QStringList &schemes)
static QUrl getExistingDirectoryUrl(QWidget *parent=nullptr, const QString &caption=QString(), const QUrl &dir=QUrl(), Options options=ShowDirsOnly, const QStringList &supportedSchemes=QStringList())
This is a convenience static function that will return an existing directory selected by the user.
void setNameFilters(const QStringList &filters)
static QString getOpenFileName(QWidget *parent=nullptr, const QString &caption=QString(), const QString &dir=QString(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options())
This is a convenience static function that returns an existing file selected by the user.
AcceptMode acceptMode
the accept mode of the dialog
Definition qfiledialog.h:32
QUrl directoryUrl() const
Returns the url of the directory currently being displayed in the dialog.
void fileSelected(const QString &file)
When the selection changes for local operations and the dialog is accepted, this signal is emitted wi...
void setViewMode(ViewMode mode)
FileMode fileMode
the file mode of the dialog
Definition qfiledialog.h:31
QStringList selectedFiles() const
Returns a list of strings containing the absolute paths of the selected files in the dialog.
void setAcceptMode(AcceptMode mode)
void selectNameFilter(const QString &filter)
QStringList supportedSchemes
the URL schemes that the file dialog should allow navigating to.
Definition qfiledialog.h:35
void setHistory(const QStringList &paths)
Sets the browsing history of the filedialog to contain the given paths.
@ DontConfirmOverwrite
Definition qfiledialog.h:51
@ DontUseCustomDirectoryIcons
Definition qfiledialog.h:55
@ DontResolveSymlinks
Definition qfiledialog.h:50
@ HideNameFilterDetails
Definition qfiledialog.h:54
@ DontUseNativeDialog
Definition qfiledialog.h:52
QDir directory() const
Returns the directory currently being displayed in the dialog.
ViewMode viewMode
the way files and directories are displayed in the dialog
Definition qfiledialog.h:30
void setDirectory(const QString &directory)
Sets the file dialog's current directory.
static QUrl getOpenFileUrl(QWidget *parent=nullptr, const QString &caption=QString(), const QUrl &dir=QUrl(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options(), const QStringList &supportedSchemes=QStringList())
This is a convenience static function that returns an existing file selected by the user.
void selectUrl(const QUrl &url)
Selects the given url in the file dialog.
static void getOpenFileContent(const QString &nameFilter, const std::function< void(const QString &, const QByteArray &)> &fileContentsReady)
This is a convenience static function that will return the content of a file selected by the user.
void setFileMode(FileMode mode)
void setNameFilter(const QString &filter)
DialogLabel
\value LookIn \value FileName \value FileType \value Accept \value Reject
Definition qfiledialog.h:44
QByteArray saveState() const
QStringList history() const
Returns the browsing history of the filedialog as a list of paths.
AcceptMode
\value AcceptOpen \value AcceptSave
Definition qfiledialog.h:42
void setLabelText(DialogLabel label, const QString &text)
Sets the text shown in the filedialog in the specified label.
void accept() override
\reimp
static QUrl getSaveFileUrl(QWidget *parent=nullptr, const QString &caption=QString(), const QUrl &dir=QUrl(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options(), const QStringList &supportedSchemes=QStringList())
This is a convenience static function that returns a file selected by the user.
void setSidebarUrls(const QList< QUrl > &urls)
static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint=QString())
This is a convenience static function that saves fileContent to a file, using a file name and locatio...
QAbstractItemDelegate * itemDelegate() const
Returns the item delegate used to render the items in the views in the filedialog.
void changeEvent(QEvent *e) override
\reimp
static QStringList getOpenFileNames(QWidget *parent=nullptr, const QString &caption=QString(), const QString &dir=QString(), const QString &filter=QString(), QString *selectedFilter=nullptr, Options options=Options())
This is a convenience static function that will return one or more existing files selected by the use...
QList< QUrl > selectedUrls() const
Returns a list of urls containing the selected files in the dialog.
QString selectedMimeTypeFilter() const
QString defaultSuffix
suffix added to the filename if no other suffix was specified
Definition qfiledialog.h:33
void setItemDelegate(QAbstractItemDelegate *delegate)
Sets the item delegate used to render items in the views in the file dialog to the given delegate.
virtual void open()
Definition qdialog.cpp:499
QString labelText(DialogLabel label) const
Returns the text shown in the filedialog in the specified label.
void setDirectoryUrl(const QUrl &directory)
Sets the file dialog's current directory url.
void setOption(Option option, bool on=true)
void setOptions(Options options)
QAbstractFileIconProvider * iconProvider() const
Returns the icon provider used by the filedialog.
ViewMode
This enum describes the view mode of the file dialog; i.e.
Definition qfiledialog.h:38
void setIconProvider(QAbstractFileIconProvider *provider)
Sets the icon provider used by the filedialog to the specified provider.
QDir::Filters filter() const
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
bool isSymLink() const
Returns true if this object points to a symbolic link, shortcut, or alias; otherwise returns false.
QString suffix() const
Returns the suffix (extension) of the file.
QString fileName() const
Returns the name of the file, excluding the path.
QString absoluteFilePath() const
Returns an absolute path including the file name.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QString absolutePath() const
Returns a file's path absolute path.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
QDir absoluteDir() const
Returns the file's absolute path as a QDir object.
bool isAbsolute() const
Returns true if the file path is absolute, otherwise returns false (i.e.
Definition qfileinfo.h:116
QString path() const
Returns the file's path.
bool exists() const
Returns true if the file exists; otherwise returns false.
The QFileSystemModel class provides a data model for the local filesystem.
QModelIndex mkdir(const QModelIndex &parent, const QString &name)
Create a directory with the name in the parent model index.
QDir rootDirectory() const
The currently set directory.
void setNameFilterDisables(bool enable)
QString rootPath() const
The currently set root path.
QFileInfo fileInfo(const QModelIndex &index) const
Returns the QFileInfo for the item stored in the model under the given index.
void setIconProvider(QAbstractFileIconProvider *provider)
Sets the provider of file icons for the directory model.
QVariant myComputer(int role=Qt::DisplayRole) const
Returns the data stored under the given role for the item "My Computer".
void fetchMore(const QModelIndex &parent) override
\reimp
void setReadOnly(bool enable)
void setNameFilters(const QStringList &filters)
Sets the name filters to apply against the existing files.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
\reimp
void setFilter(QDir::Filters filters)
Sets the directory model's filter to that specified by filters.
bool remove(const QModelIndex &index)
Removes the model item index from the file system model and {deletes the corresponding file from the ...
bool isDir(const QModelIndex &index) const
Returns true if the model item index represents a directory; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
\reentrant \inmodule QtGui
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
static Qt::KeyboardModifiers keyboardModifiers()
Returns the current state of the modifier keys on the keyboard.
The QHeaderView class provides a header row or header column for item views.
Definition qheaderview.h:18
QSize sizeHint() const override
Returns a suitable size hint for this header.
bool isSectionHidden(int logicalIndex) const
Returns true if the section specified by logicalIndex is explicitly hidden from the user; otherwise r...
void setSortIndicator(int logicalIndex, Qt::SortOrder order)
Sets the sort indicator for the section specified by the given logicalIndex in the direction specifie...
void resizeSection(int logicalIndex, int size)
Resizes the section specified by logicalIndex to size measured in pixels.
void setStretchLastSection(bool stretch)
bool restoreState(const QByteArray &state)
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
\inmodule QtCore
The QKeyEvent class describes a key event.
Definition qevent.h:423
The QLineEdit widget is a one-line text editor.
Definition qlineedit.h:28
void selectAll()
Selects all the text (i.e.
void clear()
Clears the contents of the line edit.
void setText(const QString &)
QString text
the line edit's text.
Definition qlineedit.h:32
void keyPressEvent(QKeyEvent *) override
Converts the given key press event into a line edit action.
void setWrapping(bool enable)
void setResizeMode(ResizeMode mode)
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
T value(qsizetype i) const
Definition qlist.h:661
const_reverse_iterator crbegin() const noexcept
Definition qlist.h:621
qsizetype removeAll(const AT &t)
Definition qlist.h:575
void prepend(rvalue_ref t)
Definition qlist.h:456
const T & constFirst() const noexcept
Definition qlist.h:630
void reserve(qsizetype size)
Definition qlist.h:746
const_iterator cend() const noexcept
Definition qlist.h:614
void append(parameter_type t)
Definition qlist.h:441
const_iterator cbegin() const noexcept
Definition qlist.h:613
void clear()
Definition qlist.h:417
const_reverse_iterator crend() const noexcept
Definition qlist.h:622
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition qmenu.h:26
void popup(const QPoint &pos, QAction *at=nullptr)
Displays the menu so that the action atAction will be at the specified global position p.
Definition qmenu.cpp:2288
QAction * addSeparator()
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:1899
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3124
The QMessageBox class provides a modal dialog for informing the user or for asking the user a questio...
Definition qmessagebox.h:21
static StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
\inmodule QtCore
const char * key(int index) const
Returns the key with the given index, or \nullptr if no such key exists.
int keyToValue(const char *key, bool *ok=nullptr) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
\inmodule QtCore
QMimeType mimeTypeForName(const QString &nameOrAlias) const
Returns a MIME type for nameOrAlias or an invalid one if none found.
\inmodule QtCore
Definition qmimetype.h:25
\inmodule QtCore
QVariant data(int role=Qt::DisplayRole) const
Returns the data for the given role for the item referred to by the index.
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr const QAbstractItemModel * model() const noexcept
Returns a pointer to the model containing the item that this index refers to.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
QObject * q_ptr
Definition qobject.h:60
QObject * parent
Definition qobject.h:61
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:114
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
The QPlatformDialogHelper class allows for platform-specific customization of dialogs.
The QPlatformFileDialogHelper class allows for platform-specific customization of file dialogs.
static QStringList cleanFilterList(const QString &filter)
\inmodule QtCore\reentrant
Definition qpoint.h:23
The QPushButton widget provides a command button.
Definition qpushbutton.h:20
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
\inmodule QtCore \reentrant
\inmodule QtCore
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qsettings.h:30
void setValue(QAnyStringView key, const QVariant &value)
Sets the value of setting key to value.
QVariant value(QAnyStringView key, const QVariant &defaultValue) const
Returns the value for setting key.
QStringList childGroups() const
Returns a list of all key top-level groups that contain keys that can be read using the QSettings obj...
void beginGroup(QAnyStringView prefix)
Appends prefix to the current group.
The QShortcut class is used to create keyboard shortcuts.
Definition qshortcut.h:19
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:443
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
The QStandardItemModel class provides a generic model for storing custom data.
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6737
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
static QString fromStdString(const std::string &s)
Definition qstring.h:1322
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
std::string toStdString() const
Returns a std::string object with the data contained in this QString.
Definition qstring.h:1319
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
QString simplified() const &
Definition qstring.h:384
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
QString sliced(qsizetype pos) const
Definition qstring.h:341
QString & append(QChar c)
Definition qstring.cpp:3227
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
\variable QStyleOptionToolButton::features
QFontMetrics fontMetrics
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget=nullptr) const =0
Returns the rectangle containing the specified subControl of the given complex control (with the styl...
@ SH_ItemView_ActivateItemOnSingleClick
Definition qstyle.h:644
@ SP_ArrowForward
Definition qstyle.h:770
@ SP_FileDialogListView
Definition qstyle.h:751
@ SP_ArrowBack
Definition qstyle.h:769
@ SP_FileDialogNewFolder
Definition qstyle.h:747
@ SP_FileDialogDetailedView
Definition qstyle.h:748
@ SP_FileDialogToParent
Definition qstyle.h:746
@ CE_ComboBoxLabel
Definition qstyle.h:221
@ CC_ComboBox
Definition qstyle.h:333
@ SC_ComboBoxEditField
Definition qstyle.h:365
void setItemsExpandable(bool enable)
QHeaderView * header() const
Returns the header for the tree view.
void keyPressEvent(QKeyEvent *event) override
\reimp
void setRootIsDecorated(bool show)
void setSortingEnabled(bool enable)
void setUrls(const QList< QUrl > &list)
Definition qsidebar.cpp:195
void addUrls(const QList< QUrl > &urls, int row=-1, bool move=true)
Add urls list into the list at row.
Definition qsidebar.cpp:209
bool showFullPath
Definition qsidebar_p.h:64
void setFileSystemModel(QFileSystemModel *model)
QFileSystemModel to get index's from, clears existing rows.
Definition qsidebar.cpp:264
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3354
static QList< QUrl > fromStringList(const QStringList &uris, ParsingMode mode=TolerantMode)
Definition qurl.cpp:3646
bool isLocalFile() const
Definition qurl.cpp:3431
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2494
static QStringList toStringList(const QList< QUrl > &uris, FormattingOptions options=FormattingOptions(PrettyDecoded))
Definition qurl.cpp:3630
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1874
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
@ PreferLocalFile
Definition qurl.h:114
void setPath(const QString &path, ParsingMode mode=DecodedMode)
Sets the path of the URL to path.
Definition qurl.cpp:2411
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
QStringList toStringList() const
Returns the variant as a QStringList if the variant has userType() \l QMetaType::QStringList,...
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
QWidgetData data
Definition qwidget_p.h:696
QList< QAction * > actions
Definition qwidget_p.h:701
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setAttribute(Qt::WidgetAttribute, bool on=true)
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute.
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
void setEnabled(bool)
Definition qwidget.cpp:3365
QPalette palette
the widget's palette
Definition qwidget.h:132
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7956
virtual void setVisible(bool visible)
Definition qwidget.cpp:8329
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9428
QStyle * style() const
Definition qwidget.cpp:2607
bool hasFocus() const
Definition qwidget.cpp:6471
bool isVisible() const
Definition qwidget.h:874
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
bool visible
whether the widget is visible
Definition qwidget.h:144
QString text
QPushButton * button
[2]
void textChanged(const QString &newText)
double e
QSet< QString >::iterator it
auto signal
QStyleOptionButton opt
else opt state
[0]
Token token
Definition keywords.cpp:444
Combined button and popup list for selecting options.
void saveFile(const QByteArray &data, const std::string &fileNameHint)
void openFile(const std::string &accept, const std::function< void(bool fileSelected)> &fileDialogClosed, const std::function< char *(uint64_t size, const std::string &name)> &acceptFile, const std::function< void()> &fileDataReady)
@ CTRL
@ SHIFT
@ NavigationModeKeypadDirectional
@ WA_WState_ExplicitShowHide
Definition qnamespace.h:334
@ WA_Resized
Definition qnamespace.h:307
@ WA_DontShowOnScreen
Definition qnamespace.h:382
@ WA_WState_Hidden
Definition qnamespace.h:296
@ WA_DeleteOnClose
Definition qnamespace.h:320
@ Horizontal
Definition qnamespace.h:98
@ ImhNoPredictiveText
@ UserRole
@ DisplayRole
@ Key_Backspace
Definition qnamespace.h:661
@ Key_Left
Definition qnamespace.h:672
@ Key_Up
Definition qnamespace.h:673
@ Key_H
Definition qnamespace.h:553
@ Key_Back
Definition qnamespace.h:841
@ AscendingOrder
Definition qnamespace.h:121
@ AltModifier
@ AA_DontUseNativeDialogs
Definition qnamespace.h:457
@ CaseInsensitive
@ CaseSensitive
@ SkipEmptyParts
Definition qnamespace.h:127
@ ActionsContextMenu
@ CustomContextMenu
@ ElideMiddle
Definition qnamespace.h:190
@ ItemIsDropEnabled
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLStreamKHR stream
const char * mimeType
static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)
static const qint32 QFileDialogMagic
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)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLenum mode
const GLfloat * m
GLuint64 key
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLfloat GLfloat f
GLint GLsizei width
GLsizei const GLuint * paths
GLuint GLsizei const GLchar * label
[43]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
const GLchar * marker
GLuint name
GLint first
GLsizei bufSize
GLfloat GLfloat GLfloat GLfloat h
struct _cl_event * event
GLuint res
GLsizei maxLength
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
static QString absolutePath(const QString &path)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static constexpr QChar sep
SSL_CTX int(*) void arg)
#define QStringLiteral(str)
#define QT_BEGIN_INCLUDE_NAMESPACE
#define Q_AUTOTEST_EXPORT
#define QT_END_INCLUDE_NAMESPACE
#define QT_CONFIG(feature)
#define tr(X)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define emit
#define Q_UNUSED(x)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
int qint32
Definition qtypes.h:44
ptrdiff_t qsizetype
Definition qtypes.h:70
qint64 qlonglong
Definition qtypes.h:58
const char className[16]
[1]
Definition qwizard.cpp:100
QSqlQueryModel * model
[16]
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QFileInfo info(fileName)
[8]
QSettings settings("MySoft", "Star Runner")
[0]
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
QObject::connect nullptr
myObject disconnect()
[26]
QMimeDatabase db
[0]
QString dir
[11]
XML files xml auto fileContentReady
[14]
QStringList fileNames
[4]
QFileDialog dialog(this)
[1]
QStringList files
[8]
dialog setFileMode(QFileDialog::AnyFile)
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
QGraphicsItem * item
QPainter painter(this)
[7]
QCompleter * completer
[0]
QMenu menu
[5]
QQuickView * view
[0]
view create()
char * toString(const MyType &t)
[31]
QJSValueList args
QFileDialogArgs(const QUrl &url={})
PersistentModelIndexList selection
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:955
bool contains(const AT &t) const noexcept
Definition qlist.h:44
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent