Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
321#include <QMetaEnum>
322#if QT_CONFIG(shortcut)
323# include <qshortcut.h>
324#endif
326
332QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
333 : QDialog(*new QFileDialogPrivate, parent, f)
334{
335 Q_D(QFileDialog);
337 d->init(args);
338}
339
348 const QString &caption,
349 const QString &directory,
350 const QString &filter)
351 : QDialog(*new QFileDialogPrivate, parent, { })
352{
353 Q_D(QFileDialog);
355 args.filter = filter;
356 args.caption = caption;
357 d->init(args);
358}
359
364 : QDialog(*new QFileDialogPrivate, args.parent, { })
365{
366 Q_D(QFileDialog);
367 d->init(args);
368 setFileMode(args.mode);
369 setOptions(args.options);
370 selectFile(args.selection);
371}
372
377{
378#if QT_CONFIG(settings)
379 Q_D(QFileDialog);
380 d->saveSettings();
381#endif
382}
383
398void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
399{
400 Q_D(QFileDialog);
401 if (!d->nativeDialogInUse)
402 d->qFileDialogUi->sidebar->setUrls(urls);
403}
404
409QList<QUrl> QFileDialog::sidebarUrls() const
410{
411 Q_D(const QFileDialog);
412 return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
413}
414
415static const qint32 QFileDialogMagic = 0xbe;
416
425{
426 Q_D(const QFileDialog);
427 int version = 4;
430 stream.setVersion(QDataStream::Qt_5_0);
431
433 stream << qint32(version);
434 if (d->usingWidgets()) {
435 stream << d->qFileDialogUi->splitter->saveState();
436 stream << d->qFileDialogUi->sidebar->urls();
437 } else {
438 stream << d->splitterState;
439 stream << d->sidebarUrls;
440 }
441 stream << history();
442 stream << *lastVisitedDir();
443 if (d->usingWidgets())
444 stream << d->qFileDialogUi->treeView->header()->saveState();
445 else
446 stream << d->headerData;
447 stream << qint32(viewMode());
448 return data;
449}
450
461{
462 Q_D(QFileDialog);
463 QByteArray sd = state;
465 stream.setVersion(QDataStream::Qt_5_0);
466 if (stream.atEnd())
467 return false;
469 QUrl currentDirectory;
471 qint32 v;
473 stream >> marker;
474 stream >> v;
475 // the code below only supports versions 3 and 4
476 if (marker != QFileDialogMagic || (v != 3 && v != 4))
477 return false;
478
479 stream >> d->splitterState
480 >> d->sidebarUrls
481 >> history;
482 if (v == 3) {
483 QString currentDirectoryString;
484 stream >> currentDirectoryString;
485 currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
486 } else {
487 stream >> currentDirectory;
488 }
489 stream >> d->headerData
490 >> viewMode;
491
492 setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
494
495 if (!d->usingWidgets())
496 return true;
497
498 return d->restoreWidgetState(history, -1);
499}
500
505{
506 Q_D(QFileDialog);
507 if (e->type() == QEvent::LanguageChange) {
508 d->retranslateWindowTitle();
509 d->retranslateStrings();
510 }
512}
513
515 :
516#if QT_CONFIG(proxymodel)
517 proxyModel(nullptr),
518#endif
519 model(nullptr),
520 currentHistoryLocation(-1),
521 renameAction(nullptr),
522 deleteAction(nullptr),
523 showHiddenAction(nullptr),
524 useDefaultCaption(true),
525 qFileDialogUi(nullptr),
526 options(QFileDialogOptions::create())
527{
528}
529
533
550
563
565{
566 if (code == QDialog::Accepted) {
567 Q_Q(QFileDialog);
568 q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
569 q->setSidebarUrls(options->sidebarUrls());
570 q->setHistory(options->history());
571 }
572}
573
575{
576 Q_Q(QFileDialog);
577 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
578 return;
579 if (q->acceptMode() == QFileDialog::AcceptOpen) {
580 const QFileDialog::FileMode fileMode = q->fileMode();
581 if (fileMode == QFileDialog::Directory)
582 q->setWindowTitle(QFileDialog::tr("Find Directory"));
583 else
584 q->setWindowTitle(QFileDialog::tr("Open"));
585 } else
586 q->setWindowTitle(QFileDialog::tr("Save As"));
587
588 setWindowTitle = q->windowTitle();
589}
590
592{
593 *lastVisitedDir() = dir;
594}
595
601
603{
606 } else {
607 switch (q_func()->fileMode()) {
609 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("Directory:"));
610 break;
611 default:
612 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("File &name:"));
613 break;
614 }
615 }
616}
617
623
625{
626 Q_Q(QFileDialog);
627 // 'Save as' at a folder: Temporarily change to "Open".
628 if (saveAsOnFolder) {
629 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Open"));
632 return;
633 } else {
634 switch (q->fileMode()) {
636 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Choose"));
637 break;
638 default:
640 q->acceptMode() == QFileDialog::AcceptOpen ?
641 QFileDialog::tr("&Open") :
642 QFileDialog::tr("&Save"));
643 break;
644 }
645 }
646}
647
653
655{
656 Q_Q(QFileDialog);
657 /* WIDGETS */
660 if (!usingWidgets())
661 return;
662
663 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
664 QAbstractItemModel *abstractModel = model;
665#if QT_CONFIG(proxymodel)
666 if (proxyModel)
667 abstractModel = proxyModel;
668#endif
669 const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
670 for (int i = 1; i < total; ++i) {
671 actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
672 }
673
674 /* MENU ACTIONS */
675 renameAction->setText(QFileDialog::tr("&Rename"));
676 deleteAction->setText(QFileDialog::tr("&Delete"));
677 showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
678 newFolderAction->setText(QFileDialog::tr("&New Folder"));
679 qFileDialogUi->retranslateUi(q);
684}
685
687{
688 Q_Q(QFileDialog);
689 emit q->filesSelected(files);
690 if (files.size() == 1)
691 emit q->fileSelected(files.first());
692}
693
695{
696 // Don't use Q_Q here! This function is called from ~QDialog,
697 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
698 const QDialog * const q = static_cast<const QDialog*>(q_ptr);
700 return true;
702 || q->testAttribute(Qt::WA_DontShowOnScreen)
704 return false;
705 }
706
707 return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
708}
709
714
733{
734 const QFileDialog::Options previousOptions = options();
735 if (!(previousOptions & option) != !on)
736 setOptions(previousOptions ^ option);
737}
738
748{
749 Q_D(const QFileDialog);
750 return d->options->testOption(static_cast<QFileDialogOptions::FileDialogOption>(option));
751}
752
773{
774 Q_D(QFileDialog);
775
776 Options changed = (options ^ QFileDialog::options());
777 if (!changed)
778 return;
779
780 d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));
781
783 d->nativeDialogInUse = false;
784 d->createWidgets();
785 }
786
787 if (d->usingWidgets()) {
788 if (changed & DontResolveSymlinks)
789 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
790 if (changed & ReadOnly) {
791 bool ro = (options & ReadOnly);
792 d->model->setReadOnly(ro);
793 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
794 d->renameAction->setEnabled(!ro);
795 d->deleteAction->setEnabled(!ro);
796 }
797
798 if (changed & DontUseCustomDirectoryIcons) {
799 QFileIconProvider::Options providerOptions = iconProvider()->options();
802 iconProvider()->setOptions(providerOptions);
803 }
804 }
805
806 if (changed & HideNameFilterDetails)
807 setNameFilters(d->options->nameFilters());
808
809 if (changed & ShowDirsOnly)
811}
812
813QFileDialog::Options QFileDialog::options() const
814{
815 Q_D(const QFileDialog);
820 static_assert((int)QFileDialog::ReadOnly == (int)QFileDialogOptions::ReadOnly);
823 return QFileDialog::Options(int(d->options->options()));
824}
825
835void QFileDialog::open(QObject *receiver, const char *member)
836{
837 Q_D(QFileDialog);
840 connect(this, signal, receiver, member);
841 d->signalToDisconnectOnClose = signal;
842 d->receiverToDisconnectOnClose = receiver;
843 d->memberToDisconnectOnClose = member;
844
846}
847
848
852void QFileDialog::setVisible(bool visible)
853{
854 // will call QFileDialogPrivate::setVisible override
856}
857
865{
866 Q_Q(QFileDialog);
867
868 if (canBeNativeDialog()){
869 if (setNativeDialogVisible(visible)){
870 // Set WA_DontShowOnScreen so that QDialogPrivate::setVisible(visible) below
871 // updates the state correctly, but skips showing the non-native version:
872 q->setAttribute(Qt::WA_DontShowOnScreen);
873#if QT_CONFIG(fscompleter)
874 // So the completer doesn't try to complete and therefore show a popup
876 completer->setModel(nullptr);
877#endif
878 } else {
880 q->setAttribute(Qt::WA_DontShowOnScreen, false);
881#if QT_CONFIG(fscompleter)
882 if (!nativeDialogInUse) {
883 if (proxyModel != nullptr)
884 completer->setModel(proxyModel);
885 else
887 }
888#endif
889 }
890 }
891
892 if (visible && usingWidgets())
893 qFileDialogUi->fileNameEdit->setFocus();
894
896}
897
903{
904 //The shortcut in the side bar may have a parent that is not fetched yet (e.g. an hidden file)
905 //so we force the fetching
906 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(), true);
907 QModelIndex idx = model->d_func()->index(node);
908 enterDirectory(idx);
909}
910
930{
931 Q_D(QFileDialog);
932 QString newDirectory = directory;
933 //we remove .. and . from the given path if exist
934 if (!directory.isEmpty())
935 newDirectory = QDir::cleanPath(directory);
936
937 if (!directory.isEmpty() && newDirectory.isEmpty())
938 return;
939
940 QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
942
943 d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
944 if (!d->usingWidgets()) {
945 d->setDirectory_sys(newDirUrl);
946 return;
947 }
948 if (d->rootPath() == newDirectory)
949 return;
950 QModelIndex root = d->model->setRootPath(newDirectory);
951 if (!d->nativeDialogInUse) {
952 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
953 if (root != d->rootIndex()) {
954#if QT_CONFIG(fscompleter)
955 if (directory.endsWith(u'/'))
956 d->completer->setCompletionPrefix(newDirectory);
957 else
958 d->completer->setCompletionPrefix(newDirectory + u'/');
959#endif
960 d->setRootIndex(root);
961 }
962 d->qFileDialogUi->listView->selectionModel()->clear();
963 }
964}
965
970{
971 Q_D(const QFileDialog);
972 if (d->nativeDialogInUse) {
973 QString dir = d->directory_sys().toLocalFile();
974 return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
975 }
976 return d->rootPath();
977}
978
997{
998 Q_D(QFileDialog);
999 if (!directory.isValid())
1000 return;
1001
1003 d->options->setInitialDirectory(directory);
1004
1005 if (d->nativeDialogInUse)
1006 d->setDirectory_sys(directory);
1007 else if (directory.isLocalFile())
1008 setDirectory(directory.toLocalFile());
1009 else if (Q_UNLIKELY(d->usingWidgets()))
1010 qWarning("Non-native QFileDialog supports only local files");
1011}
1012
1019{
1020 Q_D(const QFileDialog);
1021 if (d->nativeDialogInUse)
1022 return d->directory_sys();
1023 else
1025}
1026
1027// FIXME Qt 5.4: Use upcoming QVolumeInfo class to determine this information?
1028static inline bool isCaseSensitiveFileSystem(const QString &path)
1029{
1030 Q_UNUSED(path);
1031#if defined(Q_OS_WIN)
1032 // Return case insensitive unconditionally, even if someone has a case sensitive
1033 // file system mounted, wrongly capitalized drive letters will cause mismatches.
1034 return false;
1035#elif defined(Q_OS_MACOS)
1036 return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE);
1037#else
1038 return true;
1039#endif
1040}
1041
1042// Determine the file name to be set on the line edit from the path
1043// passed to selectFile() in mode QFileDialog::AcceptSave.
1044static inline QString fileFromPath(const QString &rootPath, QString path)
1045{
1046 if (!QFileInfo(path).isAbsolute())
1047 return path;
1048 if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
1049 path.remove(0, rootPath.size());
1050
1051 if (path.isEmpty())
1052 return path;
1053
1054 if (path.at(0) == QDir::separator()
1055#ifdef Q_OS_WIN
1056 //On Windows both cases can happen
1057 || path.at(0) == u'/'
1058#endif
1059 ) {
1060 path.remove(0, 1);
1061 }
1062 return path;
1063}
1064
1071{
1072 Q_D(QFileDialog);
1073 if (filename.isEmpty())
1074 return;
1075
1076 if (!d->usingWidgets()) {
1077 QUrl url;
1078 if (QFileInfo(filename).isRelative()) {
1079 url = d->options->initialDirectory();
1080 QString path = url.path();
1081 if (!path.endsWith(u'/'))
1082 path += u'/';
1083 url.setPath(path + filename);
1084 } else {
1085 url = QUrl::fromLocalFile(filename);
1086 }
1087 d->selectFile_sys(url);
1088 d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
1089 return;
1090 }
1091
1092 if (!QDir::isRelativePath(filename)) {
1093 QFileInfo info(filename);
1094 QString filenamePath = info.absoluteDir().path();
1095
1096 if (d->model->rootPath() != filenamePath)
1097 setDirectory(filenamePath);
1098 }
1099
1100 QModelIndex index = d->model->index(filename);
1101 d->qFileDialogUi->listView->selectionModel()->clear();
1102 if (!isVisible() || !d->lineEdit()->hasFocus())
1103 d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
1104}
1105
1115{
1116 Q_D(QFileDialog);
1117 if (!url.isValid())
1118 return;
1119
1120 if (d->nativeDialogInUse)
1121 d->selectFile_sys(url);
1122 else if (url.isLocalFile())
1124 else
1125 qWarning("Non-native QFileDialog supports only local files");
1126}
1127
1128#ifdef Q_OS_UNIX
1129static QString homeDirFromPasswdEntry(const QString &path, const QByteArray &userName)
1130{
1131#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1132 passwd pw;
1133 passwd *tmpPw;
1134 long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
1135 if (bufSize == -1)
1136 bufSize = 1024;
1137 QVarLengthArray<char, 1024> buf(bufSize);
1138 int err = 0;
1139# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
1140 tmpPw = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size());
1141# else
1142 err = getpwnam_r(userName.constData(), &pw, buf.data(), buf.size(), &tmpPw);
1143# endif
1144 if (err || !tmpPw)
1145 return path;
1146 return QFile::decodeName(pw.pw_dir);
1147#else
1148 passwd *pw = getpwnam(userName.constData());
1149 if (!pw)
1150 return path;
1151 return QFile::decodeName(pw->pw_dir);
1152#endif // defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
1153}
1154
1155Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)
1156{
1157 if (!path.startsWith(u'~'))
1158 return path;
1159
1160 if (path.size() == 1) // '~'
1161 return QDir::homePath();
1162
1163 QStringView sv(path);
1164 const qsizetype sepIndex = sv.indexOf(QDir::separator());
1165 if (sepIndex == 1) // '~/' or '~/a/b/c'
1166 return QDir::homePath() + sv.sliced(1);
1167
1168#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1169 if (sepIndex == -1)
1170 return QDir::homePath();
1171 return QDir::homePath() + sv.sliced(sepIndex);
1172#else
1173 const qsizetype userNameLen = sepIndex != -1 ? sepIndex - strlen("~") // '~user/a/b'
1174 : path.size() - strlen("~"); // '~user'
1175 const QByteArray userName = sv.sliced(1, userNameLen).toLocal8Bit();
1176 QString homePath = homeDirFromPasswdEntry(path, userName);
1177 if (sepIndex == -1)
1178 return homePath;
1179 return homePath + sv.sliced(sepIndex);
1180#endif // defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
1181}
1182#endif
1183
1188{
1189 Q_Q(const QFileDialog);
1191 QString editText = lineEdit()->text();
1192 if (!editText.contains(u'"')) {
1193#ifdef Q_OS_UNIX
1194 const QString prefix = q->directory().absolutePath() + QDir::separator();
1195 if (QFile::exists(prefix + editText))
1196 files << editText;
1197 else
1198 files << qt_tildeExpansion(editText);
1199#else
1200 files << editText;
1201 Q_UNUSED(q);
1202#endif
1203 } else {
1204 // " is used to separate files like so: "file1" "file2" "file3" ...
1205 // ### need escape character for filenames with quotes (")
1206 QStringList tokens = editText.split(u'\"');
1207 for (int i=0; i<tokens.size(); ++i) {
1208 if ((i % 2) == 0)
1209 continue; // Every even token is a separator
1210#ifdef Q_OS_UNIX
1211 const QString token = tokens.at(i);
1212 const QString prefix = q->directory().absolutePath() + QDir::separator();
1213 if (QFile::exists(prefix + token))
1214 files << token;
1215 else
1216 files << qt_tildeExpansion(token);
1217#else
1218 files << toInternal(tokens.at(i));
1219#endif
1220 }
1221 }
1223}
1224
1225// Return selected files without defaulting to the root of the file system model
1226// used for initializing QFileDialogOptions for native dialogs. The default is
1227// not suitable for native dialogs since it mostly equals directory().
1229{
1230 QList<QUrl> files;
1231
1232 if (!usingWidgets())
1234
1235 const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
1236 files.reserve(selectedRows.size());
1237 for (const QModelIndex &index : selectedRows)
1239
1240 if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
1241 const QStringList typedFilesList = typedFiles();
1242 files.reserve(typedFilesList.size());
1243 for (const QString &path : typedFilesList)
1245 }
1246
1247 return files;
1248}
1249
1251{
1253 for (int i=0; i<filesToFix.size(); ++i) {
1254 QString name = toInternal(filesToFix.at(i));
1256 // if the filename has no suffix, add the default suffix
1257 const QString defaultSuffix = options->defaultSuffix();
1258 if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
1259 name += u'.' + defaultSuffix;
1260
1261 if (info.isAbsolute()) {
1262 files.append(name);
1263 } else {
1264 // at this point the path should only have Qt path separators.
1265 // This check is needed since we might be at the root directory
1266 // and on Windows it already ends with slash.
1267 QString path = rootPath();
1268 if (!path.endsWith(u'/'))
1269 path += u'/';
1270 path += name;
1271 files.append(path);
1272 }
1273 }
1274 return files;
1275}
1276
1277QList<QUrl> QFileDialogPrivate::addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const
1278{
1279 QList<QUrl> urls;
1280 urls.reserve(urlsToFix.size());
1281 // if the filename has no suffix, add the default suffix
1282 const QString defaultSuffix = options->defaultSuffix();
1283 for (QUrl url : urlsToFix) {
1284 if (!defaultSuffix.isEmpty()) {
1285 const QString urlPath = url.path();
1286 const auto idx = urlPath.lastIndexOf(u'/');
1287 if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
1288 url.setPath(urlPath + u'.' + defaultSuffix);
1289 }
1290 urls.append(url);
1291 }
1292 return urls;
1293}
1294
1295
1304{
1305 Q_D(const QFileDialog);
1306
1308 const QList<QUrl> userSelectedFiles = d->userSelectedFiles();
1309 files.reserve(userSelectedFiles.size());
1310 for (const QUrl &file : userSelectedFiles)
1311 files.append(file.toString(QUrl::PreferLocalFile));
1312
1313 if (files.isEmpty() && d->usingWidgets()) {
1314 const FileMode fm = fileMode();
1315 if (fm != ExistingFile && fm != ExistingFiles)
1316 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1317 }
1318 return files;
1319}
1320
1329QList<QUrl> QFileDialog::selectedUrls() const
1330{
1331 Q_D(const QFileDialog);
1332 if (d->nativeDialogInUse) {
1333 return d->userSelectedFiles();
1334 } else {
1335 QList<QUrl> urls;
1336 const QStringList selectedFileList = selectedFiles();
1337 urls.reserve(selectedFileList.size());
1338 for (const QString &file : selectedFileList)
1339 urls.append(QUrl::fromLocalFile(file));
1340 return urls;
1341 }
1342}
1343
1344/*
1345 Makes a list of filters from ;;-separated text.
1346 Used by the mac and windows implementations
1347*/
1349{
1350 if (filter.isEmpty())
1351 return QStringList();
1352
1353 auto sep = ";;"_L1;
1354 if (!filter.contains(sep) && filter.contains(u'\n'))
1355 sep = "\n"_L1;
1356
1357 return filter.split(sep);
1358}
1359
1381
1382
1383/*
1384 Strip the filters by removing the details, e.g. (*.*).
1385*/
1387{
1388#if QT_CONFIG(regularexpression)
1389 QStringList strippedFilters;
1391 strippedFilters.reserve(filters.size());
1392 for (const QString &filter : filters) {
1393 QString filterName;
1394 auto match = r.match(filter);
1395 if (match.hasMatch())
1396 filterName = match.captured(1);
1397 strippedFilters.append(filterName.simplified());
1398 }
1399 return strippedFilters;
1400#else
1401 return filters;
1402#endif
1403}
1404
1405
1426{
1427 Q_D(QFileDialog);
1428 QStringList cleanedFilters;
1429 cleanedFilters.reserve(filters.size());
1430 for (const QString &filter : filters)
1431 cleanedFilters << filter.simplified();
1432
1433 d->options->setNameFilters(cleanedFilters);
1434
1435 if (!d->usingWidgets())
1436 return;
1437
1438 d->qFileDialogUi->fileTypeCombo->clear();
1439 if (cleanedFilters.isEmpty())
1440 return;
1441
1443 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1444 else
1445 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1446
1447 d->useNameFilter(0);
1448}
1449
1457{
1458 return d_func()->options->nameFilters();
1459}
1460
1470{
1471 Q_D(QFileDialog);
1472 d->options->setInitiallySelectedNameFilter(filter);
1473 if (!d->usingWidgets()) {
1474 d->selectNameFilter_sys(filter);
1475 return;
1476 }
1477 int i = -1;
1480 if (!filters.isEmpty())
1481 i = d->qFileDialogUi->fileTypeCombo->findText(filters.first());
1482 } else {
1483 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1484 }
1485 if (i >= 0) {
1486 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1487 d->useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1488 }
1489}
1490
1499{
1500 Q_D(const QFileDialog);
1501 if (!d->usingWidgets())
1502 return d->selectedNameFilter_sys();
1503
1504 return d->qFileDialogUi->fileTypeCombo->currentText();
1505}
1506
1514QDir::Filters QFileDialog::filter() const
1515{
1516 Q_D(const QFileDialog);
1517 if (d->usingWidgets())
1518 return d->model->filter();
1519 return d->options->filter();
1520}
1521
1532{
1533 Q_D(QFileDialog);
1534 d->options->setFilter(filters);
1535 if (!d->usingWidgets()) {
1536 d->setFilter_sys();
1537 return;
1538 }
1539
1540 d->model->setFilter(filters);
1541 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1542}
1543
1544#if QT_CONFIG(mimetype)
1545
1546static QString nameFilterForMime(const QString &mimeType)
1547{
1550 if (mime.isValid()) {
1551 if (mime.isDefault()) {
1552 return QFileDialog::tr("All files (*)");
1553 } else {
1554 const QString patterns = mime.globPatterns().join(u' ');
1555 return mime.comment() + " ("_L1 + patterns + u')';
1556 }
1557 }
1558 return QString();
1559}
1560
1578void QFileDialog::setMimeTypeFilters(const QStringList &filters)
1579{
1580 Q_D(QFileDialog);
1582 for (const QString &mimeType : filters) {
1583 const QString text = nameFilterForMime(mimeType);
1584 if (!text.isEmpty())
1585 nameFilters.append(text);
1586 }
1588 d->options->setMimeTypeFilters(filters);
1589}
1590
1597QStringList QFileDialog::mimeTypeFilters() const
1598{
1599 return d_func()->options->mimeTypeFilters();
1600}
1601
1608void QFileDialog::selectMimeTypeFilter(const QString &filter)
1609{
1610 Q_D(QFileDialog);
1611 d->options->setInitiallySelectedMimeTypeFilter(filter);
1612
1613 const QString filterForMime = nameFilterForMime(filter);
1614
1615 if (!d->usingWidgets()) {
1616 d->selectMimeTypeFilter_sys(filter);
1617 if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
1618 selectNameFilter(filterForMime);
1619 }
1620 } else if (!filterForMime.isEmpty()) {
1621 selectNameFilter(filterForMime);
1622 }
1623}
1624
1625#endif // mimetype
1626
1632{
1633 Q_D(const QFileDialog);
1634 QString mimeTypeFilter;
1635 if (!d->usingWidgets())
1636 mimeTypeFilter = d->selectedMimeTypeFilter_sys();
1637
1638#if QT_CONFIG(mimetype)
1639 if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
1640 const auto nameFilter = selectedNameFilter();
1641 const auto mimeTypes = d->options->mimeTypeFilters();
1642 for (const auto &mimeType: mimeTypes) {
1643 QString filter = nameFilterForMime(mimeType);
1645 filter = qt_strip_filters({ filter }).constFirst();
1646 if (filter == nameFilter) {
1647 mimeTypeFilter = mimeType;
1648 break;
1649 }
1650 }
1651 }
1652#endif
1653
1654 return mimeTypeFilter;
1655}
1656
1667{
1668 Q_D(QFileDialog);
1669 d->options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(mode));
1670 if (!d->usingWidgets())
1671 return;
1672 if (mode == Detail)
1673 d->showDetailsView();
1674 else
1675 d->showListView();
1676}
1677
1679{
1680 Q_D(const QFileDialog);
1681 if (!d->usingWidgets())
1682 return static_cast<QFileDialog::ViewMode>(d->options->viewMode());
1683 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1684}
1685
1702{
1703 Q_D(QFileDialog);
1704 d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));
1705 if (!d->usingWidgets())
1706 return;
1707
1708 d->retranslateWindowTitle();
1709
1710 // set selection mode and behavior
1714 else
1715 selectionMode = QAbstractItemView::SingleSelection;
1716 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1717 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1718 // set filter
1719 d->model->setFilter(d->filterForMode(filter()));
1720 // setup file type for directory
1721 if (mode == Directory) {
1722 d->qFileDialogUi->fileTypeCombo->clear();
1723 d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
1724 d->qFileDialogUi->fileTypeCombo->setEnabled(false);
1725 }
1726 d->updateFileNameLabel();
1727 d->updateOkButtonText();
1728 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1729 d->updateOkButton();
1730}
1731
1733{
1734 Q_D(const QFileDialog);
1735 return static_cast<FileMode>(d->options->fileMode());
1736}
1737
1749{
1750 Q_D(QFileDialog);
1751 d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode));
1752 // clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
1754 if (!d->usingWidgets())
1755 return;
1757 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1758 d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
1759 d->updateOkButton();
1760 if (mode == AcceptSave) {
1761 d->qFileDialogUi->lookInCombo->setEditable(false);
1762 }
1763 d->retranslateWindowTitle();
1764}
1765
1780{
1781 Q_D(QFileDialog);
1782 d->options->setSupportedSchemes(schemes);
1783}
1784
1786{
1787 return d_func()->options->supportedSchemes();
1788}
1789
1790/*
1791 Returns the file system model index that is the root index in the
1792 views
1793*/
1795 return mapToSource(qFileDialogUi->listView->rootIndex());
1796}
1797
1799 if (!qFileDialogUi->stackedWidget)
1800 return nullptr;
1801 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1802 return qFileDialogUi->listView;
1803 return qFileDialogUi->treeView;
1804}
1805
1807 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1808}
1809
1811{
1812#if defined(Q_OS_UNIX)
1813 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1814#elif defined(Q_OS_WIN)
1815 DWORD maxLength;
1816 const QString drive = path.left(3);
1817 if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == false)
1818 return -1;
1819 return maxLength;
1820#else
1821 Q_UNUSED(path);
1822#endif
1823 return -1;
1824}
1825
1826/*
1827 Sets the view root index to be the file system model index
1828*/
1830 Q_ASSERT(index.isValid() ? index.model() == model : true);
1832 qFileDialogUi->treeView->setRootIndex(idx);
1833 qFileDialogUi->listView->setRootIndex(idx);
1834}
1835/*
1836 Select a file system model index
1837 returns the index that was selected (or not depending upon sortfilterproxymodel)
1838*/
1840 Q_ASSERT(index.isValid() ? index.model() == model : true);
1841
1843 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1844 qFileDialogUi->listView->selectionModel()->select(idx,
1846 return idx;
1847}
1848
1850{
1851 Q_D(const QFileDialog);
1852 return static_cast<AcceptMode>(d->options->acceptMode());
1853}
1854
1867{
1868 Q_D(QFileDialog);
1869 d->options->setDefaultSuffix(suffix);
1870}
1871
1873{
1874 Q_D(const QFileDialog);
1875 return d->options->defaultSuffix();
1876}
1877
1883{
1884 Q_D(QFileDialog);
1885 if (d->usingWidgets())
1886 d->qFileDialogUi->lookInCombo->setHistory(paths);
1887}
1888
1890{
1891 m_history = paths;
1892 // Only populate the first item, showPopup will populate the rest if needed
1893 QList<QUrl> list;
1894 const QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1895 //On windows the popup display the "C:\", convert to nativeSeparators
1896 const QUrl url = idx.isValid()
1898 : QUrl("file:"_L1);
1899 if (url.isValid())
1900 list.append(url);
1901 urlModel->setUrls(list);
1902}
1903
1908{
1909 Q_D(const QFileDialog);
1910 if (!d->usingWidgets())
1911 return QStringList();
1912 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1913 //On windows the popup display the "C:\", convert to nativeSeparators
1914 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1915 if (!currentHistory.contains(newHistory))
1916 currentHistory << newHistory;
1917 return currentHistory;
1918}
1919
1939{
1940 Q_D(QFileDialog);
1941 if (!d->usingWidgets())
1942 return;
1943 d->qFileDialogUi->listView->setItemDelegate(delegate);
1944 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1945}
1946
1951{
1952 Q_D(const QFileDialog);
1953 if (!d->usingWidgets())
1954 return nullptr;
1955 return d->qFileDialogUi->listView->itemDelegate();
1956}
1957
1962{
1963 Q_D(QFileDialog);
1964 if (!d->usingWidgets())
1965 return;
1966 d->model->setIconProvider(provider);
1967 //It forces the refresh of all entries in the side bar, then we can get new icons
1968 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1969}
1970
1975{
1976 Q_D(const QFileDialog);
1977 if (!d->model)
1978 return nullptr;
1979 return d->model->iconProvider();
1980}
1981
1983{
1984 if (!qFileDialogUi)
1985 return;
1986 switch (label) {
1988 qFileDialogUi->lookInLabel->setText(text);
1989 break;
1991 qFileDialogUi->fileNameLabel->setText(text);
1992 break;
1994 qFileDialogUi->fileTypeLabel->setText(text);
1995 break;
1997 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
1998 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
2000 } else {
2001 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
2003 }
2004 break;
2006 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
2008 break;
2009 }
2010}
2011
2017{
2018 Q_D(QFileDialog);
2019 d->options->setLabelText(static_cast<QFileDialogOptions::DialogLabel>(label), text);
2020 d->setLabelTextControl(label, text);
2021}
2022
2027{
2028 Q_D(const QFileDialog);
2029 if (!d->usingWidgets())
2030 return d->options->labelText(static_cast<QFileDialogOptions::DialogLabel>(label));
2032 switch (label) {
2033 case LookIn:
2034 return d->qFileDialogUi->lookInLabel->text();
2035 case FileName:
2036 return d->qFileDialogUi->fileNameLabel->text();
2037 case FileType:
2038 return d->qFileDialogUi->fileTypeLabel->text();
2039 case Accept:
2040 if (acceptMode() == AcceptOpen)
2041 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
2042 else
2043 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
2044 if (button)
2045 return button->text();
2046 break;
2047 case Reject:
2048 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
2049 if (button)
2050 return button->text();
2051 break;
2052 }
2053 return QString();
2054}
2055
2103 const QString &caption,
2104 const QString &dir,
2105 const QString &filter,
2106 QString *selectedFilter,
2107 Options options)
2108{
2109 const QStringList schemes = QStringList(QStringLiteral("file"));
2110 const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2111 selectedFilter, options, schemes);
2112 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2113 return selectedUrl.toLocalFile();
2114 else
2115 return selectedUrl.toString();
2116}
2117
2146 const QString &caption,
2147 const QUrl &dir,
2148 const QString &filter,
2149 QString *selectedFilter,
2150 Options options,
2151 const QStringList &supportedSchemes)
2152{
2154 args.parent = parent;
2155 args.caption = caption;
2156 args.filter = filter;
2157 args.mode = ExistingFile;
2158 args.options = options;
2159
2162 if (selectedFilter && !selectedFilter->isEmpty())
2163 dialog.selectNameFilter(*selectedFilter);
2164 if (dialog.exec() == QDialog::Accepted) {
2165 if (selectedFilter)
2166 *selectedFilter = dialog.selectedNameFilter();
2167 return dialog.selectedUrls().value(0);
2168 }
2169 return QUrl();
2170}
2171
2216 const QString &caption,
2217 const QString &dir,
2218 const QString &filter,
2219 QString *selectedFilter,
2220 Options options)
2221{
2222 const QStringList schemes = QStringList(QStringLiteral("file"));
2223 const QList<QUrl> selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),
2224 filter, selectedFilter, options, schemes);
2226 fileNames.reserve(selectedUrls.size());
2227 for (const QUrl &url : selectedUrls)
2229 return fileNames;
2230}
2231
2261 const QString &caption,
2262 const QUrl &dir,
2263 const QString &filter,
2264 QString *selectedFilter,
2265 Options options,
2266 const QStringList &supportedSchemes)
2267{
2269 args.parent = parent;
2270 args.caption = caption;
2271 args.filter = filter;
2272 args.mode = ExistingFiles;
2273 args.options = options;
2274
2277 if (selectedFilter && !selectedFilter->isEmpty())
2278 dialog.selectNameFilter(*selectedFilter);
2279 if (dialog.exec() == QDialog::Accepted) {
2280 if (selectedFilter)
2281 *selectedFilter = dialog.selectedNameFilter();
2282 return dialog.selectedUrls();
2283 }
2284 return QList<QUrl>();
2285}
2286
2306void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted, QWidget *parent)
2307{
2308#ifdef Q_OS_WASM
2310 auto openFileImpl = std::make_shared<std::function<void(void)>>();
2312 QByteArray fileContent;
2313 *openFileImpl = [=]() mutable {
2314 auto fileDialogClosed = [&](bool fileSelected) {
2315 if (!fileSelected) {
2316 fileOpenCompleted(fileName, fileContent);
2317 openFileImpl.reset();
2318 }
2319 };
2320 auto acceptFile = [&](uint64_t size, const std::string name) -> char * {
2321 const uint64_t twoGB = 1ULL << 31; // QByteArray limit
2322 if (size > twoGB)
2323 return nullptr;
2324
2326 fileContent.resize(size);
2327 return fileContent.data();
2328 };
2329 auto fileContentReady = [&]() mutable {
2330 fileOpenCompleted(fileName, fileContent);
2331 openFileImpl.reset();
2332 };
2333
2334 QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
2335 };
2336
2337 (*openFileImpl)();
2338#else
2341 dialog->setNameFilter(nameFilter);
2343
2344 auto fileSelected = [=](const QString &fileName) {
2345 QByteArray fileContent;
2346 if (!fileName.isNull()) {
2347 QFile selectedFile(fileName);
2348 if (selectedFile.open(QIODevice::ReadOnly))
2349 fileContent = selectedFile.readAll();
2350 }
2351 fileOpenCompleted(fileName, fileContent);
2352 };
2353
2355 dialog->show();
2356#endif
2357}
2358
2377void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint, QWidget *parent)
2378{
2379#ifdef Q_OS_WASM
2381 QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
2382#else
2386 dialog->selectFile(fileNameHint);
2387
2388 auto fileSelected = [=](const QString &fileName) {
2389 if (!fileName.isNull()) {
2390 QFile selectedFile(fileName);
2391 if (selectedFile.open(QIODevice::WriteOnly))
2392 selectedFile.write(fileContent);
2393 }
2394 };
2395
2398 dialog->show();
2399#endif
2400}
2401
2451 const QString &caption,
2452 const QString &dir,
2453 const QString &filter,
2454 QString *selectedFilter,
2455 Options options)
2456{
2457 const QStringList schemes = QStringList(QStringLiteral("file"));
2458 const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
2459 selectedFilter, options, schemes);
2460 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2461 return selectedUrl.toLocalFile();
2462 else
2463 return selectedUrl.toString();
2464}
2465
2494 const QString &caption,
2495 const QUrl &dir,
2496 const QString &filter,
2497 QString *selectedFilter,
2498 Options options,
2499 const QStringList &supportedSchemes)
2500{
2502 args.parent = parent;
2503 args.caption = caption;
2504 args.filter = filter;
2505 args.mode = AnyFile;
2506 args.options = options;
2507
2511 if (selectedFilter && !selectedFilter->isEmpty())
2512 dialog.selectNameFilter(*selectedFilter);
2513 if (dialog.exec() == QDialog::Accepted) {
2514 if (selectedFilter)
2515 *selectedFilter = dialog.selectedNameFilter();
2516 return dialog.selectedUrls().value(0);
2517 }
2518 return QUrl();
2519}
2520
2566 const QString &caption,
2567 const QString &dir,
2568 Options options)
2569{
2570 const QStringList schemes = QStringList(QStringLiteral("file"));
2571 const QUrl selectedUrl =
2573 if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
2574 return selectedUrl.toLocalFile();
2575 else
2576 return selectedUrl.toString();
2577}
2578
2607 const QString &caption,
2608 const QUrl &dir,
2609 Options options,
2610 const QStringList &supportedSchemes)
2611{
2613 args.parent = parent;
2614 args.caption = caption;
2615 args.mode = Directory;
2616 args.options = options;
2617
2620 if (dialog.exec() == QDialog::Accepted)
2621 return dialog.selectedUrls().value(0);
2622 return QUrl();
2623}
2624
2625inline static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)
2626{
2627 if (url.isLocalFile()) {
2628 QFileInfo info = local;
2629 if (!local.isAbsolute())
2631 const QFileInfo pathInfo(info.absolutePath());
2632 if (!pathInfo.exists() || !pathInfo.isDir())
2633 return QUrl();
2634 if (info.exists() && info.isDir())
2635 return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));
2636 return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
2637 } else {
2638 return url;
2639 }
2640}
2641
2642/*
2643 Initialize working directory and selection from \a url.
2644*/
2646{
2647 // default case, re-use QFileInfo to avoid stat'ing
2648 const QFileInfo local(url.toLocalFile());
2649 // Get the initial directory URL
2650 if (!url.isEmpty())
2652 if (directory.isEmpty()) {
2653 const QUrl lastVisited = *lastVisitedDir();
2654 if (lastVisited != url)
2655 directory = _qt_get_directory(lastVisited, QFileInfo());
2656 }
2657 if (directory.isEmpty())
2659
2660 /*
2661 The initial directory can contain both the initial directory
2662 and initial selection, e.g. /home/user/foo.txt
2663 */
2664 if (selection.isEmpty() && !url.isEmpty()) {
2665 if (url.isLocalFile()) {
2666 if (!local.isDir())
2667 selection = local.fileName();
2668 } else {
2669 // With remote URLs we can only assume.
2671 }
2672 }
2673}
2674
2679{
2680 Q_D(QFileDialog);
2681
2683
2684 if (d->receiverToDisconnectOnClose) {
2685 disconnect(this, d->signalToDisconnectOnClose,
2686 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2687 d->receiverToDisconnectOnClose = nullptr;
2688 }
2689 d->memberToDisconnectOnClose.clear();
2690 d->signalToDisconnectOnClose.clear();
2691}
2692
2693bool QFileDialogPrivate::itemAlreadyExists(const QString &fileName)
2694{
2695#if QT_CONFIG(messagebox)
2696 Q_Q(QFileDialog);
2697 const QString msg = QFileDialog::tr("%1 already exists.\nDo you want to replace it?").arg(fileName);
2698 using B = QMessageBox;
2699 const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
2700 return res == B::Yes;
2701#endif
2702 return false;
2703}
2704
2705void QFileDialogPrivate::itemNotFound(const QString &fileName, QFileDialog::FileMode mode)
2706{
2707#if QT_CONFIG(messagebox)
2708 Q_Q(QFileDialog);
2710 ? QFileDialog::tr("%1\nDirectory not found.\n"
2711 "Please verify the correct directory name was given.")
2712 : QFileDialog::tr("%1\nFile not found.\nPlease verify the "
2713 "correct file name was given.");
2714
2715 QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
2716#endif // QT_CONFIG(messagebox)
2717}
2718
2723{
2724 Q_D(QFileDialog);
2725 if (!d->usingWidgets()) {
2726 const QList<QUrl> urls = selectedUrls();
2727 if (urls.isEmpty())
2728 return;
2729 d->emitUrlsSelected(urls);
2730 if (urls.size() == 1)
2731 d->emitUrlSelected(urls.first());
2733 return;
2734 }
2735
2737 if (files.isEmpty())
2738 return;
2739 QString lineEditText = d->lineEdit()->text();
2740 // "hidden feature" type .. and then enter, and it will move up a dir
2741 // special case for ".."
2742 if (lineEditText == ".."_L1) {
2743 d->navigateToParent();
2744 const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
2745 d->lineEdit()->selectAll();
2746 return;
2747 }
2748
2749 const auto mode = fileMode();
2750 switch (mode) {
2751 case Directory: {
2752 QString fn = files.first();
2753 QFileInfo info(fn);
2754 if (!info.exists())
2755 info = QFileInfo(d->getEnvironmentVariable(fn));
2756 if (!info.exists()) {
2757 d->itemNotFound(info.fileName(), mode);
2758 return;
2759 }
2760 if (info.isDir()) {
2761 d->emitFilesSelected(files);
2763 }
2764 return;
2765 }
2766
2767 case AnyFile: {
2768 QString fn = files.first();
2769 QFileInfo info(fn);
2770 if (info.isDir()) {
2771 setDirectory(info.absoluteFilePath());
2772 return;
2773 }
2774
2775 if (!info.exists()) {
2776 const long maxNameLength = d->maxNameLength(info.path());
2777 if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
2778 return;
2779 }
2780
2781 // check if we have to ask for permission to overwrite the file
2782 if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {
2783 d->emitFilesSelected(QStringList(fn));
2785 } else {
2786 if (d->itemAlreadyExists(info.fileName())) {
2787 d->emitFilesSelected(QStringList(fn));
2789 }
2790 }
2791 return;
2792 }
2793
2794 case ExistingFile:
2795 case ExistingFiles:
2796 for (const auto &file : files) {
2798 if (!info.exists())
2799 info = QFileInfo(d->getEnvironmentVariable(file));
2800 if (!info.exists()) {
2801 d->itemNotFound(info.fileName(), mode);
2802 return;
2803 }
2804 if (info.isDir()) {
2805 setDirectory(info.absoluteFilePath());
2806 d->lineEdit()->clear();
2807 return;
2808 }
2809 }
2810 d->emitFilesSelected(files);
2812 return;
2813 }
2814}
2815
2816#if QT_CONFIG(settings)
2817void QFileDialogPrivate::saveSettings()
2818{
2819 Q_Q(QFileDialog);
2820 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2821 settings.beginGroup("FileDialog");
2822
2823 if (usingWidgets()) {
2824 settings.setValue("sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
2825 settings.setValue("shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
2826 settings.setValue("treeViewHeader", qFileDialogUi->treeView->header()->saveState());
2827 }
2828 QStringList historyUrls;
2829 const QStringList history = q->history();
2830 historyUrls.reserve(history.size());
2831 for (const QString &path : history)
2832 historyUrls << QUrl::fromLocalFile(path).toString();
2833 settings.setValue("history", historyUrls);
2834 settings.setValue("lastVisited", lastVisitedDir()->toString());
2835 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
2836 settings.setValue("viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
2837 settings.setValue("qtVersion", QT_VERSION_STR ""_L1);
2838}
2839
2840bool QFileDialogPrivate::restoreFromSettings()
2841{
2842 Q_Q(QFileDialog);
2843 QSettings settings(QSettings::UserScope, u"QtProject"_s);
2844 if (!settings.childGroups().contains("FileDialog"_L1))
2845 return false;
2846 settings.beginGroup("FileDialog");
2847
2848 q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value("lastVisited").toUrl() : *lastVisitedDir());
2849
2850 QByteArray viewModeStr = settings.value("viewMode").toString().toLatin1();
2851 const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
2852 bool ok = false;
2853 int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
2854 if (!ok)
2855 viewMode = QFileDialog::List;
2856 q->setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));
2857
2859 headerData = settings.value("treeViewHeader").toByteArray();
2860
2861 if (!usingWidgets())
2862 return true;
2863
2864 QStringList history;
2865 const auto urlStrings = settings.value("history").toStringList();
2866 for (const QString &urlStr : urlStrings) {
2867 QUrl url(urlStr);
2868 if (url.isLocalFile())
2869 history << url.toLocalFile();
2870 }
2871
2872 return restoreWidgetState(history, settings.value("sidebarWidth", -1).toInt());
2873}
2874#endif // settings
2875
2876bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPosition)
2877{
2878 Q_Q(QFileDialog);
2879 if (splitterPosition >= 0) {
2880 QList<int> splitterSizes;
2881 splitterSizes.append(splitterPosition);
2882 splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
2883 qFileDialogUi->splitter->setSizes(splitterSizes);
2884 } else {
2885 if (!qFileDialogUi->splitter->restoreState(splitterState))
2886 return false;
2887 QList<int> list = qFileDialogUi->splitter->sizes();
2888 if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
2889 for (int i = 0; i < list.size(); ++i)
2890 list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
2891 qFileDialogUi->splitter->setSizes(list);
2892 }
2893 }
2894
2895 qFileDialogUi->sidebar->setUrls(sidebarUrls);
2896
2897 static const int MaxHistorySize = 5;
2898 if (history.size() > MaxHistorySize)
2899 history.erase(history.begin(), history.end() - MaxHistorySize);
2900 q->setHistory(history);
2901
2902 QHeaderView *headerView = qFileDialogUi->treeView->header();
2903 if (!headerView->restoreState(headerData))
2904 return false;
2905
2906 QList<QAction*> actions = headerView->actions();
2907 QAbstractItemModel *abstractModel = model;
2908#if QT_CONFIG(proxymodel)
2909 if (proxyModel)
2910 abstractModel = proxyModel;
2911#endif
2912 const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
2913 for (int i = 1; i < total; ++i)
2914 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
2915
2916 return true;
2917}
2918
2925{
2926 Q_Q(QFileDialog);
2927 if (!args.caption.isEmpty()) {
2928 useDefaultCaption = false;
2929 setWindowTitle = args.caption;
2930 q->setWindowTitle(args.caption);
2931 }
2932
2933 q->setAcceptMode(QFileDialog::AcceptOpen);
2935 if (!nativeDialogInUse)
2936 createWidgets();
2937 q->setFileMode(QFileDialog::AnyFile);
2938 if (!args.filter.isEmpty())
2939 q->setNameFilter(args.filter);
2940 // QTBUG-70798, prevent the default blocking the restore logic.
2941 const bool dontStoreDir = !args.directory.isValid() && !lastVisitedDir()->isValid();
2942 q->setDirectoryUrl(args.directory);
2943 if (dontStoreDir)
2944 lastVisitedDir()->clear();
2945 if (args.directory.isLocalFile())
2946 q->selectFile(args.selection);
2947 else
2948 q->selectUrl(args.directory);
2949
2950#if QT_CONFIG(settings)
2951 // Try to restore from the FileDialog settings group; if it fails, fall back
2952 // to the pre-5.5 QByteArray serialized settings.
2953 if (!restoreFromSettings()) {
2954 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
2955 q->restoreState(settings.value("Qt/filedialog").toByteArray());
2956 }
2957#endif
2958
2959#if defined(Q_EMBEDDED_SMALLSCREEN)
2960 qFileDialogUi->lookInLabel->setVisible(false);
2961 qFileDialogUi->fileNameLabel->setVisible(false);
2962 qFileDialogUi->fileTypeLabel->setVisible(false);
2963 qFileDialogUi->sidebar->hide();
2964#endif
2965
2966 const QSize sizeHint = q->sizeHint();
2967 if (sizeHint.isValid())
2968 q->resize(sizeHint);
2969}
2970
2977{
2978 if (qFileDialogUi)
2979 return;
2980 Q_Q(QFileDialog);
2981
2982 // This function is sometimes called late (e.g as a fallback from setVisible). In that case we
2983 // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly
2984 // set window state or geometry.
2985 QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
2986 Qt::WindowStates preState = q->windowState();
2987
2988 model = new QFileSystemModel(q);
2991 model->setObjectName("qt_filesystem_model"_L1);
2993 model->setNameFilterDisables(helper->defaultNameFilterDisables());
2994 else
2996 model->d_func()->disableRecursiveSort = true;
3003 model->setReadOnly(false);
3004
3005 qFileDialogUi.reset(new Ui_QFileDialog());
3006 qFileDialogUi->setupUi(q);
3007
3008 QList<QUrl> initialBookmarks;
3009 initialBookmarks << QUrl("file:"_L1)
3011 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
3014
3019
3020 qFileDialogUi->lookInCombo->setFileDialogPrivate(this);
3023
3024 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
3025 qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
3026
3027 // filename
3028 qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);
3029#ifndef QT_NO_SHORTCUT
3030 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
3031#endif
3032#if QT_CONFIG(fscompleter)
3033 completer = new QFSCompleter(model, q);
3034 qFileDialogUi->fileNameEdit->setCompleter(completer);
3035#endif // QT_CONFIG(fscompleter)
3036
3037 qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
3038
3045
3046 // filetype
3047 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
3048 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
3049 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
3054
3055 qFileDialogUi->listView->setFileDialogPrivate(this);
3056 qFileDialogUi->listView->setModel(model);
3059 QObjectPrivate::connect(qFileDialogUi->listView, &QAbstractItemView::customContextMenuRequested,
3061#ifndef QT_NO_SHORTCUT
3065#endif
3066
3067 qFileDialogUi->treeView->setFileDialogPrivate(this);
3068 qFileDialogUi->treeView->setModel(model);
3069 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
3070 QFontMetrics fm(q->font());
3071 treeHeader->resizeSection(0, fm.horizontalAdvance("wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
3072 treeHeader->resizeSection(1, fm.horizontalAdvance("128.88 GB"_L1));
3073 treeHeader->resizeSection(2, fm.horizontalAdvance("mp3Folder"_L1));
3074 treeHeader->resizeSection(3, fm.horizontalAdvance("10/29/81 02:02PM"_L1));
3075 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
3076
3077 QActionGroup *showActionGroup = new QActionGroup(q);
3078 showActionGroup->setExclusive(false);
3081
3082 QAbstractItemModel *abstractModel = model;
3083#if QT_CONFIG(proxymodel)
3084 if (proxyModel)
3085 abstractModel = proxyModel;
3086#endif
3087 for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
3088 QAction *showHeader = new QAction(showActionGroup);
3089 showHeader->setCheckable(true);
3090 showHeader->setChecked(true);
3091 treeHeader->addAction(showHeader);
3092 }
3093
3094 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
3095 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
3096
3099 QObjectPrivate::connect(qFileDialogUi->treeView, &QAbstractItemView::customContextMenuRequested,
3101#ifndef QT_NO_SHORTCUT
3105#endif
3106
3107 // Selections
3108 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
3113 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
3114
3117
3118#if QT_CONFIG(settings)
3119 // Try to restore from the FileDialog settings group; if it fails, fall back
3120 // to the pre-5.5 QByteArray serialized settings.
3121 if (!restoreFromSettings()) {
3122 const QSettings settings(QSettings::UserScope, u"QtProject"_s);
3123 q->restoreState(settings.value("Qt/filedialog").toByteArray());
3124 }
3125#endif
3126
3127 // Initial widget states from options
3128 q->setFileMode(static_cast<QFileDialog::FileMode>(options->fileMode()));
3129 q->setAcceptMode(static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
3130 q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
3131 q->setOptions(static_cast<QFileDialog::Options>(static_cast<int>(options->options())));
3132 if (!options->sidebarUrls().isEmpty())
3133 q->setSidebarUrls(options->sidebarUrls());
3134 q->setDirectoryUrl(options->initialDirectory());
3135#if QT_CONFIG(mimetype)
3136 if (!options->mimeTypeFilters().isEmpty())
3137 q->setMimeTypeFilters(options->mimeTypeFilters());
3138 else
3139#endif
3140 if (!options->nameFilters().isEmpty())
3141 q->setNameFilters(options->nameFilters());
3142 q->selectNameFilter(options->initiallySelectedNameFilter());
3143 q->setDefaultSuffix(options->defaultSuffix());
3144 q->setHistory(options->history());
3145 const auto initiallySelectedFiles = options->initiallySelectedFiles();
3146 if (initiallySelectedFiles.size() == 1)
3147 q->selectFile(initiallySelectedFiles.first().fileName());
3148 for (const QUrl &url : initiallySelectedFiles)
3149 q->selectUrl(url);
3150 lineEdit()->selectAll();
3153 q->resize(preSize.isValid() ? preSize : q->sizeHint());
3154 q->setWindowState(preState);
3155}
3156
3158{
3159 Q_Q(QFileDialog);
3160 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
3161 qFileDialogUi->treeView->header()->setSectionHidden(int(actionGroup->actions().indexOf(action) + 1),
3162 !action->isChecked());
3163}
3164
3165#if QT_CONFIG(proxymodel)
3178void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
3179{
3180 Q_D(QFileDialog);
3181 if (!d->usingWidgets())
3182 return;
3183 if ((!proxyModel && !d->proxyModel)
3184 || (proxyModel == d->proxyModel))
3185 return;
3186
3187 QModelIndex idx = d->rootIndex();
3188 if (d->proxyModel)
3191 else
3194
3195 if (proxyModel != nullptr) {
3196 proxyModel->setParent(this);
3197 d->proxyModel = proxyModel;
3198 proxyModel->setSourceModel(d->model);
3199 d->qFileDialogUi->listView->setModel(d->proxyModel);
3200 d->qFileDialogUi->treeView->setModel(d->proxyModel);
3201#if QT_CONFIG(fscompleter)
3202 d->completer->setModel(d->proxyModel);
3203 d->completer->proxyModel = d->proxyModel;
3204#endif
3207 } else {
3208 d->proxyModel = nullptr;
3209 d->qFileDialogUi->listView->setModel(d->model);
3210 d->qFileDialogUi->treeView->setModel(d->model);
3211#if QT_CONFIG(fscompleter)
3212 d->completer->setModel(d->model);
3213 d->completer->sourceModel = d->model;
3214 d->completer->proxyModel = nullptr;
3215#endif
3218 }
3219 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
3220 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
3221
3222 d->setRootIndex(idx);
3223
3224 // reconnect selection
3225 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
3230}
3231
3237QAbstractProxyModel *QFileDialog::proxyModel() const
3238{
3239 Q_D(const QFileDialog);
3240 return d->proxyModel;
3241}
3242#endif // QT_CONFIG(proxymodel)
3243
3250{
3251 Q_Q(QFileDialog);
3252 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, nullptr, q));
3253 qFileDialogUi->backButton->setAutoRaise(true);
3254 qFileDialogUi->backButton->setEnabled(false);
3257
3258 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, nullptr, q));
3259 qFileDialogUi->forwardButton->setAutoRaise(true);
3260 qFileDialogUi->forwardButton->setEnabled(false);
3263
3264 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, nullptr, q));
3265 qFileDialogUi->toParentButton->setAutoRaise(true);
3266 qFileDialogUi->toParentButton->setEnabled(false);
3269
3270 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, nullptr, q));
3271 qFileDialogUi->listModeButton->setAutoRaise(true);
3272 qFileDialogUi->listModeButton->setDown(true);
3275
3276 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, nullptr, q));
3277 qFileDialogUi->detailModeButton->setAutoRaise(true);
3280
3281 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
3282 qFileDialogUi->backButton->setFixedSize(toolSize);
3283 qFileDialogUi->listModeButton->setFixedSize(toolSize);
3284 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
3285 qFileDialogUi->forwardButton->setFixedSize(toolSize);
3286 qFileDialogUi->toParentButton->setFixedSize(toolSize);
3287
3288 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, nullptr, q));
3289 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
3290 qFileDialogUi->newFolderButton->setAutoRaise(true);
3291 qFileDialogUi->newFolderButton->setEnabled(false);
3294}
3295
3302{
3303 Q_Q(QFileDialog);
3304
3305 QAction *goHomeAction = new QAction(q);
3306#ifndef QT_NO_SHORTCUT
3307 goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
3308#endif
3311 q->addAction(goHomeAction);
3312
3313 // ### TODO add Desktop & Computer actions
3314
3315 QAction *goToParent = new QAction(q);
3316 goToParent->setObjectName("qt_goto_parent_action"_L1);
3317#ifndef QT_NO_SHORTCUT
3318 goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
3319#endif
3322 q->addAction(goToParent);
3323
3324 renameAction = new QAction(q);
3325 renameAction->setEnabled(false);
3326 renameAction->setObjectName("qt_rename_action"_L1);
3329
3330 deleteAction = new QAction(q);
3331 deleteAction->setEnabled(false);
3332 deleteAction->setObjectName("qt_delete_action"_L1);
3335
3336 showHiddenAction = new QAction(q);
3337 showHiddenAction->setObjectName("qt_show_hidden_action"_L1);
3341
3342 newFolderAction = new QAction(q);
3343 newFolderAction->setObjectName("qt_new_folder_action"_L1);
3346}
3347
3349{
3350 Q_Q(QFileDialog);
3351 q->setDirectory(QDir::homePath());
3352}
3353
3354
3356{
3357 if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
3358 return;
3360 item.selection.clear();
3361 const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3362 for (const auto &index : selectedIndexes)
3363 item.selection.append(QPersistentModelIndex(index));
3364}
3365
3372{
3373 Q_Q(QFileDialog);
3374 qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
3375 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
3376 q->setHistory(qFileDialogUi->lookInCombo->history());
3377
3378 const QString newNativePath = QDir::toNativeSeparators(newPath);
3379
3380 // equal paths indicate this was invoked by _q_navigateBack/Forward()
3381 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
3382 if (currentHistoryLocation >= 0)
3384 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
3385 currentHistory.removeLast();
3386 }
3387 currentHistory.append({newNativePath, PersistentModelIndexList()});
3389 }
3390 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
3391 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
3392}
3393
3395{
3396 Q_Q(QFileDialog);
3397 q->setDirectory(historyItem.path);
3398 // Restore selection unless something has changed in the file system
3399 if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
3400 return;
3401 if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
3402 [](const QPersistentModelIndex &i) { return !i.isValid(); })) {
3403 historyItem.selection.clear();
3404 return;
3405 }
3406
3407 QAbstractItemView *view = q->viewMode() == QFileDialog::List
3408 ? static_cast<QAbstractItemView *>(qFileDialogUi->listView)
3409 : static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
3410 auto selectionModel = view->selectionModel();
3411 const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
3413 selectionModel->select(historyItem.selection.constFirst(),
3415 auto it = historyItem.selection.cbegin() + 1;
3416 const auto end = historyItem.selection.cend();
3417 for (; it != end; ++it)
3418 selectionModel->select(*it, flags);
3419
3420 view->scrollTo(historyItem.selection.constFirst());
3421}
3422
3435
3448
3456{
3457 Q_Q(QFileDialog);
3459 QString newDirectory;
3460 if (dir.isRoot()) {
3461 newDirectory = model->myComputer().toString();
3462 } else {
3463 dir.cdUp();
3464 newDirectory = dir.absolutePath();
3465 }
3466 q->setDirectory(newDirectory);
3467 emit q->directoryEntered(newDirectory);
3468}
3469
3476{
3477 Q_Q(QFileDialog);
3478 qFileDialogUi->listView->clearSelection();
3479
3480 QString newFolderString = QFileDialog::tr("New Folder");
3481 QString folderName = newFolderString;
3482 QString prefix = q->directory().absolutePath() + QDir::separator();
3483 if (QFile::exists(prefix + folderName)) {
3484 qlonglong suffix = 2;
3485 while (QFile::exists(prefix + folderName)) {
3486 folderName = newFolderString + QString::number(suffix++);
3487 }
3488 }
3489
3491 QModelIndex index = model->mkdir(parent, folderName);
3492 if (!index.isValid())
3493 return;
3494
3495 index = select(index);
3496 if (index.isValid()) {
3497 qFileDialogUi->treeView->setCurrentIndex(index);
3499 }
3500}
3501
3503{
3504 qFileDialogUi->listModeButton->setDown(true);
3505 qFileDialogUi->detailModeButton->setDown(false);
3506 qFileDialogUi->treeView->hide();
3507 qFileDialogUi->listView->show();
3508 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
3509 qFileDialogUi->listView->doItemsLayout();
3510}
3511
3513{
3514 qFileDialogUi->listModeButton->setDown(false);
3515 qFileDialogUi->detailModeButton->setDown(true);
3516 qFileDialogUi->listView->hide();
3517 qFileDialogUi->treeView->show();
3518 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
3519 qFileDialogUi->treeView->doItemsLayout();
3520}
3521
3528{
3529#if !QT_CONFIG(menu)
3531#else
3532 Q_Q(QFileDialog);
3533 QAbstractItemView *view = nullptr;
3534 if (q->viewMode() == QFileDialog::Detail)
3535 view = qFileDialogUi->treeView;
3536 else
3537 view = qFileDialogUi->listView;
3538 QModelIndex index = view->indexAt(position);
3539 index = mapToSource(index.sibling(index.row(), 0));
3540
3541 QMenu *menu = new QMenu(view);
3543
3544 if (index.isValid()) {
3545 // file context menu
3546 const bool ro = model && model->isReadOnly();
3547 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3552 menu->addSeparator();
3553 }
3555 if (qFileDialogUi->newFolderButton->isVisible()) {
3556 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
3558 }
3559 menu->popup(view->viewport()->mapToGlobal(position));
3560
3561#endif // QT_CONFIG(menu)
3562}
3563
3568{
3569 Q_Q(QFileDialog);
3570 QModelIndex index = qFileDialogUi->listView->currentIndex();
3571 index = index.sibling(index.row(), 0);
3572 if (q->viewMode() == QFileDialog::List)
3573 qFileDialogUi->listView->edit(index);
3574 else
3575 qFileDialogUi->treeView->edit(index);
3576}
3577
3579{
3580 QModelIndex modelIndex = model->index(path);
3581 return model->remove(modelIndex);
3582}
3583
3590{
3591 if (model->isReadOnly())
3592 return;
3593
3594 const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
3595 for (auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
3597 if (index == qFileDialogUi->listView->rootIndex())
3598 continue;
3599
3600 index = mapToSource(index.sibling(index.row(), 0));
3601 if (!index.isValid())
3602 continue;
3603
3605 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
3606
3607 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
3608#if QT_CONFIG(messagebox)
3609 Q_Q(QFileDialog);
3610 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
3611 QFileDialog::tr("'%1' is write protected.\nDo you want to delete it anyway?")
3612 .arg(fileName),
3614 return;
3615 else if (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
3616 QFileDialog::tr("Are you sure you want to delete '%1'?")
3617 .arg(fileName),
3619 return;
3620
3621 // the event loop has run, we have to validate if the index is valid because the model might have removed it.
3622 if (!index.isValid())
3623 return;
3624
3625#else
3626 if (!(p & QFile::WriteUser))
3627 return;
3628#endif // QT_CONFIG(messagebox)
3629
3630 if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
3631 if (!removeDirectory(filePath)) {
3632#if QT_CONFIG(messagebox)
3633 QMessageBox::warning(q, q->windowTitle(),
3634 QFileDialog::tr("Could not delete directory."));
3635#endif
3636 }
3637 } else {
3638 model->remove(index);
3639 }
3640 }
3641}
3642
3644{
3645 if (text.startsWith("//"_L1) || text.startsWith(u'\\')) {
3646 qFileDialogUi->listView->selectionModel()->clearSelection();
3647 return;
3648 }
3649
3650 const QStringList multipleFiles = typedFiles();
3651 if (multipleFiles.size() > 0) {
3652 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
3653 QList<QModelIndex> newFiles;
3654 for (const auto &file : multipleFiles) {
3655 QModelIndex idx = model->index(file);
3656 if (oldFiles.removeAll(idx) == 0)
3657 newFiles.append(idx);
3658 }
3659 for (const auto &newFile : std::as_const(newFiles))
3660 select(newFile);
3661 if (lineEdit()->hasFocus()) {
3662 auto *sm = qFileDialogUi->listView->selectionModel();
3663 for (const auto &oldFile : std::as_const(oldFiles))
3665 }
3666 }
3667}
3668
3673{
3674 Q_Q(QFileDialog);
3675 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
3677 if (!button)
3678 return;
3679 const QFileDialog::FileMode fileMode = q->fileMode();
3680
3681 bool enableButton = true;
3682 bool isOpenDirectory = false;
3683
3684 const QStringList files = q->selectedFiles();
3685 QString lineEditText = lineEdit()->text();
3686
3687 if (lineEditText.startsWith("//"_L1) || lineEditText.startsWith(u'\\')) {
3688 button->setEnabled(true);
3690 return;
3691 }
3692
3693 if (files.isEmpty()) {
3694 enableButton = false;
3695 } else if (lineEditText == ".."_L1) {
3696 isOpenDirectory = true;
3697 } else {
3698 switch (fileMode) {
3700 QString fn = files.first();
3701 QModelIndex idx = model->index(fn);
3702 if (!idx.isValid())
3704 if (!idx.isValid() || !model->isDir(idx))
3705 enableButton = false;
3706 break;
3707 }
3708 case QFileDialog::AnyFile: {
3709 QString fn = files.first();
3710 QFileInfo info(fn);
3711 QModelIndex idx = model->index(fn);
3712 QString fileDir;
3714 if (info.isDir()) {
3715 fileDir = info.canonicalFilePath();
3716 } else {
3717 fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
3718 fileName = fn.mid(fileDir.size() + 1);
3719 }
3720 if (lineEditText.contains(".."_L1)) {
3721 fileDir = info.canonicalFilePath();
3722 fileName = info.fileName();
3723 }
3724
3725 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
3726 enableButton = false;
3727 break;
3728 }
3729 if (idx.isValid() && model->isDir(idx)) {
3730 isOpenDirectory = true;
3731 enableButton = true;
3732 break;
3733 }
3734 if (!idx.isValid()) {
3735 const long maxLength = maxNameLength(fileDir);
3736 enableButton = maxLength < 0 || fileName.size() <= maxLength;
3737 }
3738 break;
3739 }
3742 for (const auto &file : files) {
3743 QModelIndex idx = model->index(file);
3744 if (!idx.isValid())
3746 if (!idx.isValid()) {
3747 enableButton = false;
3748 break;
3749 }
3750 if (idx.isValid() && model->isDir(idx)) {
3751 isOpenDirectory = true;
3752 break;
3753 }
3754 }
3755 break;
3756 default:
3757 break;
3758 }
3759 }
3760
3761 button->setEnabled(enableButton);
3762 updateOkButtonText(isOpenDirectory);
3763}
3764
3769{
3771 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
3772}
3773
3781{
3782 Q_Q(QFileDialog);
3783 // My Computer or a directory
3784 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
3785 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
3786 if (path.isEmpty() || model->isDir(sourceIndex)) {
3787 const QFileDialog::FileMode fileMode = q->fileMode();
3788 q->setDirectory(path);
3789 emit q->directoryEntered(path);
3790 if (fileMode == QFileDialog::Directory) {
3791 // ### find out why you have to do both of these.
3792 lineEdit()->setText(QString());
3793 lineEdit()->clear();
3794 }
3795 } else {
3796 // Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE)
3797 if ((!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, qFileDialogUi->treeView)
3799 && index.model()->flags(index) & Qt::ItemIsEnabled) {
3800 q->accept();
3801 }
3802 }
3803}
3804
3812{
3813 enum { UrlRole = Qt::UserRole + 1 };
3814
3815 #if QT_CONFIG(messagebox)
3816 Q_Q(QFileDialog);
3817#endif
3818 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
3819 qFileDialogUi->lookInCombo->modelColumn(),
3820 qFileDialogUi->lookInCombo->rootModelIndex());
3821 QString path2 = path;
3822 if (!index.isValid())
3824 else {
3825 path2 = index.data(UrlRole).toUrl().toLocalFile();
3826 index = mapFromSource(model->index(path2));
3827 }
3828 QDir dir(path2);
3829 if (!dir.exists())
3830 dir.setPath(getEnvironmentVariable(path2));
3831
3832 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
3834#if QT_CONFIG(messagebox)
3835 } else {
3836 QString message = QFileDialog::tr("%1\nDirectory not found.\nPlease verify the "
3837 "correct directory name was given.");
3838 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
3839#endif // QT_CONFIG(messagebox)
3840 }
3841}
3842
3850{
3851 QStringList nameFilters = options->nameFilters();
3852 if (index == nameFilters.size()) {
3853 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3854 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3855 options->setNameFilters(nameFilters);
3856 }
3857
3858 QString nameFilter = nameFilters.at(index);
3859 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3860 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3861 QString newNameFilterExtension;
3862 if (newNameFilters.size() > 0)
3863 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3864
3866 const QString fileNameExtension = QFileInfo(fileName).suffix();
3867 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3868 const qsizetype fileNameExtensionLength = fileNameExtension.size();
3869 fileName.replace(fileName.size() - fileNameExtensionLength,
3870 fileNameExtensionLength, newNameFilterExtension);
3871 qFileDialogUi->listView->clearSelection();
3873 }
3874 }
3875
3876 model->setNameFilters(newNameFilters);
3877}
3878
3886{
3887 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3888 const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3889 bool stripDirs = fileMode != QFileDialog::Directory;
3890
3891 QStringList allFiles;
3892 for (const auto &index : indexes) {
3893 if (stripDirs && model->isDir(mapToSource(index)))
3894 continue;
3895 allFiles.append(index.data().toString());
3896 }
3897 if (allFiles.size() > 1)
3898 for (qsizetype i = 0; i < allFiles.size(); ++i) {
3899 allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
3900 }
3901
3902 QString finalFiles = allFiles.join(u' ');
3903 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3904 lineEdit()->setText(finalFiles);
3905 else
3907}
3908
3915{
3916 Q_Q(QFileDialog);
3917 QDir::Filters dirFilters = q->filter();
3918 dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
3919 q->setFilter(dirFilters);
3920}
3921
3929{
3930 if (!qFileDialogUi->treeView
3931 || parent != qFileDialogUi->treeView->rootIndex()
3932 || !qFileDialogUi->treeView->selectionModel()
3933 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3934 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3935 return;
3936}
3937
3938void QFileDialogPrivate::fileRenamed(const QString &path, const QString &oldName, const QString &newName)
3939{
3940 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3941 if (fileMode == QFileDialog::Directory) {
3942 if (path == rootPath() && lineEdit()->text() == oldName)
3943 lineEdit()->setText(newName);
3944 }
3945}
3946
3948{
3949 Q_Q(QFileDialog);
3950 emit q->urlSelected(file);
3951 if (file.isLocalFile())
3952 emit q->fileSelected(file.toLocalFile());
3953}
3954
3956{
3957 Q_Q(QFileDialog);
3958 emit q->urlsSelected(files);
3959 QStringList localFiles;
3960 for (const QUrl &file : files)
3961 if (file.isLocalFile())
3962 localFiles.append(file.toLocalFile());
3963 if (!localFiles.isEmpty())
3964 emit q->filesSelected(localFiles);
3965}
3966
3968{
3969 Q_Q(QFileDialog);
3970 emit q->currentUrlChanged(file);
3971 if (file.isLocalFile())
3972 emit q->currentChanged(file.toLocalFile());
3973}
3974
3976{
3977 Q_Q(QFileDialog);
3978 emit q->directoryUrlEntered(directory);
3979 if (!directory.isEmpty()) { // Windows native dialogs occasionally emit signals with empty strings.
3980 *lastVisitedDir() = directory;
3981 if (directory.isLocalFile())
3982 emit q->directoryEntered(directory.toLocalFile());
3983 }
3984}
3985
3994
3995#if QT_CONFIG(shortcut)
3996 Q_Q(QFileDialog);
3997 if (event->matches(QKeySequence::Cancel)) {
3998 q->reject();
3999 return true;
4000 }
4001#endif
4002 switch (event->key()) {
4003 case Qt::Key_Backspace:
4005 return true;
4006 case Qt::Key_Back:
4007#ifdef QT_KEYPAD_NAVIGATION
4008 if (QApplicationPrivate::keypadNavigationEnabled())
4009 return false;
4010#endif
4011 case Qt::Key_Left:
4012 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
4014 return true;
4015 }
4016 break;
4017 default:
4018 break;
4019 }
4020 return false;
4021}
4022
4024{
4025#ifdef Q_OS_UNIX
4026 if (string.size() > 1 && string.startsWith(u'$')) {
4027 return QString::fromLocal8Bit(qgetenv(QStringView{string}.mid(1).toLatin1().constData()));
4028 }
4029#else
4030 if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
4031 return QString::fromLocal8Bit(qgetenv(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData()));
4032 }
4033#endif
4034 return string;
4035}
4036
4038 d_ptr = d_pointer;
4039 urlModel = new QUrlModel(this);
4040 urlModel->showFullPath = true;
4041 urlModel->setFileSystemModel(d_ptr->model);
4042 setModel(urlModel);
4043}
4044
4046{
4047 if (model()->rowCount() > 1)
4049
4050 urlModel->setUrls(QList<QUrl>());
4051 QList<QUrl> list;
4052 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
4053 while (idx.isValid()) {
4055 if (url.isValid())
4056 list.append(url);
4057 idx = idx.parent();
4058 }
4059 // add "my computer"
4060 list.append(QUrl("file:"_L1));
4061 urlModel->addUrls(list, 0);
4062 idx = model()->index(model()->rowCount() - 1, 0);
4063
4064 // append history
4065 QList<QUrl> urls;
4066 for (int i = 0; i < m_history.size(); ++i) {
4067 QUrl path = QUrl::fromLocalFile(m_history.at(i));
4068 if (!urls.contains(path))
4069 urls.prepend(path);
4070 }
4071 if (urls.size() > 0) {
4072 model()->insertRow(model()->rowCount());
4073 idx = model()->index(model()->rowCount()-1, 0);
4074 // ### TODO maybe add a horizontal line before this
4075 model()->setData(idx, QFileDialog::tr("Recent Places"));
4076 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
4077 if (m) {
4078 Qt::ItemFlags flags = m->flags(idx);
4079 flags &= ~Qt::ItemIsEnabled;
4080 m->item(idx.row(), idx.column())->setFlags(flags);
4081 }
4082 urlModel->addUrls(urls, -1, false);
4083 }
4084 setCurrentIndex(0);
4085
4087}
4088
4089// Exact same as QComboBox::paintEvent(), except we elide the text.
4091{
4092 QStylePainter painter(this);
4094
4095 // draw the combobox frame, focusrect and selected etc.
4098
4101 int size = editRect.width() - opt.iconSize.width() - 4;
4102 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
4103 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
4104
4105 // draw the icon and text
4106 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
4107}
4108
4110{
4111 d_ptr = d_pointer;
4113 setWrapping(true);
4116 setContextMenuPolicy(Qt::CustomContextMenu);
4117#if QT_CONFIG(draganddrop)
4118 setDragDropMode(QAbstractItemView::InternalMove);
4119#endif
4120}
4121
4123{
4124 int height = qMax(10, sizeHintForRow(0));
4125 return QSize(QListView::sizeHint().width() * 2, height * 30);
4126}
4127
4129{
4130#ifdef QT_KEYPAD_NAVIGATION
4131 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4133 return;
4134 }
4135#endif // QT_KEYPAD_NAVIGATION
4136
4137 if (!d_ptr->itemViewKeyboardEvent(e))
4139 e->accept();
4140}
4141
4143{
4144 d_ptr = d_pointer;
4146 setRootIsDecorated(false);
4147 setItemsExpandable(false);
4148 setSortingEnabled(true);
4150 header()->setStretchLastSection(false);
4153 setContextMenuPolicy(Qt::CustomContextMenu);
4154#if QT_CONFIG(draganddrop)
4155 setDragDropMode(QAbstractItemView::InternalMove);
4156#endif
4157}
4158
4160{
4161#ifdef QT_KEYPAD_NAVIGATION
4162 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4164 return;
4165 }
4166#endif // QT_KEYPAD_NAVIGATION
4167
4168 if (!d_ptr->itemViewKeyboardEvent(e))
4170 e->accept();
4171}
4172
4174{
4175 int height = qMax(10, sizeHintForRow(0));
4177 return QSize(sizeHint.width() * 4, height * 30);
4178}
4179
4185{
4186#ifdef QT_KEYPAD_NAVIGATION
4187 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
4189 return;
4190 }
4191#endif // QT_KEYPAD_NAVIGATION
4192
4193#if QT_CONFIG(shortcut)
4194 int key = e->key();
4195#endif
4197#if QT_CONFIG(shortcut)
4198 if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
4199#endif
4200 e->accept();
4201}
4202
4203#if QT_CONFIG(fscompleter)
4204
4206{
4207 const QFileSystemModel *dirModel;
4208 if (proxyModel)
4209 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
4210 else
4211 dirModel = sourceModel;
4212 QString currentLocation = dirModel->rootPath();
4214 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
4215#if defined(Q_OS_UNIX)
4216 if (currentLocation == QDir::separator())
4217 return path.remove(0, currentLocation.size());
4218#endif
4219 if (currentLocation.endsWith(u'/'))
4220 return path.remove(0, currentLocation.size());
4221 else
4222 return path.remove(0, currentLocation.size()+1);
4223 }
4224 return index.data(QFileSystemModel::FilePathRole).toString();
4225}
4226
4228{
4229 if (path.isEmpty())
4230 return QStringList(completionPrefix());
4231
4234#if defined(Q_OS_WIN)
4235 if (pathCopy == "\\"_L1 || pathCopy == "\\\\"_L1)
4236 return QStringList(pathCopy);
4237 QString doubleSlash("\\\\"_L1);
4238 if (pathCopy.startsWith(doubleSlash))
4239 pathCopy = pathCopy.mid(2);
4240 else
4241 doubleSlash.clear();
4242#elif defined(Q_OS_UNIX)
4243 {
4244 QString tildeExpanded = qt_tildeExpansion(pathCopy);
4245 if (tildeExpanded != pathCopy) {
4246 QFileSystemModel *dirModel;
4247 if (proxyModel)
4248 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
4249 else
4250 dirModel = sourceModel;
4251 dirModel->fetchMore(dirModel->index(tildeExpanded));
4252 }
4253 pathCopy = std::move(tildeExpanded);
4254 }
4255#endif
4256
4257#if defined(Q_OS_WIN)
4258 QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
4259 if (!doubleSlash.isEmpty() && !parts.isEmpty())
4260 parts[0].prepend(doubleSlash);
4261 if (pathCopy.endsWith(sep))
4262 parts.append(QString());
4263#else
4264 QStringList parts = pathCopy.split(sep);
4265 if (pathCopy[0] == sep) // read the "/" at the beginning as the split removed it
4266 parts[0] = sep;
4267#endif
4268
4269#if defined(Q_OS_WIN)
4270 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
4271#else
4272 bool startsFromRoot = pathCopy[0] == sep;
4273#endif
4274 if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
4275 const QFileSystemModel *dirModel;
4276 if (proxyModel)
4277 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
4278 else
4279 dirModel = sourceModel;
4280 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
4281#if defined(Q_OS_WIN)
4282 if (currentLocation.endsWith(u':'))
4283 currentLocation.append(sep);
4284#endif
4285 if (currentLocation.contains(sep) && path != currentLocation) {
4286 QStringList currentLocationList = splitPath(currentLocation);
4287 while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) == ".."_L1) {
4288 parts.removeFirst();
4289 currentLocationList.removeLast();
4290 }
4291 if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
4292 currentLocationList.removeLast();
4293 return currentLocationList + parts;
4294 }
4295 }
4296 return parts;
4297}
4298
4299#endif // QT_CONFIG(completer)
4300
4301
4303
4304#include "moc_qfiledialog.cpp"
void clicked(bool checked=false)
This signal is emitted when the button is activated (i.e., pressed down then released while the mouse...
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 bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
Sets the role data for the item at index to value.
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been inserted into the model.
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 activated(const QModelIndex &index)
This signal is emitted when the item specified by index is activated by the user.
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 triggered(QAction *)
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 triggered(bool checked=false)
This signal is emitted when an action is activated by the user; for example, when the user clicks a m...
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
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
QByteArray sliced(qsizetype pos) const &
Definition qbytearray.h:200
\inmodule QtCore
virtual void initStyleOption(QStyleOptionComboBox *option) const
Initialize option with the values from this QComboBox.
@ AdjustToContentsOnFirstShow
Definition qcombobox.h:83
void activated(int index)
This signal is sent when the user chooses an item in the combobox.
void textActivated(const QString &)
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
void setModel(QAbstractItemModel *c)
Sets the model which provides completions to model.
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
\inmodule QtCore\reentrant
Definition qdatastream.h:46
void accepted()
This signal is emitted when a button inside the button box is clicked, as long as it was defined with...
StandardButton
These enums describe flags for standard buttons.
void rejected()
This signal is emitted when a button inside the button box is clicked, as long as it was defined with...
bool setNativeDialogVisible(bool visible)
Definition qdialog.cpp:162
virtual void setVisible(bool visible)
Definition qdialog.cpp:754
bool nativeDialogInUse
Definition qdialog_p.h:86
The QDialog class is the base class of dialog windows.
Definition qdialog.h:19
virtual void reject()
Hides the modal dialog and sets the result code to Rejected.
Definition qdialog.cpp:639
virtual int exec()
Shows the dialog as a \l{QDialog::Modal Dialogs}{modal dialog}, blocking until the user closes it.
Definition qdialog.cpp:543
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:602
virtual void open()
Definition qdialog.cpp:503
void setVisible(bool visible) override
\reimp
Definition qdialog.cpp:744
virtual void accept()
Hides the modal dialog and sets the result code to Accepted.
Definition qdialog.cpp:628
\inmodule QtCore
Definition qdir.h:20
static bool isRelativePath(const QString &path)
Returns true if path is relative; returns false if it is absolute.
Definition qdir.cpp:2412
static QDir current()
Returns the application's current directory.
Definition qdir.h:219
static QChar separator()
Returns the native directory separator: "/" under Unix and "\\" under Windows.
Definition qdir.h:209
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2398
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:2103
bool isEmpty(Filters filters=Filters(AllEntries|NoDotAndDotDot)) const
Returns whether the directory is empty.
Definition qdir.cpp:1969
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2054
static QString rootPath()
Returns the absolute path of the root directory.
Definition qdir.cpp:2159
@ Files
Definition qdir.h:23
@ Hidden
Definition qdir.h:35
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
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 > &)
void nativeCurrentChanged(const QUrl &file)
QModelIndex select(const QModelIndex &index) const
QModelIndex mapFromSource(const QModelIndex &index) const
void emitFilesSelected(const QStringList &files)
void nativeEnterDirectory(const QUrl &directory)
static void setLastVisitedDirectory(const QUrl &dir)
void navigate(HistoryItem &)
QList< QPersistentModelIndex > PersistentModelIndexList
void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)
QString getEnvironmentVariable(const QString &string)
static long maxNameLength(const QString &path)
bool removeDirectory(const QString &path)
QAbstractItemView * currentView() const
QScopedPointer< Ui_QFileDialog > qFileDialogUi
QFileSystemModel * model
void fileRenamed(const QString &path, const QString &oldName, const QString &newName)
void pathChanged(const QString &)
QAction * showHiddenAction
void emitUrlSelected(const QUrl &file)
void goToDirectory(const QString &)
void enterDirectory(const QModelIndex &index)
QList< QUrl > sidebarUrls
static QString toInternal(const QString &path)
QLineEdit * lineEdit() const
QStringList typedFiles() const
QList< QUrl > selectedFiles_sys() const
void emitUrlsSelected(const QList< QUrl > &files)
QFileIconProvider defaultIconProvider
QAction * newFolderAction
void showHeader(QAction *)
QList< HistoryItem > currentHistory
void useNameFilter(int index)
virtual void helperPrepareShow(QPlatformDialogHelper *) override
void setRootIndex(const QModelIndex &index) const
void setVisible(bool visible) override
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 currentChanged(const QModelIndex &index)
void showContextMenu(const QPoint &position)
bool canBeNativeDialog() const override
void updateOkButtonText(bool saveAsOnFolder=false)
QPlatformFileDialogHelper * platformFileDialogHelper() const
bool itemViewKeyboardEvent(QKeyEvent *event)
void init(const QFileDialogArgs &args)
void goToUrl(const QUrl &url)
virtual void initHelper(QPlatformDialogHelper *) override
virtual void helperDone(QDialog::DialogCode, QPlatformDialogHelper *) override
QSharedPointer< QFileDialogOptions > options
void autoCompleteFileName(const QString &)
void rowsInserted(const QModelIndex &parent)
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 allows 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; that is,...
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 returns 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 returns one or more existing files selected by the user.
bool restoreState(const QByteArray &state)
~QFileDialog()
Destroys the file dialog.
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 returns 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 returns 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
void done(int result) override
\reimp
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)
void filterSelected(const QString &filter)
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
static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint, QWidget *parent=nullptr)
This is a convenience static function that saves fileContent to a file, using a file name and locatio...
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.
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 setVisible(bool visible) override
\reimp
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)
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 returns one or more existing files selected by the user.
static void getOpenFileContent(const QString &nameFilter, const std::function< void(const QString &, const QByteArray &)> &fileContentsReady, QWidget *parent=nullptr)
This is a convenience static function that returns the content of a file selected by the user.
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:503
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; that is, what information about each file is di...
Definition qfiledialog.h:38
void setIconProvider(QAbstractFileIconProvider *provider)
Sets the icon provider used by the filedialog to the specified provider.
QDir::Filters filter() const
bool isSymLink() const
QString suffix() const
Returns the suffix (extension) of the file.
QString fileName() const
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
bool isAbsolute() const
Returns true if the file system entry's path is absolute, otherwise returns false (that is,...
Definition qfileinfo.h:120
bool exists() const
Returns true if the file system entry this QFileInfo refers to 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)
void fileRenamed(const QString &path, const QString &oldName, const QString &newName)
This signal is emitted whenever a file with the oldName is successfully renamed to newName.
void rootPathChanged(const QString &newPath)
This signal is emitted whenever the root path has been changed to a newPath.
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
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
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
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.
void setSortIndicator(int logicalIndex, Qt::SortOrder order)
Sets the sort indicator for the section specified by the given logicalIndex in the direction specifie...
void setStretchLastSection(bool stretch)
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.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
This signal is emitted whenever the selection changes.
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This signal is emitted whenever the current item changes.
The QKeyEvent class describes a key event.
Definition qevent.h:424
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
The QLineEdit widget is a one-line text editor.
Definition qlineedit.h:28
void returnPressed()
This signal is emitted when the Return or Enter key is used.
void selectAll()
Selects all the text (highlights it) and moves the cursor to the end.
void clear()
Clears the contents of the line edit.
void textChanged(const QString &)
This signal is emitted whenever the text changes.
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)
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
T value(qsizetype i) const
Definition qlist.h:664
const_reverse_iterator crbegin() const noexcept
Definition qlist.h:638
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
const_reverse_iterator crend() const noexcept
Definition qlist.h:639
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:2310
QAction * addSeparator()
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:1921
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3117
The QMessageBox class provides a modal dialog for informing the user or for asking the user a questio...
Definition qmessagebox.h:22
static StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
\inmodule QtCore
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:72
QObject * parent
Definition qobject.h:73
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
Definition qobject_p.h:328
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
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.
void fileSelected(const QUrl &file)
void currentChanged(const QUrl &path)
void directoryEntered(const QUrl &directory)
static QStringList cleanFilterList(const QString &filter)
void filterSelected(const QString &filter)
void filesSelected(const QList< QUrl > &files)
\inmodule QtCore\reentrant
Definition qpoint.h:25
The QPushButton widget provides a command button.
Definition qpushbutton.h:20
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore \reentrant
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.
const_iterator cbegin() const noexcept
Definition qset.h:138
\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
void activated()
This signal is emitted when the user types the shortcut's key sequence.
void goToUrl(const QUrl &url)
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:483
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
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:127
The QStandardItemModel class provides a generic model for storing custom data.
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
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:129
QString left(qsizetype n) const &
Definition qstring.h:363
QByteArray toLatin1() const &
Definition qstring.h:630
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
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:5455
QString sliced(qsizetype pos) const &
Definition qstring.h:394
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6995
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:8218
static QString fromStdString(const std::string &s)
Definition qstring.h:1447
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
std::string toStdString() const
Returns a std::string object with the data contained in this QString.
Definition qstring.h:1444
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
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:5506
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1369
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:8084
QString & append(QChar c)
Definition qstring.cpp:3252
\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:646
@ SP_ArrowForward
Definition qstyle.h:772
@ SP_FileDialogListView
Definition qstyle.h:753
@ SP_ArrowBack
Definition qstyle.h:771
@ SP_FileDialogNewFolder
Definition qstyle.h:749
@ SP_FileDialogDetailedView
Definition qstyle.h:750
@ SP_FileDialogToParent
Definition qstyle.h:748
@ 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:204
void addUrls(const QList< QUrl > &urls, int row=-1, bool move=true)
Add urls list into the list at row.
Definition qsidebar.cpp:218
bool showFullPath
Definition qsidebar_p.h:65
void setFileSystemModel(QFileSystemModel *model)
QFileSystemModel to get index's from, clears existing rows.
Definition qsidebar.cpp:273
\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:3368
static QList< QUrl > fromStringList(const QStringList &uris, ParsingMode mode=TolerantMode)
Definition qurl.cpp:3660
bool isLocalFile() const
Definition qurl.cpp:3445
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2497
static QStringList toStringList(const QList< QUrl > &uris, FormattingOptions options=FormattingOptions(PrettyDecoded))
Definition qurl.cpp:3644
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1882
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1896
@ PreferLocalFile
Definition qurl.h:114
void setPath(const QString &path, ParsingMode mode=DecodedMode)
Sets the path of the URL to path.
Definition qurl.cpp:2414
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
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:704
QList< QAction * > actions
Definition qwidget_p.h:709
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:3358
QPalette palette
the widget's palette
Definition qwidget.h:132
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7875
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9382
QStyle * style() const
Definition qwidget.cpp:2600
bool hasFocus() const
Definition qwidget.cpp:6446
bool isVisible() const
Definition qwidget.h:874
bool visible
whether the widget is visible
Definition qwidget.h:144
QString text
QPushButton * button
[2]
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)
Definition qcompare.h:63
@ CTRL
@ SHIFT
@ NavigationModeKeypadDirectional
@ WA_Resized
Definition qnamespace.h:308
@ WA_DontShowOnScreen
Definition qnamespace.h:383
@ WA_DeleteOnClose
Definition qnamespace.h:321
@ Horizontal
Definition qnamespace.h:99
@ ImhNoPredictiveText
@ UserRole
@ DisplayRole
@ Key_Backspace
Definition qnamespace.h:666
@ Key_Left
Definition qnamespace.h:677
@ Key_Up
Definition qnamespace.h:678
@ Key_H
Definition qnamespace.h:554
@ Key_Back
Definition qnamespace.h:846
@ AscendingOrder
Definition qnamespace.h:122
@ AltModifier
@ AA_DontUseNativeDialogs
Definition qnamespace.h:458
@ CaseInsensitive
@ CaseSensitive
@ SkipEmptyParts
Definition qnamespace.h:128
@ ActionsContextMenu
@ CustomContextMenu
@ ElideMiddle
Definition qnamespace.h:191
@ ItemIsEnabled
@ ItemIsDropEnabled
#define Q_UNLIKELY(x)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
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:166
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 SIGNAL(a)
Definition qobjectdefs.h:53
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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLint GLsizei width
GLuint color
[2]
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
const GLchar * marker
GLuint name
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:49
ptrdiff_t qsizetype
Definition qtypes.h:165
qint64 qlonglong
Definition qtypes.h:63
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]
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]
QHostInfo info
[0]
QQuickView * view
[0]
view create()
char * toString(const MyType &t)
[31]
QJSValueList args
QFileDialogArgs(const QUrl &url={})
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962