1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <private/qwidgetitemdata_p.h>
44 #include "qfiledialog.h"
46 #ifndef QT_NO_FILEDIALOG
47 #include "qfiledialog_p.h"
48 #include <private/qguiapplication_p.h>
49 #include <qfontmetrics.h>
51 #include <qheaderview.h>
52 #include <qshortcut.h>
53 #include <qgridlayout.h>
55 #include <qmessagebox.h>
56 #include <qinputdialog.h>
58 #include <qsettings.h>
60 #include <qapplication.h>
61 #include <qstylepainter.h>
62 #if !defined(Q_OS_WINCE)
63 #include "ui_qfiledialog.h"
65 #define Q_EMBEDDED_SMALLSCREEN
66 #include "ui_qfiledialog_embedded.h"
67 #if defined(Q_OS_WINCE)
68 extern bool qt_priv_ptr_valid;
71 #if defined(Q_OS_UNIX)
73 #elif defined(Q_OS_WIN)
74 # include <QtCore/qt_windows.h>
79 Q_GLOBAL_STATIC(QString, lastVisitedDir)
84 Exported hooks that can be used to customize the static functions.
86 typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
87 Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0;
89 typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
90 Q_WIDGETS_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0;
92 typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
93 Q_WIDGETS_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0;
95 typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
96 Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook = 0;
100 \brief The QFileDialog class provides a dialog that allow users to select files or directories.
101 \ingroup standard-dialogs
104 The QFileDialog class enables a user to traverse the file system in
105 order to select one or many files or a directory.
107 The easiest way to create a QFileDialog is to use the static
108 functions. On Windows, Mac OS X, KDE and GNOME, these static functions will
109 call the native file dialog when possible.
111 \snippet code/src_gui_dialogs_qfiledialog.cpp 0
113 In the above example, a modal QFileDialog is created using a static
114 function. The dialog initially displays the contents of the "/home/jana"
115 directory, and displays files matching the patterns given in the
116 string "Image Files (*.png *.jpg *.bmp)". The parent of the file dialog
117 is set to \e this, and the window title is set to "Open Image".
119 If you want to use multiple filters, separate each one with
120 \e two semicolons. For example:
122 \snippet code/src_gui_dialogs_qfiledialog.cpp 1
124 You can create your own QFileDialog without using the static
125 functions. By calling setFileMode(), you can specify what the user must
126 select in the dialog:
128 \snippet code/src_gui_dialogs_qfiledialog.cpp 2
130 In the above example, the mode of the file dialog is set to
131 AnyFile, meaning that the user can select any file, or even specify a
132 file that doesn't exist. This mode is useful for creating a
133 "Save As" file dialog. Use ExistingFile if the user must select an
134 existing file, or \l Directory if only a directory may be selected.
135 See the \l QFileDialog::FileMode enum for the complete list of modes.
137 The fileMode property contains the mode of operation for the dialog;
138 this indicates what types of objects the user is expected to select.
139 Use setNameFilter() to set the dialog's file filter. For example:
141 \snippet code/src_gui_dialogs_qfiledialog.cpp 3
143 In the above example, the filter is set to \c{"Images (*.png *.xpm *.jpg)"},
144 this means that only files with the extension \c png, \c xpm,
145 or \c jpg will be shown in the QFileDialog. You can apply
146 several filters by using setNameFilters(). Use selectNameFilter() to select
147 one of the filters you've given as the file dialog's default filter.
149 The file dialog has two view modes: \l{QFileDialog::}{List} and
150 \l{QFileDialog::}{Detail}.
151 \l{QFileDialog::}{List} presents the contents of the current directory
152 as a list of file and directory names. \l{QFileDialog::}{Detail} also
153 displays a list of file and directory names, but provides additional
154 information alongside each name, such as the file size and modification
155 date. Set the mode with setViewMode():
157 \snippet code/src_gui_dialogs_qfiledialog.cpp 4
159 The last important function you will need to use when creating your
160 own file dialog is selectedFiles().
162 \snippet code/src_gui_dialogs_qfiledialog.cpp 5
164 In the above example, a modal file dialog is created and shown. If
165 the user clicked OK, the file they selected is put in \c fileName.
167 The dialog's working directory can be set with setDirectory().
168 Each file in the current directory can be selected using
169 the selectFile() function.
171 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
172 how to use QFileDialog as well as other built-in Qt dialogs.
174 \sa QDir, QFileInfo, QFile, QColorDialog, QFontDialog, {Standard Dialogs Example},
175 {Application Example}
179 \enum QFileDialog::AcceptMode
186 \enum QFileDialog::ViewMode
188 This enum describes the view mode of the file dialog; i.e. what
189 information about each file will be displayed.
191 \value Detail Displays an icon, a name, and details for each item in
193 \value List Displays only an icon and a name for each item in the
200 \enum QFileDialog::FileMode
202 This enum is used to indicate what the user may select in the file
203 dialog; i.e. what the dialog will return if the user clicks OK.
205 \value AnyFile The name of a file, whether it exists or not.
206 \value ExistingFile The name of a single existing file.
207 \value Directory The name of a directory. Both files and
208 directories are displayed.
209 \value ExistingFiles The names of zero or more existing files.
211 This value is obsolete since Qt 4.5:
213 \value DirectoryOnly Use \c Directory and setOption(ShowDirsOnly, true) instead.
219 \enum QFileDialog::Option
221 \value ShowDirsOnly Only show directories in the file dialog. By
222 default both files and directories are shown. (Valid only in the
223 \l Directory file mode.)
225 \value DontResolveSymlinks Don't resolve symlinks in the file
226 dialog. By default symlinks are resolved.
228 \value DontConfirmOverwrite Don't ask for confirmation if an
229 existing file is selected. By default confirmation is requested.
231 \value DontUseNativeDialog Don't use the native file dialog. By
232 default, the native file dialog is used unless you use a subclass
233 of QFileDialog that contains the Q_OBJECT macro.
235 \value ReadOnly Indicates that the model is readonly.
237 \value HideNameFilterDetails Indicates if the file name filter details are
240 \value DontUseSheet In previous versions of Qt, the static
241 functions would create a sheet by default if the static function
242 was given a parent. This is no longer supported and does nothing in Qt 4.5, The
243 static functions will always be an application modal dialog. If
244 you want to use sheets, use QFileDialog::open() instead.
249 \enum QFileDialog::DialogLabel
259 \fn void QFileDialog::filesSelected(const QStringList &selected)
261 When the selection changes and the dialog is accepted, this signal is
262 emitted with the (possibly empty) list of \a selected files.
264 \sa currentChanged(), QDialog::Accepted
269 \fn void QFileDialog::fileSelected(const QString &file)
271 When the selection changes and the dialog is accepted, this signal is
272 emitted with the (possibly empty) selected \a file.
274 \sa currentChanged(), QDialog::Accepted
279 \fn void QFileDialog::currentChanged(const QString &path)
281 When the current file changes, this signal is emitted with the
282 new file name as the \a path parameter.
288 \fn void QFileDialog::directoryEntered(const QString &directory)
291 This signal is emitted when the user enters a \a directory.
295 \fn void QFileDialog::filterSelected(const QString &filter)
298 This signal is emitted when the user selects a \a filter.
301 //#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
302 //bool Q_WIDGETS_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API
305 QT_BEGIN_INCLUDE_NAMESPACE
307 #include <qwindowsstyle.h>
309 #include <qshortcut.h>
311 #include <qmacstyle_mac.h>
313 QT_END_INCLUDE_NAMESPACE
316 \fn QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags flags)
318 Constructs a file dialog with the given \a parent and widget \a flags.
320 QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
321 : QDialog(*new QFileDialogPrivate, parent, f)
325 d->lineEdit()->selectAll();
329 Constructs a file dialog with the given \a parent and \a caption that
330 initially displays the contents of the specified \a directory.
331 The contents of the directory are filtered before being shown in the
332 dialog, using a semicolon-separated list of filters specified by
335 QFileDialog::QFileDialog(QWidget *parent,
336 const QString &caption,
337 const QString &directory,
338 const QString &filter)
339 : QDialog(*new QFileDialogPrivate, parent, 0)
342 d->init(directory, filter, caption);
343 d->lineEdit()->selectAll();
349 QFileDialog::QFileDialog(const QFileDialogArgs &args)
350 : QDialog(*new QFileDialogPrivate, args.parent, 0)
353 d->init(args.directory, args.filter, args.caption);
354 setFileMode(args.mode);
355 setOptions(args.options);
356 selectFile(args.selection);
357 d->lineEdit()->selectAll();
361 Destroys the file dialog.
363 QFileDialog::~QFileDialog()
365 #ifndef QT_NO_SETTINGS
366 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
367 settings.beginGroup(QLatin1String("Qt"));
368 settings.setValue(QLatin1String("filedialog"), saveState());
374 Sets the \a urls that are located in the sidebar.
378 \snippet filedialogurls.cpp 0
380 The file dialog will then look like this:
382 \image filedialogurls.png
386 void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
389 d->qFileDialogUi->sidebar->setUrls(urls);
394 Returns a list of urls that are currently in the sidebar
396 QList<QUrl> QFileDialog::sidebarUrls() const
398 Q_D(const QFileDialog);
399 return d->qFileDialogUi->sidebar->urls();
402 static const qint32 QFileDialogMagic = 0xbe;
406 Saves the state of the dialog's layout, history and current directory.
408 Typically this is used in conjunction with QSettings to remember the size
409 for a future session. A version number is stored as part of the data.
411 QByteArray QFileDialog::saveState() const
413 Q_D(const QFileDialog);
416 QDataStream stream(&data, QIODevice::WriteOnly);
418 stream << qint32(QFileDialogMagic);
419 stream << qint32(version);
420 stream << d->qFileDialogUi->splitter->saveState();
421 stream << d->qFileDialogUi->sidebar->urls();
423 stream << *lastVisitedDir();
424 stream << d->qFileDialogUi->treeView->header()->saveState();
425 stream << qint32(viewMode());
431 Restores the dialogs's layout, history and current directory to the \a state specified.
433 Typically this is used in conjunction with QSettings to restore the size
436 Returns false if there are errors
438 bool QFileDialog::restoreState(const QByteArray &state)
442 QByteArray sd = state;
443 QDataStream stream(&sd, QIODevice::ReadOnly);
446 QByteArray splitterState;
447 QByteArray headerData;
448 QList<QUrl> bookmarks;
450 QString currentDirectory;
456 if (marker != QFileDialogMagic || v != version)
459 stream >> splitterState
466 if (!d->qFileDialogUi->splitter->restoreState(splitterState))
468 QList<int> list = d->qFileDialogUi->splitter->sizes();
469 if (list.count() >= 2 && list.at(0) == 0 && list.at(1) == 0) {
470 for (int i = 0; i < list.count(); ++i)
471 list[i] = d->qFileDialogUi->splitter->widget(i)->sizeHint().width();
472 d->qFileDialogUi->splitter->setSizes(list);
475 d->qFileDialogUi->sidebar->setUrls(bookmarks);
476 while (history.count() > 5)
479 setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
480 QHeaderView *headerView = d->qFileDialogUi->treeView->header();
481 if (!headerView->restoreState(headerData))
484 QList<QAction*> actions = headerView->actions();
485 QAbstractItemModel *abstractModel = d->model;
486 #ifndef QT_NO_PROXYMODEL
488 abstractModel = d->proxyModel;
490 int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
491 for (int i = 1; i < total; ++i)
492 actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
494 setViewMode(ViewMode(viewMode));
501 void QFileDialog::changeEvent(QEvent *e)
504 if (e->type() == QEvent::LanguageChange) {
505 d->retranslateWindowTitle();
506 d->retranslateStrings();
508 QDialog::changeEvent(e);
511 QFileDialogPrivate::QFileDialogPrivate()
513 #ifndef QT_NO_PROXYMODEL
517 currentHistoryLocation(-1),
521 useDefaultCaption(true),
522 defaultFileTypes(true),
524 options(new QFileDialogOptions)
528 QFileDialogPrivate::~QFileDialogPrivate()
532 void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
534 QFileDialog *d = q_func();
535 QObject::connect(h, SIGNAL(fileSelected(QString)), d, SIGNAL(fileSelected(QString)));
536 QObject::connect(h, SIGNAL(filesSelected(QStringList)), d, SIGNAL(filesSelected(QStringList)));
537 QObject::connect(h, SIGNAL(currentChanged(QString)), d, SIGNAL(currentChanged(QString)));
538 QObject::connect(h, SIGNAL(directoryEntered(QString)), d, SIGNAL(directoryEntered(QString)));
539 QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
540 static_cast<QPlatformFileDialogHelper *>(h)->setOptions(options);
543 void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
546 options->setWindowTitle(q->windowTitle());
547 options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(q->viewMode()));
548 options->setHistory(q->history());
549 options->setSidebarUrls(qFileDialogUi->sidebar->urls());
550 const QDir directory = q->directory();
551 options->setInitialDirectory(directory.exists() ?
552 directory.absolutePath() :
554 options->setInitiallySelectedNameFilter(q->selectedNameFilter());
555 options->setInitiallySelectedFiles(q->selectedFiles());
558 void QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
560 if (code == QDialog::Accepted) {
562 q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
563 q->setSidebarUrls(options->sidebarUrls());
564 q->setHistory(options->history());
568 void QFileDialogPrivate::retranslateWindowTitle()
571 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
573 if (q->acceptMode() == QFileDialog::AcceptOpen) {
574 const QFileDialog::FileMode fileMode = q->fileMode();
575 if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory)
576 q->setWindowTitle(QFileDialog::tr("Find Directory"));
578 q->setWindowTitle(QFileDialog::tr("Open"));
580 q->setWindowTitle(QFileDialog::tr("Save As"));
582 setWindowTitle = q->windowTitle();
585 void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
587 *lastVisitedDir() = dir;
590 void QFileDialogPrivate::updateFileNameLabel()
592 if (!options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
593 switch (q_func()->fileMode()) {
594 case QFileDialog::DirectoryOnly:
595 case QFileDialog::Directory:
596 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("Directory:"));
599 setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("File &name:"));
605 void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)
608 // 'Save as' at a folder: Temporarily change to "Open".
609 if (saveAsOnFolder) {
610 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Open"));
611 } else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
612 setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));
615 switch (q->fileMode()) {
616 case QFileDialog::DirectoryOnly:
617 case QFileDialog::Directory:
618 setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Choose"));
621 setLabelTextControl(QFileDialog::Accept,
622 q->acceptMode() == QFileDialog::AcceptOpen ?
623 QFileDialog::tr("&Open") :
624 QFileDialog::tr("&Save"));
630 void QFileDialogPrivate::retranslateStrings()
634 if (defaultFileTypes)
635 q->setNameFilter(QFileDialog::tr("All Files (*)"));
637 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
638 QAbstractItemModel *abstractModel = model;
639 #ifndef QT_NO_PROXYMODEL
641 abstractModel = proxyModel;
643 int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
644 for (int i = 1; i < total; ++i) {
645 actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
649 renameAction->setText(QFileDialog::tr("&Rename"));
650 deleteAction->setText(QFileDialog::tr("&Delete"));
651 showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
652 newFolderAction->setText(QFileDialog::tr("&New Folder"));
653 qFileDialogUi->retranslateUi(q);
654 updateFileNameLabel();
657 void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
660 emit q->filesSelected(files);
661 if (files.count() == 1)
662 emit q->fileSelected(files.first());
665 bool QFileDialogPrivate::canBeNativeDialog()
668 if (nativeDialogInUse)
670 if (q->testAttribute(Qt::WA_DontShowOnScreen))
672 if (q->options() & QFileDialog::DontUseNativeDialog)
675 QLatin1String staticName(QFileDialog::staticMetaObject.className());
676 QLatin1String dynamicName(q->metaObject()->className());
677 return (staticName == dynamicName);
682 Sets the given \a option to be enabled if \a on is true; otherwise,
683 clears the given \a option.
685 \sa options, testOption()
687 void QFileDialog::setOption(Option option, bool on)
689 const QFileDialog::Options previousOptions = options();
690 if (!(previousOptions & option) != !on)
691 setOptions(previousOptions ^ option);
697 Returns true if the given \a option is enabled; otherwise, returns
700 \sa options, setOption()
702 bool QFileDialog::testOption(Option option) const
704 Q_D(const QFileDialog);
705 return d->options->testOption(static_cast<QFileDialogOptions::FileDialogOption>(option));
709 \property QFileDialog::options
710 \brief the various options that affect the look and feel of the dialog
713 By default, all options are disabled.
715 Options should be set before showing the dialog. Setting them while the
716 dialog is visible is not guaranteed to have an immediate effect on the
717 dialog (depending on the option and on the platform).
719 \sa setOption(), testOption()
721 void QFileDialog::setOptions(Options options)
725 Options changed = (options ^ QFileDialog::options());
729 d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));
730 if (changed & DontResolveSymlinks)
731 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
732 if (changed & ReadOnly) {
733 bool ro = (options & ReadOnly);
734 d->model->setReadOnly(ro);
735 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
736 d->renameAction->setEnabled(!ro);
737 d->deleteAction->setEnabled(!ro);
739 if (changed & HideNameFilterDetails)
740 setNameFilters(d->options->nameFilters());
742 if (changed & ShowDirsOnly)
743 setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
746 QFileDialog::Options QFileDialog::options() const
748 Q_D(const QFileDialog);
749 return QFileDialog::Options(int(d->options->options()));
757 This function connects one of its signals to the slot specified by \a receiver
758 and \a member. The specific signal depends is filesSelected() if fileMode is
759 ExistingFiles and fileSelected() if fileMode is anything else.
761 The signal will be disconnected from the slot when the dialog is closed.
763 void QFileDialog::open(QObject *receiver, const char *member)
766 const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))
767 : SIGNAL(fileSelected(QString));
768 connect(this, signal, receiver, member);
769 d->signalToDisconnectOnClose = signal;
770 d->receiverToDisconnectOnClose = receiver;
771 d->memberToDisconnectOnClose = member;
780 void QFileDialog::setVisible(bool visible)
784 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
786 } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
789 if (d->canBeNativeDialog()){
790 if (d->setNativeDialogVisible(visible)){
791 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
792 // updates the state correctly, but skips showing the non-native version:
793 setAttribute(Qt::WA_DontShowOnScreen);
794 #ifndef QT_NO_FSCOMPLETER
795 //So the completer don't try to complete and therefore to show a popup
796 d->completer->setModel(0);
799 setAttribute(Qt::WA_DontShowOnScreen, false);
800 #ifndef QT_NO_FSCOMPLETER
801 if (d->proxyModel != 0)
802 d->completer->setModel(d->proxyModel);
804 d->completer->setModel(d->model);
809 if (!d->nativeDialogInUse)
810 d->qFileDialogUi->fileNameEdit->setFocus();
812 QDialog::setVisible(visible);
817 set the directory to url
819 void QFileDialogPrivate::_q_goToUrl(const QUrl &url)
821 //The shortcut in the side bar may have a parent that is not fetched yet (e.g. an hidden file)
822 //so we force the fetching
823 QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(), true);
824 QModelIndex idx = model->d_func()->index(node);
825 _q_enterDirectory(idx);
829 \fn void QFileDialog::setDirectory(const QDir &directory)
835 Sets the file dialog's current \a directory.
837 void QFileDialog::setDirectory(const QString &directory)
840 QString newDirectory = directory;
841 QFileInfo info(directory);
842 //we remove .. and . from the given path if exist
843 if (!directory.isEmpty())
844 newDirectory = QDir::cleanPath(directory);
846 if (!directory.isEmpty() && newDirectory.isEmpty())
849 d->setLastVisitedDirectory(newDirectory);
851 if (d->nativeDialogInUse){
852 d->setDirectory_sys(newDirectory);
855 if (d->rootPath() == newDirectory)
857 QModelIndex root = d->model->setRootPath(newDirectory);
858 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
859 if (root != d->rootIndex()) {
860 #ifndef QT_NO_FSCOMPLETER
861 if (directory.endsWith(QLatin1Char('/')))
862 d->completer->setCompletionPrefix(newDirectory);
864 d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/'));
866 d->setRootIndex(root);
868 d->qFileDialogUi->listView->selectionModel()->clear();
872 Returns the directory currently being displayed in the dialog.
874 QDir QFileDialog::directory() const
876 Q_D(const QFileDialog);
877 return QDir(d->nativeDialogInUse ? d->directory_sys() : d->rootPath());
881 Selects the given \a filename in the file dialog.
885 void QFileDialog::selectFile(const QString &filename)
888 if (filename.isEmpty())
891 if (d->nativeDialogInUse){
892 d->selectFile_sys(filename);
896 if (!QDir::isRelativePath(filename)) {
897 QFileInfo info(filename);
898 QString filenamePath = info.absoluteDir().path();
900 if (d->model->rootPath() != filenamePath)
901 setDirectory(filenamePath);
904 QModelIndex index = d->model->index(filename);
906 if (!index.isValid()) {
907 // save as dialog where we want to input a default value
908 QString text = filename;
909 if (QFileInfo(filename).isAbsolute()) {
910 QString current = d->rootPath();
911 text.remove(current);
912 if (text.at(0) == QDir::separator()
914 //On Windows both cases can happen
915 || text.at(0) == QLatin1Char('/')
918 text = text.remove(0,1);
922 file = index.data().toString();
924 d->qFileDialogUi->listView->selectionModel()->clear();
925 if (!isVisible() || !d->lineEdit()->hasFocus())
926 d->lineEdit()->setText(file);
930 Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0)
934 if (!path.startsWith(QLatin1Char('~')))
937 QStringList tokens = ret.split(QDir::separator());
938 if (tokens.first() == QLatin1String("~")) {
939 ret.replace(0, 1, QDir::homePath());
941 QString userName = tokens.first();
942 userName.remove(0, 1);
943 #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
947 const int bufSize = sizeof(buf);
949 #if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
950 tmpPw = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize);
952 err = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize, &tmpPw);
956 const QString homePath = QString::fromLocal8Bit(pw.pw_dir);
958 passwd *pw = getpwnam(userName.toLocal8Bit().constData());
961 const QString homePath = QString::fromLocal8Bit(pw->pw_dir);
963 ret.replace(0, tokens.first().length(), homePath);
972 Returns the text in the line edit which can be one or more file names
974 QStringList QFileDialogPrivate::typedFiles() const
976 Q_Q(const QFileDialog);
978 QString editText = lineEdit()->text();
979 if (!editText.contains(QLatin1Char('"'))) {
981 const QString prefix = q->directory().absolutePath() + QDir::separator();
982 if (QFile::exists(prefix + editText))
985 files << qt_tildeExpansion(editText);
991 // " is used to separate files like so: "file1" "file2" "file3" ...
992 // ### need escape character for filenames with quotes (")
993 QStringList tokens = editText.split(QLatin1Char('\"'));
994 for (int i=0; i<tokens.size(); ++i) {
996 continue; // Every even token is a separator
998 const QString token = tokens.at(i);
999 const QString prefix = q->directory().absolutePath() + QDir::separator();
1000 if (QFile::exists(prefix + token))
1003 files << qt_tildeExpansion(token);
1005 files << toInternal(tokens.at(i));
1009 return addDefaultSuffixToFiles(files);
1012 QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesToFix) const
1015 for (int i=0; i<filesToFix.size(); ++i) {
1016 QString name = toInternal(filesToFix.at(i));
1017 QFileInfo info(name);
1018 // if the filename has no suffix, add the default suffix
1019 const QString defaultSuffix = options->defaultSuffix();
1020 if (!defaultSuffix.isEmpty() && !info.isDir() && name.lastIndexOf(QLatin1Char('.')) == -1)
1021 name += QLatin1Char('.') + defaultSuffix;
1022 if (info.isAbsolute()) {
1025 // at this point the path should only have Qt path separators.
1026 // This check is needed since we might be at the root directory
1027 // and on Windows it already ends with slash.
1028 QString path = rootPath();
1029 if (!path.endsWith(QLatin1Char('/')))
1030 path += QLatin1Char('/');
1040 Returns a list of strings containing the absolute paths of the
1041 selected files in the dialog. If no files are selected, or
1042 the mode is not ExistingFiles or ExistingFile, selectedFiles() contains the current path in the viewport.
1044 \sa selectedNameFilter(), selectFile()
1046 QStringList QFileDialog::selectedFiles() const
1048 Q_D(const QFileDialog);
1049 if (d->nativeDialogInUse)
1050 return d->addDefaultSuffixToFiles(d->selectedFiles_sys());
1052 QModelIndexList indexes = d->qFileDialogUi->listView->selectionModel()->selectedRows();
1054 for (int i = 0; i < indexes.count(); ++i)
1055 files.append(indexes.at(i).data(QFileSystemModel::FilePathRole).toString());
1057 if (files.isEmpty() && !d->lineEdit()->text().isEmpty())
1058 files = d->typedFiles();
1059 const FileMode fm = fileMode();
1060 if (files.isEmpty() && !(fm == ExistingFile || fm == ExistingFiles))
1061 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1066 Makes a list of filters from ;;-separated text.
1067 Used by the mac and windows implementations
1069 QStringList qt_make_filter_list(const QString &filter)
1074 return QStringList();
1076 QString sep(QLatin1String(";;"));
1077 int i = f.indexOf(sep, 0);
1079 if (f.indexOf(QLatin1Char('\n'), 0) != -1) {
1080 sep = QLatin1Char('\n');
1081 i = f.indexOf(sep, 0);
1085 return f.split(sep);
1091 Sets the filter used in the file dialog to the given \a filter.
1093 If \a filter contains a pair of parentheses containing one or more
1094 of \b{anything*something}, separated by spaces, then only the
1095 text contained in the parentheses is used as the filter. This means
1096 that these calls are all equivalent:
1098 \snippet code/src_gui_dialogs_qfiledialog.cpp 6
1100 \sa setNameFilters()
1102 void QFileDialog::setNameFilter(const QString &filter)
1104 setNameFilters(qt_make_filter_list(filter));
1109 \property QFileDialog::nameFilterDetailsVisible
1111 \brief This property holds whether the filter details is shown or not.
1114 When this property is true (the default), the filter details are shown
1115 in the combo box. When the property is set to false, these are hidden.
1117 Use setOption(HideNameFilterDetails, !\e enabled) or
1118 !testOption(HideNameFilterDetails).
1120 void QFileDialog::setNameFilterDetailsVisible(bool enabled)
1122 setOption(HideNameFilterDetails, !enabled);
1125 bool QFileDialog::isNameFilterDetailsVisible() const
1127 return !testOption(HideNameFilterDetails);
1132 Strip the filters by removing the details, e.g. (*.*).
1134 QStringList qt_strip_filters(const QStringList &filters)
1136 QStringList strippedFilters;
1137 QRegExp r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
1138 for (int i = 0; i < filters.count(); ++i) {
1140 int index = r.indexIn(filters[i]);
1142 filterName = r.cap(1);
1143 strippedFilters.append(filterName.simplified());
1145 return strippedFilters;
1152 Sets the \a filters used in the file dialog.
1154 \snippet code/src_gui_dialogs_qfiledialog.cpp 7
1156 void QFileDialog::setNameFilters(const QStringList &filters)
1159 d->defaultFileTypes = (filters == QStringList(QFileDialog::tr("All Files (*)")));
1160 QStringList cleanedFilters;
1161 for (int i = 0; i < filters.count(); ++i) {
1162 cleanedFilters << filters[i].simplified();
1164 d->options->setNameFilters(cleanedFilters);
1166 d->qFileDialogUi->fileTypeCombo->clear();
1167 if (cleanedFilters.isEmpty())
1170 if (testOption(HideNameFilterDetails))
1171 d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
1173 d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
1175 d->_q_useNameFilter(0);
1181 Returns the file type filters that are in operation on this file
1184 QStringList QFileDialog::nameFilters() const
1186 return d_func()->options->nameFilters();
1192 Sets the current file type \a filter. Multiple filters can be
1193 passed in \a filter by separating them with semicolons or spaces.
1195 \sa setNameFilter(), setNameFilters(), selectedNameFilter()
1197 void QFileDialog::selectNameFilter(const QString &filter)
1200 if (d->nativeDialogInUse) {
1201 d->selectNameFilter_sys(filter);
1205 if (testOption(HideNameFilterDetails)) {
1206 i = d->qFileDialogUi->fileTypeCombo->findText(qt_strip_filters(qt_make_filter_list(filter)).first());
1208 i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1211 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1212 d->_q_useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1219 Returns the filter that the user selected in the file dialog.
1223 QString QFileDialog::selectedNameFilter() const
1225 Q_D(const QFileDialog);
1226 if (d->nativeDialogInUse)
1227 return d->selectedNameFilter_sys();
1229 return d->qFileDialogUi->fileTypeCombo->currentText();
1235 Returns the filter that is used when displaying files.
1239 QDir::Filters QFileDialog::filter() const
1241 Q_D(const QFileDialog);
1242 return d->model->filter();
1248 Sets the filter used by the model to \a filters. The filter is used
1249 to specify the kind of files that should be shown.
1254 void QFileDialog::setFilter(QDir::Filters filters)
1257 d->model->setFilter(filters);
1258 d->options->setFilter(filters);
1259 if (d->nativeDialogInUse){
1264 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1268 \property QFileDialog::viewMode
1269 \brief the way files and directories are displayed in the dialog
1271 By default, the \c Detail mode is used to display information about
1272 files and directories.
1276 void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
1280 d->_q_showDetailsView();
1282 d->_q_showListView();
1285 QFileDialog::ViewMode QFileDialog::viewMode() const
1287 Q_D(const QFileDialog);
1288 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1292 \property QFileDialog::fileMode
1293 \brief the file mode of the dialog
1295 The file mode defines the number and type of items that the user is
1296 expected to select in the dialog.
1298 By default, this property is set to AnyFile.
1300 This function will set the labels for the FileName and
1301 \l{QFileDialog::}{Accept} \l{DialogLabel}s. It is possible to set
1302 custom text after the call to setFileMode().
1306 void QFileDialog::setFileMode(QFileDialog::FileMode mode)
1309 d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));
1310 d->retranslateWindowTitle();
1312 // keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete)
1313 setOption(ShowDirsOnly, mode == DirectoryOnly);
1315 // set selection mode and behavior
1316 QAbstractItemView::SelectionMode selectionMode;
1317 if (mode == QFileDialog::ExistingFiles)
1318 selectionMode = QAbstractItemView::ExtendedSelection;
1320 selectionMode = QAbstractItemView::SingleSelection;
1321 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1322 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1324 d->model->setFilter(d->filterForMode(filter()));
1325 // setup file type for directory
1326 if (mode == DirectoryOnly || mode == Directory) {
1327 d->qFileDialogUi->fileTypeCombo->clear();
1328 d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
1329 d->qFileDialogUi->fileTypeCombo->setEnabled(false);
1331 d->updateFileNameLabel();
1332 d->updateOkButtonText();
1333 if (d->nativeDialogInUse){
1338 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1339 d->_q_updateOkButton();
1342 QFileDialog::FileMode QFileDialog::fileMode() const
1344 Q_D(const QFileDialog);
1345 return static_cast<FileMode>(d->options->fileMode());
1349 \property QFileDialog::acceptMode
1350 \brief the accept mode of the dialog
1352 The action mode defines whether the dialog is for opening or saving files.
1354 By default, this property is set to \l{AcceptOpen}.
1358 void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
1361 d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode));
1362 QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
1363 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1364 d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
1365 d->_q_updateOkButton();
1366 if (mode == AcceptSave) {
1367 d->qFileDialogUi->lookInCombo->setEditable(false);
1369 d->retranslateWindowTitle();
1370 // we need to recreate the native dialog when changing the AcceptMode
1371 d->deletePlatformHelper();
1372 // clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
1373 setAttribute(Qt::WA_DontShowOnScreen, false);
1377 Returns the file system model index that is the root index in the
1380 QModelIndex QFileDialogPrivate::rootIndex() const {
1381 return mapToSource(qFileDialogUi->listView->rootIndex());
1384 QAbstractItemView *QFileDialogPrivate::currentView() const {
1385 if (!qFileDialogUi->stackedWidget)
1387 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1388 return qFileDialogUi->listView;
1389 return qFileDialogUi->treeView;
1392 QLineEdit *QFileDialogPrivate::lineEdit() const {
1393 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1396 int QFileDialogPrivate::maxNameLength(const QString &path)
1398 #if defined(Q_OS_UNIX)
1399 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
1400 #elif defined(Q_OS_WINCE)
1403 #elif defined(Q_OS_WIN)
1405 const QString drive = path.left(3);
1406 if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == false)
1416 Sets the view root index to be the file system model index
1418 void QFileDialogPrivate::setRootIndex(const QModelIndex &index) const {
1419 Q_ASSERT(index.isValid() ? index.model() == model : true);
1420 QModelIndex idx = mapFromSource(index);
1421 qFileDialogUi->treeView->setRootIndex(idx);
1422 qFileDialogUi->listView->setRootIndex(idx);
1425 Select a file system model index
1426 returns the index that was selected (or not depending upon sortfilterproxymodel)
1428 QModelIndex QFileDialogPrivate::select(const QModelIndex &index) const {
1429 Q_ASSERT(index.isValid() ? index.model() == model : true);
1431 QModelIndex idx = mapFromSource(index);
1432 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1433 qFileDialogUi->listView->selectionModel()->select(idx,
1434 QItemSelectionModel::Select | QItemSelectionModel::Rows);
1438 QFileDialog::AcceptMode QFileDialog::acceptMode() const
1440 Q_D(const QFileDialog);
1441 return static_cast<AcceptMode>(d->options->acceptMode());
1445 \property QFileDialog::readOnly
1447 \brief Whether the filedialog is read-only
1449 If this property is set to false, the file dialog will allow renaming,
1450 and deleting of files and directories and creating directories.
1452 Use setOption(ReadOnly, \e enabled) or testOption(ReadOnly) instead.
1454 void QFileDialog::setReadOnly(bool enabled)
1456 setOption(ReadOnly, enabled);
1459 bool QFileDialog::isReadOnly() const
1461 return testOption(ReadOnly);
1465 \property QFileDialog::resolveSymlinks
1467 \brief whether the filedialog should resolve shortcuts
1469 If this property is set to true, the file dialog will resolve
1470 shortcuts or symbolic links.
1472 Use setOption(DontResolveSymlinks, !\a enabled) or
1473 !testOption(DontResolveSymlinks).
1475 void QFileDialog::setResolveSymlinks(bool enabled)
1477 setOption(DontResolveSymlinks, !enabled);
1480 bool QFileDialog::resolveSymlinks() const
1482 return !testOption(DontResolveSymlinks);
1486 \property QFileDialog::confirmOverwrite
1488 \brief whether the filedialog should ask before accepting a selected file,
1489 when the accept mode is AcceptSave
1491 Use setOption(DontConfirmOverwrite, !\e enabled) or
1492 !testOption(DontConfirmOverwrite) instead.
1494 void QFileDialog::setConfirmOverwrite(bool enabled)
1496 setOption(DontConfirmOverwrite, !enabled);
1499 bool QFileDialog::confirmOverwrite() const
1501 return !testOption(DontConfirmOverwrite);
1505 \property QFileDialog::defaultSuffix
1506 \brief suffix added to the filename if no other suffix was specified
1508 This property specifies a string that will be added to the
1509 filename if it has no suffix already. The suffix is typically
1510 used to indicate the file type (e.g. "txt" indicates a text
1513 void QFileDialog::setDefaultSuffix(const QString &suffix)
1516 d->options->setDefaultSuffix(suffix);
1519 QString QFileDialog::defaultSuffix() const
1521 Q_D(const QFileDialog);
1522 return d->options->defaultSuffix();
1526 Sets the browsing history of the filedialog to contain the given
1529 void QFileDialog::setHistory(const QStringList &paths)
1532 d->qFileDialogUi->lookInCombo->setHistory(paths);
1535 void QFileDialogComboBox::setHistory(const QStringList &paths)
1538 // Only populate the first item, showPopup will populate the rest if needed
1540 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1541 //On windows the popup display the "C:\", convert to nativeSeparators
1542 QUrl url = QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()));
1545 urlModel->setUrls(list);
1549 Returns the browsing history of the filedialog as a list of paths.
1551 QStringList QFileDialog::history() const
1553 Q_D(const QFileDialog);
1554 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1555 //On windows the popup display the "C:\", convert to nativeSeparators
1556 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1557 if (!currentHistory.contains(newHistory))
1558 currentHistory << newHistory;
1559 return currentHistory;
1563 Sets the item delegate used to render items in the views in the
1564 file dialog to the given \a delegate.
1566 \warning You should not share the same instance of a delegate between views.
1567 Doing so can cause incorrect or unintuitive editing behavior since each
1568 view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
1569 signal, and attempt to access, modify or close an editor that has already been closed.
1571 Note that the model used is QFileSystemModel. It has custom item data roles, which is
1572 described by the \l{QFileSystemModel::}{Roles} enum. You can use a QFileIconProvider if
1573 you only want custom icons.
1575 \sa itemDelegate(), setIconProvider(), QFileSystemModel
1577 void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
1580 d->qFileDialogUi->listView->setItemDelegate(delegate);
1581 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1585 Returns the item delegate used to render the items in the views in the filedialog.
1587 QAbstractItemDelegate *QFileDialog::itemDelegate() const
1589 Q_D(const QFileDialog);
1590 return d->qFileDialogUi->listView->itemDelegate();
1594 Sets the icon provider used by the filedialog to the specified \a provider.
1596 void QFileDialog::setIconProvider(QFileIconProvider *provider)
1599 d->model->setIconProvider(provider);
1600 //It forces the refresh of all entries in the side bar, then we can get new icons
1601 d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
1605 Returns the icon provider used by the filedialog.
1607 QFileIconProvider *QFileDialog::iconProvider() const
1609 Q_D(const QFileDialog);
1610 return d->model->iconProvider();
1613 void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)
1616 case QFileDialog::LookIn:
1617 qFileDialogUi->lookInLabel->setText(text);
1619 case QFileDialog::FileName:
1620 qFileDialogUi->fileNameLabel->setText(text);
1622 case QFileDialog::FileType:
1623 qFileDialogUi->fileTypeLabel->setText(text);
1625 case QFileDialog::Accept:
1626 if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
1627 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
1628 button->setText(text);
1630 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
1631 button->setText(text);
1634 case QFileDialog::Reject:
1635 if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
1636 button->setText(text);
1642 Sets the \a text shown in the filedialog in the specified \a label.
1645 void QFileDialog::setLabelText(DialogLabel label, const QString &text)
1648 d->options->setLabelText(static_cast<QFileDialogOptions::DialogLabel>(label), text);
1649 d->setLabelTextControl(label, text);
1653 Returns the text shown in the filedialog in the specified \a label.
1655 QString QFileDialog::labelText(DialogLabel label) const
1657 QPushButton *button;
1658 Q_D(const QFileDialog);
1661 return d->qFileDialogUi->lookInLabel->text();
1663 return d->qFileDialogUi->fileNameLabel->text();
1665 return d->qFileDialogUi->fileTypeLabel->text();
1667 if (acceptMode() == AcceptOpen)
1668 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
1670 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
1672 return button->text();
1674 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
1676 return button->text();
1682 For the native file dialogs
1685 #if defined(Q_WS_WIN)
1686 extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
1687 QString *initialDirectory,
1688 QString *selectedFilter);
1690 extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
1691 QString *initialDirectory,
1692 QString *selectedFilter);
1694 extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
1695 QString *initialDirectory,
1696 QString *selectedFilter);
1698 extern QString qt_win_get_existing_directory(const QFileDialogArgs &args);
1702 This is a convenience static function that returns an existing file
1703 selected by the user. If the user presses Cancel, it returns a null string.
1705 \snippet code/src_gui_dialogs_qfiledialog.cpp 8
1707 The function creates a modal file dialog with the given \a parent widget.
1708 If \a parent is not 0, the dialog will be shown centered over the parent
1711 The file dialog's working directory will be set to \a dir. If \a dir
1712 includes a file name, the file will be selected. Only files that match the
1713 given \a filter are shown. The filter selected is set to \a selectedFilter.
1714 The parameters \a dir, \a selectedFilter, and \a filter may be empty
1715 strings. If you want multiple filters, separate them with ';;', for
1719 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1722 The \a options argument holds various options about how to run the dialog,
1723 see the QFileDialog::Option enum for more information on the flags you can
1726 The dialog's caption is set to \a caption. If \a caption is not specified
1727 then a default caption will be used.
1729 On Windows, and Mac OS X, this static function will use the
1730 native file dialog and not a QFileDialog.
1732 On Windows the dialog will spin a blocking modal event loop that will not
1733 dispatch any QTimers, and if \a parent is not 0 then it will position the
1734 dialog just below the parent's title bar.
1736 On Unix/X11, the normal behavior of the file dialog is to resolve and
1737 follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
1738 the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
1739 \a options includes DontResolveSymlinks, the file dialog will treat
1740 symlinks as regular directories.
1742 \warning Do not delete \a parent during the execution of the dialog. If you
1743 want to do this, you should create the dialog yourself using one of the
1744 QFileDialog constructors.
1746 \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory()
1748 QString QFileDialog::getOpenFileName(QWidget *parent,
1749 const QString &caption,
1751 const QString &filter,
1752 QString *selectedFilter,
1755 if (qt_filedialog_open_filename_hook && !(options & DontUseNativeDialog))
1756 return qt_filedialog_open_filename_hook(parent, caption, dir, filter, selectedFilter, options);
1757 QFileDialogArgs args;
1758 args.parent = parent;
1759 args.caption = caption;
1760 args.directory = QFileDialogPrivate::workingDirectory(dir);
1761 args.selection = QFileDialogPrivate::initialSelection(dir);
1762 args.filter = filter;
1763 args.mode = ExistingFile;
1764 args.options = options;
1765 #if defined(Q_WS_WIN)
1766 if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
1767 return qt_win_get_open_file_name(args, &(args.directory), selectedFilter);
1771 // create a qt dialog
1772 QFileDialog dialog(args);
1774 dialog.selectNameFilter(*selectedFilter);
1775 if (dialog.exec() == QDialog::Accepted) {
1777 *selectedFilter = dialog.selectedNameFilter();
1778 return dialog.selectedFiles().value(0);
1784 This is a convenience static function that will return one or more existing
1785 files selected by the user.
1787 \snippet code/src_gui_dialogs_qfiledialog.cpp 9
1789 This function creates a modal file dialog with the given \a parent widget.
1790 If \a parent is not 0, the dialog will be shown centered over the parent
1793 The file dialog's working directory will be set to \a dir. If \a dir
1794 includes a file name, the file will be selected. The filter is set to
1795 \a filter so that only those files which match the filter are shown. The
1796 filter selected is set to \a selectedFilter. The parameters \a dir,
1797 \a selectedFilter and \a filter may be empty strings. If you need multiple
1798 filters, separate them with ';;', for instance:
1801 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1804 The dialog's caption is set to \a caption. If \a caption is not specified
1805 then a default caption will be used.
1807 On Windows, and Mac OS X, this static function will use the
1808 native file dialog and not a QFileDialog.
1810 On Windows the dialog will spin a blocking modal event loop that will not
1811 dispatch any QTimers, and if \a parent is not 0 then it will position the
1812 dialog just below the parent's title bar.
1814 On Unix/X11, the normal behavior of the file dialog is to resolve and
1815 follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
1816 the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}.
1817 The \a options argument holds various options about how to run the dialog,
1818 see the QFileDialog::Option enum for more information on the flags you can
1821 \note If you want to iterate over the list of files, you should iterate
1822 over a copy. For example:
1824 \snippet code/src_gui_dialogs_qfiledialog.cpp 10
1826 \warning Do not delete \a parent during the execution of the dialog. If you
1827 want to do this, you should create the dialog yourself using one of the
1828 QFileDialog constructors.
1830 \sa getOpenFileName(), getSaveFileName(), getExistingDirectory()
1832 QStringList QFileDialog::getOpenFileNames(QWidget *parent,
1833 const QString &caption,
1835 const QString &filter,
1836 QString *selectedFilter,
1839 if (qt_filedialog_open_filenames_hook && !(options & DontUseNativeDialog))
1840 return qt_filedialog_open_filenames_hook(parent, caption, dir, filter, selectedFilter, options);
1841 QFileDialogArgs args;
1842 args.parent = parent;
1843 args.caption = caption;
1844 args.directory = QFileDialogPrivate::workingDirectory(dir);
1845 args.selection = QFileDialogPrivate::initialSelection(dir);
1846 args.filter = filter;
1847 args.mode = ExistingFiles;
1848 args.options = options;
1850 #if defined(Q_WS_WIN)
1851 if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
1852 return qt_win_get_open_file_names(args, &(args.directory), selectedFilter);
1856 // create a qt dialog
1857 QFileDialog dialog(args);
1859 dialog.selectNameFilter(*selectedFilter);
1860 if (dialog.exec() == QDialog::Accepted) {
1862 *selectedFilter = dialog.selectedNameFilter();
1863 return dialog.selectedFiles();
1865 return QStringList();
1869 This is a convenience static function that will return a file name selected
1870 by the user. The file does not have to exist.
1872 It creates a modal file dialog with the given \a parent widget. If
1873 \a parent is not 0, the dialog will be shown centered over the parent
1876 \snippet code/src_gui_dialogs_qfiledialog.cpp 11
1878 The file dialog's working directory will be set to \a dir. If \a dir
1879 includes a file name, the file will be selected. Only files that match the
1880 \a filter are shown. The filter selected is set to \a selectedFilter. The
1881 parameters \a dir, \a selectedFilter, and \a filter may be empty strings.
1882 Multiple filters are separated with ';;'. For instance:
1885 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1888 The \a options argument holds various options about how to run the dialog,
1889 see the QFileDialog::Option enum for more information on the flags you can
1892 The default filter can be chosen by setting \a selectedFilter to the
1895 The dialog's caption is set to \a caption. If \a caption is not specified,
1896 a default caption will be used.
1898 On Windows, and Mac OS X, this static function will use the
1899 native file dialog and not a QFileDialog.
1901 On Windows the dialog will spin a blocking modal event loop that will not
1902 dispatch any QTimers, and if \a parent is not 0 then it will position the
1903 dialog just below the parent's title bar. On Mac OS X, with its native file
1904 dialog, the filter argument is ignored.
1906 On Unix/X11, the normal behavior of the file dialog is to resolve and
1907 follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
1908 the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
1909 \a options includes DontResolveSymlinks the file dialog will treat symlinks
1910 as regular directories.
1912 \warning Do not delete \a parent during the execution of the dialog. If you
1913 want to do this, you should create the dialog yourself using one of the
1914 QFileDialog constructors.
1916 \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory()
1918 QString QFileDialog::getSaveFileName(QWidget *parent,
1919 const QString &caption,
1921 const QString &filter,
1922 QString *selectedFilter,
1925 if (qt_filedialog_save_filename_hook && !(options & DontUseNativeDialog))
1926 return qt_filedialog_save_filename_hook(parent, caption, dir, filter, selectedFilter, options);
1927 QFileDialogArgs args;
1928 args.parent = parent;
1929 args.caption = caption;
1930 args.directory = QFileDialogPrivate::workingDirectory(dir);
1931 args.selection = QFileDialogPrivate::initialSelection(dir);
1932 args.filter = filter;
1933 args.mode = AnyFile;
1934 args.options = options;
1936 #if defined(Q_WS_WIN)
1937 if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) {
1938 return qt_win_get_save_file_name(args, &(args.directory), selectedFilter);
1942 // create a qt dialog
1943 QFileDialog dialog(args);
1944 dialog.setAcceptMode(AcceptSave);
1946 dialog.selectNameFilter(*selectedFilter);
1947 if (dialog.exec() == QDialog::Accepted) {
1949 *selectedFilter = dialog.selectedNameFilter();
1950 return dialog.selectedFiles().value(0);
1957 This is a convenience static function that will return an existing
1958 directory selected by the user.
1960 \snippet code/src_gui_dialogs_qfiledialog.cpp 12
1962 This function creates a modal file dialog with the given \a parent widget.
1963 If \a parent is not 0, the dialog will be shown centered over the parent
1966 The dialog's working directory is set to \a dir, and the caption is set to
1967 \a caption. Either of these may be an empty string in which case the
1968 current directory and a default caption will be used respectively.
1970 The \a options argument holds various options about how to run the dialog,
1971 see the QFileDialog::Option enum for more information on the flags you can
1972 pass. To ensure a native file dialog, \l{QFileDialog::}{ShowDirsOnly} must
1975 On Windows, and Mac OS X, this static function will use the
1976 native file dialog and not a QFileDialog. On Windows CE, if the device has
1977 no native file dialog, a QFileDialog will be used.
1979 On Unix/X11, the normal behavior of the file dialog is to resolve and
1980 follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
1981 the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
1982 \a options includes DontResolveSymlinks, the file dialog will treat
1983 symlinks as regular directories.
1985 On Windows the dialog will spin a blocking modal event loop that will not
1986 dispatch any QTimers, and if \a parent is not 0 then it will position the
1987 dialog just below the parent's title bar.
1989 \warning Do not delete \a parent during the execution of the dialog. If you
1990 want to do this, you should create the dialog yourself using one of the
1991 QFileDialog constructors.
1993 \sa getOpenFileName(), getOpenFileNames(), getSaveFileName()
1995 QString QFileDialog::getExistingDirectory(QWidget *parent,
1996 const QString &caption,
2000 if (qt_filedialog_existing_directory_hook && !(options & DontUseNativeDialog))
2001 return qt_filedialog_existing_directory_hook(parent, caption, dir, options);
2002 QFileDialogArgs args;
2003 args.parent = parent;
2004 args.caption = caption;
2005 args.directory = QFileDialogPrivate::workingDirectory(dir);
2006 args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
2007 args.options = options;
2009 #if defined(Q_WS_WIN)
2010 if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
2011 #if defined(Q_OS_WINCE)
2012 && qt_priv_ptr_valid
2015 return qt_win_get_existing_directory(args);
2019 // create a qt dialog
2020 QFileDialog dialog(args);
2021 if (dialog.exec() == QDialog::Accepted) {
2022 return dialog.selectedFiles().value(0);
2027 inline static QString _qt_get_directory(const QString &path)
2029 QFileInfo info = QFileInfo(QDir::current(), path);
2030 if (info.exists() && info.isDir())
2031 return QDir::cleanPath(info.absoluteFilePath());
2032 info.setFile(info.absolutePath());
2033 if (info.exists() && info.isDir())
2034 return info.absoluteFilePath();
2038 Get the initial directory path
2040 \sa initialSelection()
2042 QString QFileDialogPrivate::workingDirectory(const QString &path)
2044 if (!path.isEmpty()) {
2045 QString directory = _qt_get_directory(path);
2046 if (!directory.isEmpty())
2049 QString directory = _qt_get_directory(*lastVisitedDir());
2050 if (!directory.isEmpty())
2052 return QDir::currentPath();
2056 Get the initial selection given a path. The initial directory
2057 can contain both the initial directory and initial selection
2060 \sa workingDirectory()
2062 QString QFileDialogPrivate::initialSelection(const QString &path)
2064 if (!path.isEmpty()) {
2065 QFileInfo info(path);
2067 return info.fileName();
2075 void QFileDialog::done(int result)
2079 QDialog::done(result);
2081 if (d->receiverToDisconnectOnClose) {
2082 disconnect(this, d->signalToDisconnectOnClose,
2083 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2084 d->receiverToDisconnectOnClose = 0;
2086 d->memberToDisconnectOnClose.clear();
2087 d->signalToDisconnectOnClose.clear();
2093 void QFileDialog::accept()
2096 QStringList files = selectedFiles();
2097 if (files.isEmpty())
2099 if (d->nativeDialogInUse){
2100 d->emitFilesSelected(files);
2105 QString lineEditText = d->lineEdit()->text();
2106 // "hidden feature" type .. and then enter, and it will move up a dir
2107 // special case for ".."
2108 if (lineEditText == QLatin1String("..")) {
2109 d->_q_navigateToParent();
2110 bool block = d->qFileDialogUi->fileNameEdit->blockSignals(true);
2111 d->lineEdit()->selectAll();
2112 d->qFileDialogUi->fileNameEdit->blockSignals(block);
2116 switch (fileMode()) {
2119 QString fn = files.first();
2122 info = QFileInfo(d->getEnvironmentVariable(fn));
2123 if (!info.exists()) {
2124 #ifndef QT_NO_MESSAGEBOX
2125 QString message = tr("%1\nDirectory not found.\nPlease verify the "
2126 "correct directory name was given.");
2127 QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
2128 #endif // QT_NO_MESSAGEBOX
2132 d->emitFilesSelected(files);
2139 QString fn = files.first();
2142 setDirectory(info.absoluteFilePath());
2146 if (!info.exists()) {
2147 int maxNameLength = d->maxNameLength(info.path());
2148 if (maxNameLength >= 0 && info.fileName().length() > maxNameLength)
2152 // check if we have to ask for permission to overwrite the file
2153 if (!info.exists() || !confirmOverwrite() || acceptMode() == AcceptOpen) {
2154 d->emitFilesSelected(QStringList(fn));
2156 #ifndef QT_NO_MESSAGEBOX
2158 if (QMessageBox::warning(this, windowTitle(),
2159 tr("%1 already exists.\nDo you want to replace it?")
2160 .arg(info.fileName()),
2161 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
2162 == QMessageBox::Yes) {
2163 d->emitFilesSelected(QStringList(fn));
2173 for (int i = 0; i < files.count(); ++i) {
2174 QFileInfo info(files.at(i));
2176 info = QFileInfo(d->getEnvironmentVariable(files.at(i)));
2177 if (!info.exists()) {
2178 #ifndef QT_NO_MESSAGEBOX
2179 QString message = tr("%1\nFile not found.\nPlease verify the "
2180 "correct file name was given.");
2181 QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
2182 #endif // QT_NO_MESSAGEBOX
2186 setDirectory(info.absoluteFilePath());
2187 d->lineEdit()->clear();
2191 d->emitFilesSelected(files);
2200 Create widgets, layout and set default values
2202 void QFileDialogPrivate::init(const QString &directory, const QString &nameFilter,
2203 const QString &caption)
2206 if (!caption.isEmpty()) {
2207 useDefaultCaption = false;
2208 setWindowTitle = caption;
2209 q->setWindowTitle(caption);
2213 createMenuActions();
2214 retranslateStrings();
2215 q->setFileMode(QFileDialog::AnyFile);
2217 #ifndef QT_NO_SETTINGS
2218 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
2219 settings.beginGroup(QLatin1String("Qt"));
2220 if (!directory.isEmpty())
2221 setLastVisitedDirectory(workingDirectory(directory));
2222 q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
2225 #if defined(Q_EMBEDDED_SMALLSCREEN)
2226 qFileDialogUi->lookInLabel->setVisible(false);
2227 qFileDialogUi->fileNameLabel->setVisible(false);
2228 qFileDialogUi->fileTypeLabel->setVisible(false);
2229 qFileDialogUi->sidebar->hide();
2232 if (!nameFilter.isEmpty())
2233 q->setNameFilter(nameFilter);
2234 q->setAcceptMode(QFileDialog::AcceptOpen);
2235 q->setDirectory(workingDirectory(directory));
2236 q->selectFile(initialSelection(directory));
2238 _q_updateOkButton();
2239 q->resize(q->sizeHint());
2245 Create the widgets, set properties and connections
2247 void QFileDialogPrivate::createWidgets()
2250 model = new QFileSystemModel(q);
2251 options->setFilter(model->filter());
2252 model->setObjectName(QLatin1String("qt_filesystem_model"));
2253 if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
2254 model->setNameFilterDisables(helper->defaultNameFilterDisables());
2256 model->setNameFilterDisables(false);
2257 model->d_func()->disableRecursiveSort = true;
2258 QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,QString)));
2259 QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)),
2260 q, SLOT(_q_pathChanged(QString)));
2261 QFileDialog::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
2262 q, SLOT(_q_rowsInserted(QModelIndex)));
2263 model->setReadOnly(false);
2265 qFileDialogUi.reset(new Ui_QFileDialog());
2266 qFileDialogUi->setupUi(q);
2268 QList<QUrl> initialBookmarks;
2269 initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
2270 << QUrl::fromLocalFile(QDir::homePath());
2271 qFileDialogUi->sidebar->setModelAndUrls(model, initialBookmarks);
2272 QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(QUrl)),
2273 q, SLOT(_q_goToUrl(QUrl)));
2275 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
2276 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
2278 qFileDialogUi->lookInCombo->setFileDialogPrivate(this);
2279 QObject::connect(qFileDialogUi->lookInCombo, SIGNAL(activated(QString)), q, SLOT(_q_goToDirectory(QString)));
2281 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
2282 qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
2285 qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);
2286 #ifndef QT_NO_SHORTCUT
2287 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
2289 #ifndef QT_NO_FSCOMPLETER
2290 completer = new QFSCompleter(model, q);
2291 qFileDialogUi->fileNameEdit->setCompleter(completer);
2292 #endif // QT_NO_FSCOMPLETER
2293 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
2294 q, SLOT(_q_autoCompleteFileName(QString)));
2295 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
2296 q, SLOT(_q_updateOkButton()));
2298 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(returnPressed()), q, SLOT(accept()));
2301 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
2302 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
2303 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
2304 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(int)),
2305 q, SLOT(_q_useNameFilter(int)));
2306 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(QString)),
2307 q, SIGNAL(filterSelected(QString)));
2309 qFileDialogUi->listView->setFileDialogPrivate(this);
2310 qFileDialogUi->listView->setModel(model);
2311 QObject::connect(qFileDialogUi->listView, SIGNAL(activated(QModelIndex)),
2312 q, SLOT(_q_enterDirectory(QModelIndex)));
2313 QObject::connect(qFileDialogUi->listView, SIGNAL(customContextMenuRequested(QPoint)),
2314 q, SLOT(_q_showContextMenu(QPoint)));
2315 #ifndef QT_NO_SHORTCUT
2316 QShortcut *shortcut = new QShortcut(qFileDialogUi->listView);
2317 shortcut->setKey(QKeySequence(QLatin1String("Delete")));
2318 QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
2321 qFileDialogUi->treeView->setFileDialogPrivate(this);
2322 qFileDialogUi->treeView->setModel(model);
2323 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
2324 QFontMetrics fm(q->font());
2325 treeHeader->resizeSection(0, fm.width(QLatin1String("wwwwwwwwwwwwwwwwwwwwwwwwww")));
2326 treeHeader->resizeSection(1, fm.width(QLatin1String("128.88 GB")));
2327 treeHeader->resizeSection(2, fm.width(QLatin1String("mp3Folder")));
2328 treeHeader->resizeSection(3, fm.width(QLatin1String("10/29/81 02:02PM")));
2329 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
2331 QActionGroup *showActionGroup = new QActionGroup(q);
2332 showActionGroup->setExclusive(false);
2333 QObject::connect(showActionGroup, SIGNAL(triggered(QAction*)),
2334 q, SLOT(_q_showHeader(QAction*)));;
2336 QAbstractItemModel *abstractModel = model;
2337 #ifndef QT_NO_PROXYMODEL
2339 abstractModel = proxyModel;
2341 for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
2342 QAction *showHeader = new QAction(showActionGroup);
2343 showHeader->setCheckable(true);
2344 showHeader->setChecked(true);
2345 treeHeader->addAction(showHeader);
2348 QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
2349 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
2351 QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
2352 q, SLOT(_q_enterDirectory(QModelIndex)));
2353 QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
2354 q, SLOT(_q_showContextMenu(QPoint)));
2355 #ifndef QT_NO_SHORTCUT
2356 shortcut = new QShortcut(qFileDialogUi->treeView);
2357 shortcut->setKey(QKeySequence(QLatin1String("Delete")));
2358 QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
2362 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
2363 QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
2364 q, SLOT(_q_selectionChanged()));
2365 QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
2366 q, SLOT(_q_currentChanged(QModelIndex)));
2367 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
2369 createToolButtons();
2372 void QFileDialogPrivate::_q_showHeader(QAction *action)
2375 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
2376 qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked());
2379 #ifndef QT_NO_PROXYMODEL
2383 Sets the model for the views to the given \a proxyModel. This is useful if you
2384 want to modify the underlying model; for example, to add columns, filter
2387 Any existing proxy model will be removed, but not deleted. The file dialog
2388 will take ownership of the \a proxyModel.
2392 void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
2395 if ((!proxyModel && !d->proxyModel)
2396 || (proxyModel == d->proxyModel))
2399 QModelIndex idx = d->rootIndex();
2400 if (d->proxyModel) {
2401 disconnect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
2402 this, SLOT(_q_rowsInserted(QModelIndex)));
2404 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
2405 this, SLOT(_q_rowsInserted(QModelIndex)));
2408 if (proxyModel != 0) {
2409 proxyModel->setParent(this);
2410 d->proxyModel = proxyModel;
2411 proxyModel->setSourceModel(d->model);
2412 d->qFileDialogUi->listView->setModel(d->proxyModel);
2413 d->qFileDialogUi->treeView->setModel(d->proxyModel);
2414 #ifndef QT_NO_FSCOMPLETER
2415 d->completer->setModel(d->proxyModel);
2416 d->completer->proxyModel = d->proxyModel;
2418 connect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
2419 this, SLOT(_q_rowsInserted(QModelIndex)));
2422 d->qFileDialogUi->listView->setModel(d->model);
2423 d->qFileDialogUi->treeView->setModel(d->model);
2424 #ifndef QT_NO_FSCOMPLETER
2425 d->completer->setModel(d->model);
2426 d->completer->sourceModel = d->model;
2427 d->completer->proxyModel = 0;
2429 connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
2430 this, SLOT(_q_rowsInserted(QModelIndex)));
2432 QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
2433 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
2435 d->setRootIndex(idx);
2437 // reconnect selection
2438 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
2439 QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
2440 this, SLOT(_q_selectionChanged()));
2441 QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
2442 this, SLOT(_q_currentChanged(QModelIndex)));
2446 Returns the proxy model used by the file dialog. By default no proxy is set.
2450 QAbstractProxyModel *QFileDialog::proxyModel() const
2452 Q_D(const QFileDialog);
2453 return d->proxyModel;
2455 #endif // QT_NO_PROXYMODEL
2460 Create tool buttons, set properties and connections
2462 void QFileDialogPrivate::createToolButtons()
2465 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, 0, q));
2466 qFileDialogUi->backButton->setAutoRaise(true);
2467 qFileDialogUi->backButton->setEnabled(false);
2468 QObject::connect(qFileDialogUi->backButton, SIGNAL(clicked()), q, SLOT(_q_navigateBackward()));
2470 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, 0, q));
2471 qFileDialogUi->forwardButton->setAutoRaise(true);
2472 qFileDialogUi->forwardButton->setEnabled(false);
2473 QObject::connect(qFileDialogUi->forwardButton, SIGNAL(clicked()), q, SLOT(_q_navigateForward()));
2475 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, 0, q));
2476 qFileDialogUi->toParentButton->setAutoRaise(true);
2477 qFileDialogUi->toParentButton->setEnabled(false);
2478 QObject::connect(qFileDialogUi->toParentButton, SIGNAL(clicked()), q, SLOT(_q_navigateToParent()));
2480 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, 0, q));
2481 qFileDialogUi->listModeButton->setAutoRaise(true);
2482 qFileDialogUi->listModeButton->setDown(true);
2483 QObject::connect(qFileDialogUi->listModeButton, SIGNAL(clicked()), q, SLOT(_q_showListView()));
2485 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, 0, q));
2486 qFileDialogUi->detailModeButton->setAutoRaise(true);
2487 QObject::connect(qFileDialogUi->detailModeButton, SIGNAL(clicked()), q, SLOT(_q_showDetailsView()));
2489 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
2490 qFileDialogUi->backButton->setFixedSize(toolSize);
2491 qFileDialogUi->listModeButton->setFixedSize(toolSize);
2492 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
2493 qFileDialogUi->forwardButton->setFixedSize(toolSize);
2494 qFileDialogUi->toParentButton->setFixedSize(toolSize);
2496 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, 0, q));
2497 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
2498 qFileDialogUi->newFolderButton->setAutoRaise(true);
2499 qFileDialogUi->newFolderButton->setEnabled(false);
2500 QObject::connect(qFileDialogUi->newFolderButton, SIGNAL(clicked()), q, SLOT(_q_createDirectory()));
2506 Create actions which will be used in the right click.
2508 void QFileDialogPrivate::createMenuActions()
2512 QAction *goHomeAction = new QAction(q);
2513 #ifndef QT_NO_SHORTCUT
2514 goHomeAction->setShortcut(Qt::CTRL + Qt::Key_H + Qt::SHIFT);
2516 QObject::connect(goHomeAction, SIGNAL(triggered()), q, SLOT(_q_goHome()));
2517 q->addAction(goHomeAction);
2519 // ### TODO add Desktop & Computer actions
2521 QAction *goToParent = new QAction(q);
2522 goToParent->setObjectName(QLatin1String("qt_goto_parent_action"));
2523 #ifndef QT_NO_SHORTCUT
2524 goToParent->setShortcut(Qt::CTRL + Qt::UpArrow);
2526 QObject::connect(goToParent, SIGNAL(triggered()), q, SLOT(_q_navigateToParent()));
2527 q->addAction(goToParent);
2529 renameAction = new QAction(q);
2530 renameAction->setEnabled(false);
2531 renameAction->setObjectName(QLatin1String("qt_rename_action"));
2532 QObject::connect(renameAction, SIGNAL(triggered()), q, SLOT(_q_renameCurrent()));
2534 deleteAction = new QAction(q);
2535 deleteAction->setEnabled(false);
2536 deleteAction->setObjectName(QLatin1String("qt_delete_action"));
2537 QObject::connect(deleteAction, SIGNAL(triggered()), q, SLOT(_q_deleteCurrent()));
2539 showHiddenAction = new QAction(q);
2540 showHiddenAction->setObjectName(QLatin1String("qt_show_hidden_action"));
2541 showHiddenAction->setCheckable(true);
2542 QObject::connect(showHiddenAction, SIGNAL(triggered()), q, SLOT(_q_showHidden()));
2544 newFolderAction = new QAction(q);
2545 newFolderAction->setObjectName(QLatin1String("qt_new_folder_action"));
2546 QObject::connect(newFolderAction, SIGNAL(triggered()), q, SLOT(_q_createDirectory()));
2549 void QFileDialogPrivate::_q_goHome()
2552 q->setDirectory(QDir::homePath());
2558 Update history with new path, buttons, and combo
2560 void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
2563 QDir dir(model->rootDirectory());
2564 qFileDialogUi->toParentButton->setEnabled(dir.exists());
2565 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
2566 q->setHistory(qFileDialogUi->lookInCombo->history());
2568 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) {
2569 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) {
2570 currentHistory.removeLast();
2572 currentHistory.append(QDir::toNativeSeparators(newPath));
2573 ++currentHistoryLocation;
2575 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
2576 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
2582 Navigates to the last directory viewed in the dialog.
2584 void QFileDialogPrivate::_q_navigateBackward()
2587 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
2588 --currentHistoryLocation;
2589 QString previousHistory = currentHistory.at(currentHistoryLocation);
2590 q->setDirectory(previousHistory);
2597 Navigates to the last directory viewed in the dialog.
2599 void QFileDialogPrivate::_q_navigateForward()
2602 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
2603 ++currentHistoryLocation;
2604 QString nextHistory = currentHistory.at(currentHistoryLocation);
2605 q->setDirectory(nextHistory);
2612 Navigates to the parent directory of the currently displayed directory
2615 void QFileDialogPrivate::_q_navigateToParent()
2618 QDir dir(model->rootDirectory());
2619 QString newDirectory;
2621 newDirectory = model->myComputer().toString();
2624 newDirectory = dir.absolutePath();
2626 q->setDirectory(newDirectory);
2627 emit q->directoryEntered(newDirectory);
2633 Creates a new directory, first asking the user for a suitable name.
2635 void QFileDialogPrivate::_q_createDirectory()
2638 qFileDialogUi->listView->clearSelection();
2640 QString newFolderString = QFileDialog::tr("New Folder");
2641 QString folderName = newFolderString;
2642 QString prefix = q->directory().absolutePath() + QDir::separator();
2643 if (QFile::exists(prefix + folderName)) {
2644 qlonglong suffix = 2;
2645 while (QFile::exists(prefix + folderName)) {
2646 folderName = newFolderString + QString::number(suffix++);
2650 QModelIndex parent = rootIndex();
2651 QModelIndex index = model->mkdir(parent, folderName);
2652 if (!index.isValid())
2655 index = select(index);
2656 if (index.isValid()) {
2657 qFileDialogUi->treeView->setCurrentIndex(index);
2658 currentView()->edit(index);
2662 void QFileDialogPrivate::_q_showListView()
2664 qFileDialogUi->listModeButton->setDown(true);
2665 qFileDialogUi->detailModeButton->setDown(false);
2666 qFileDialogUi->treeView->hide();
2667 qFileDialogUi->listView->show();
2668 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
2669 qFileDialogUi->listView->doItemsLayout();
2672 void QFileDialogPrivate::_q_showDetailsView()
2674 qFileDialogUi->listModeButton->setDown(false);
2675 qFileDialogUi->detailModeButton->setDown(true);
2676 qFileDialogUi->listView->hide();
2677 qFileDialogUi->treeView->show();
2678 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
2679 qFileDialogUi->treeView->doItemsLayout();
2685 Show the context menu for the file/dir under position
2687 void QFileDialogPrivate::_q_showContextMenu(const QPoint &position)
2693 QAbstractItemView *view = 0;
2694 if (q->viewMode() == QFileDialog::Detail)
2695 view = qFileDialogUi->treeView;
2697 view = qFileDialogUi->listView;
2698 QModelIndex index = view->indexAt(position);
2699 index = mapToSource(index.sibling(index.row(), 0));
2702 if (index.isValid()) {
2703 // file context menu
2704 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
2705 renameAction->setEnabled(p & QFile::WriteUser);
2706 menu.addAction(renameAction);
2707 deleteAction->setEnabled(p & QFile::WriteUser);
2708 menu.addAction(deleteAction);
2709 menu.addSeparator();
2711 menu.addAction(showHiddenAction);
2712 if (qFileDialogUi->newFolderButton->isVisible()) {
2713 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
2714 menu.addAction(newFolderAction);
2716 menu.exec(view->viewport()->mapToGlobal(position));
2717 #endif // QT_NO_MENU
2723 void QFileDialogPrivate::_q_renameCurrent()
2726 QModelIndex index = qFileDialogUi->listView->currentIndex();
2727 index = index.sibling(index.row(), 0);
2728 if (q->viewMode() == QFileDialog::List)
2729 qFileDialogUi->listView->edit(index);
2731 qFileDialogUi->treeView->edit(index);
2734 bool QFileDialogPrivate::removeDirectory(const QString &path)
2736 QModelIndex modelIndex = model->index(path);
2737 return model->remove(modelIndex);
2743 Deletes the currently selected item in the dialog.
2745 void QFileDialogPrivate::_q_deleteCurrent()
2747 if (model->isReadOnly())
2750 QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
2751 for (int i = list.count() - 1; i >= 0; --i) {
2752 QModelIndex index = list.at(i);
2753 if (index == qFileDialogUi->listView->rootIndex())
2756 index = mapToSource(index.sibling(index.row(), 0));
2757 if (!index.isValid())
2760 QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
2761 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
2762 bool isDir = model->isDir(index);
2764 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
2765 #ifndef QT_NO_MESSAGEBOX
2767 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
2768 QFileDialog::tr("'%1' is write protected.\nDo you want to delete it anyway?")
2770 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
2772 else if (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
2773 QFileDialog::tr("Are you sure you want to delete '%1'?")
2775 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
2779 if (!(p & QFile::WriteUser))
2781 #endif // QT_NO_MESSAGEBOX
2783 // the event loop has run, we can NOT reuse index because the model might have removed it.
2785 if (!removeDirectory(filePath)) {
2786 #ifndef QT_NO_MESSAGEBOX
2787 QMessageBox::warning(q, q->windowTitle(),
2788 QFileDialog::tr("Could not delete directory."));
2792 model->remove(index);
2797 void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
2799 if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1Char('\\'))) {
2800 qFileDialogUi->listView->selectionModel()->clearSelection();
2804 QStringList multipleFiles = typedFiles();
2805 if (multipleFiles.count() > 0) {
2806 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
2807 QModelIndexList newFiles;
2808 for (int i = 0; i < multipleFiles.count(); ++i) {
2809 QModelIndex idx = model->index(multipleFiles.at(i));
2810 if (oldFiles.contains(idx))
2811 oldFiles.removeAll(idx);
2813 newFiles.append(idx);
2815 for (int i = 0; i < newFiles.count(); ++i)
2816 select(newFiles.at(i));
2817 if (lineEdit()->hasFocus())
2818 for (int i = 0; i < oldFiles.count(); ++i)
2819 qFileDialogUi->listView->selectionModel()->select(oldFiles.at(i),
2820 QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
2827 void QFileDialogPrivate::_q_updateOkButton()
2830 QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
2831 ? QDialogButtonBox::Open : QDialogButtonBox::Save);
2834 const QFileDialog::FileMode fileMode = q->fileMode();
2836 bool enableButton = true;
2837 bool isOpenDirectory = false;
2839 QStringList files = q->selectedFiles();
2840 QString lineEditText = lineEdit()->text();
2842 if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1Char('\\'))) {
2843 button->setEnabled(true);
2844 updateOkButtonText();
2848 if (files.isEmpty()) {
2849 enableButton = false;
2850 } else if (lineEditText == QLatin1String("..")) {
2851 isOpenDirectory = true;
2854 case QFileDialog::DirectoryOnly:
2855 case QFileDialog::Directory: {
2856 QString fn = files.first();
2857 QModelIndex idx = model->index(fn);
2859 idx = model->index(getEnvironmentVariable(fn));
2860 if (!idx.isValid() || !model->isDir(idx))
2861 enableButton = false;
2864 case QFileDialog::AnyFile: {
2865 QString fn = files.first();
2867 QModelIndex idx = model->index(fn);
2871 fileDir = info.canonicalFilePath();
2873 fileDir = fn.mid(0, fn.lastIndexOf(QLatin1Char('/')));
2874 fileName = fn.mid(fileDir.length() + 1);
2876 if (lineEditText.contains(QLatin1String(".."))) {
2877 fileDir = info.canonicalFilePath();
2878 fileName = info.fileName();
2881 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
2882 enableButton = false;
2885 if (idx.isValid() && model->isDir(idx)) {
2886 isOpenDirectory = true;
2887 enableButton = true;
2890 if (!idx.isValid()) {
2891 int maxLength = maxNameLength(fileDir);
2892 enableButton = maxLength < 0 || fileName.length() <= maxLength;
2896 case QFileDialog::ExistingFile:
2897 case QFileDialog::ExistingFiles:
2898 for (int i = 0; i < files.count(); ++i) {
2899 QModelIndex idx = model->index(files.at(i));
2901 idx = model->index(getEnvironmentVariable(files.at(i)));
2902 if (!idx.isValid()) {
2903 enableButton = false;
2906 if (idx.isValid() && model->isDir(idx)) {
2907 isOpenDirectory = true;
2917 button->setEnabled(enableButton);
2918 updateOkButtonText(isOpenDirectory);
2924 void QFileDialogPrivate::_q_currentChanged(const QModelIndex &index)
2926 _q_updateOkButton();
2927 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
2933 This is called when the user double clicks on a file with the corresponding
2934 model item \a index.
2936 void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index)
2939 // My Computer or a directory
2940 QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
2941 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
2942 if (path.isEmpty() || model->isDir(sourceIndex)) {
2943 const QFileDialog::FileMode fileMode = q->fileMode();
2944 q->setDirectory(path);
2945 emit q->directoryEntered(path);
2946 if (fileMode == QFileDialog::Directory
2947 || fileMode == QFileDialog::DirectoryOnly) {
2948 // ### find out why you have to do both of these.
2949 lineEdit()->setText(QString());
2950 lineEdit()->clear();
2960 Changes the file dialog's current directory to the one specified
2963 void QFileDialogPrivate::_q_goToDirectory(const QString &path)
2965 #ifndef QT_NO_MESSAGEBOX
2968 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
2969 qFileDialogUi->lookInCombo->modelColumn(),
2970 qFileDialogUi->lookInCombo->rootModelIndex());
2971 QString path2 = path;
2972 if (!index.isValid())
2973 index = mapFromSource(model->index(getEnvironmentVariable(path)));
2975 path2 = index.data(UrlRole).toUrl().toLocalFile();
2976 index = mapFromSource(model->index(path2));
2980 dir = getEnvironmentVariable(path2);
2982 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
2983 _q_enterDirectory(index);
2984 #ifndef QT_NO_MESSAGEBOX
2986 QString message = QFileDialog::tr("%1\nDirectory not found.\nPlease verify the "
2987 "correct directory name was given.");
2988 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
2989 #endif // QT_NO_MESSAGEBOX
2996 Sets the current name filter to be nameFilter and
2997 update the qFileDialogUi->fileNameEdit when in AcceptSave mode with the new extension.
2999 void QFileDialogPrivate::_q_useNameFilter(int index)
3001 QStringList nameFilters = options->nameFilters();
3002 if (index == nameFilters.size()) {
3003 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
3004 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
3005 options->setNameFilters(nameFilters);
3008 QString nameFilter = nameFilters.at(index);
3009 QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
3010 if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
3011 QString newNameFilterExtension;
3012 if (newNameFilters.count() > 0)
3013 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
3015 QString fileName = lineEdit()->text();
3016 const QString fileNameExtension = QFileInfo(fileName).suffix();
3017 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
3018 const int fileNameExtensionLength = fileNameExtension.count();
3019 fileName.replace(fileName.count() - fileNameExtensionLength,
3020 fileNameExtensionLength, newNameFilterExtension);
3021 qFileDialogUi->listView->clearSelection();
3022 lineEdit()->setText(fileName);
3026 model->setNameFilters(newNameFilters);
3032 This is called when the model index corresponding to the current file is changed
3033 from \a index to \a current.
3035 void QFileDialogPrivate::_q_selectionChanged()
3037 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3038 QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
3039 bool stripDirs = (fileMode != QFileDialog::DirectoryOnly && fileMode != QFileDialog::Directory);
3041 QStringList allFiles;
3042 for (int i = 0; i < indexes.count(); ++i) {
3043 if (stripDirs && model->isDir(mapToSource(indexes.at(i))))
3045 allFiles.append(indexes.at(i).data().toString());
3047 if (allFiles.count() > 1)
3048 for (int i = 0; i < allFiles.count(); ++i) {
3049 allFiles.replace(i, QString(QLatin1Char('"') + allFiles.at(i) + QLatin1Char('"')));
3052 QString finalFiles = allFiles.join(QLatin1Char(' '));
3053 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
3054 lineEdit()->setText(finalFiles);
3056 _q_updateOkButton();
3062 Includes hidden files and directories in the items displayed in the dialog.
3064 void QFileDialogPrivate::_q_showHidden()
3067 QDir::Filters dirFilters = q->filter();
3068 if (showHiddenAction->isChecked())
3069 dirFilters |= QDir::Hidden;
3071 dirFilters &= ~QDir::Hidden;
3072 q->setFilter(dirFilters);
3078 When parent is root and rows have been inserted when none was there before
3079 then select the first one.
3081 void QFileDialogPrivate::_q_rowsInserted(const QModelIndex &parent)
3083 if (!qFileDialogUi->treeView
3084 || parent != qFileDialogUi->treeView->rootIndex()
3085 || !qFileDialogUi->treeView->selectionModel()
3086 || qFileDialogUi->treeView->selectionModel()->hasSelection()
3087 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
3091 void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldName, const QString newName)
3093 const QFileDialog::FileMode fileMode = q_func()->fileMode();
3094 if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
3095 if (path == rootPath() && lineEdit()->text() == oldName)
3096 lineEdit()->setText(newName);
3103 For the list and tree view watch keys to goto parent and back in the history
3105 returns true if handled
3107 bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
3110 switch (event->key()) {
3111 case Qt::Key_Backspace:
3112 _q_navigateToParent();
3115 #ifdef QT_KEYPAD_NAVIGATION
3116 if (QApplication::keypadNavigationEnabled())
3120 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
3121 _q_navigateBackward();
3125 case Qt::Key_Escape:
3134 QString QFileDialogPrivate::getEnvironmentVariable(const QString &string)
3137 if (string.size() > 1 && string.startsWith(QLatin1Char('$'))) {
3138 return QString::fromLocal8Bit(getenv(string.mid(1).toLatin1().constData()));
3141 if (string.size() > 2 && string.startsWith(QLatin1Char('%')) && string.endsWith(QLatin1Char('%'))) {
3142 return QString::fromLocal8Bit(qgetenv(string.mid(1, string.size() - 2).toLatin1().constData()));
3148 void QFileDialogComboBox::setFileDialogPrivate(QFileDialogPrivate *d_pointer) {
3150 urlModel = new QUrlModel(this);
3151 urlModel->showFullPath = true;
3152 urlModel->setFileSystemModel(d_ptr->model);
3156 void QFileDialogComboBox::showPopup()
3158 if (model()->rowCount() > 1)
3159 QComboBox::showPopup();
3161 urlModel->setUrls(QList<QUrl>());
3163 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
3164 while (idx.isValid()) {
3165 QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
3170 // add "my computer"
3171 list.append(QUrl::fromLocalFile(QLatin1String("")));
3172 urlModel->addUrls(list, 0);
3173 idx = model()->index(model()->rowCount() - 1, 0);
3177 for (int i = 0; i < m_history.count(); ++i) {
3178 QUrl path = QUrl::fromLocalFile(m_history.at(i));
3179 if (!urls.contains(path))
3182 if (urls.count() > 0) {
3183 model()->insertRow(model()->rowCount());
3184 idx = model()->index(model()->rowCount()-1, 0);
3185 // ### TODO maybe add a horizontal line before this
3186 model()->setData(idx, QFileDialog::tr("Recent Places"));
3187 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
3189 Qt::ItemFlags flags = m->flags(idx);
3190 flags &= ~Qt::ItemIsEnabled;
3191 m->item(idx.row(), idx.column())->setFlags(flags);
3193 urlModel->addUrls(urls, -1, false);
3197 QComboBox::showPopup();
3200 // Exact same as QComboBox::paintEvent(), except we elide the text.
3201 void QFileDialogComboBox::paintEvent(QPaintEvent *)
3203 QStylePainter painter(this);
3204 painter.setPen(palette().color(QPalette::Text));
3206 // draw the combobox frame, focusrect and selected etc.
3207 QStyleOptionComboBox opt;
3208 initStyleOption(&opt);
3210 QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
3211 QStyle::SC_ComboBoxEditField, this);
3212 int size = editRect.width() - opt.iconSize.width() - 4;
3213 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
3214 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
3216 // draw the icon and text
3217 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
3220 QFileDialogListView::QFileDialogListView(QWidget *parent) : QListView(parent)
3224 void QFileDialogListView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)
3227 setSelectionBehavior(QAbstractItemView::SelectRows);
3229 setResizeMode(QListView::Adjust);
3230 setEditTriggers(QAbstractItemView::EditKeyPressed);
3231 setContextMenuPolicy(Qt::CustomContextMenu);
3232 #ifndef QT_NO_DRAGANDDROP
3233 setDragDropMode(QAbstractItemView::InternalMove);
3237 QSize QFileDialogListView::sizeHint() const
3239 int height = qMax(10, sizeHintForRow(0));
3240 return QSize(QListView::sizeHint().width() * 2, height * 30);
3243 void QFileDialogListView::keyPressEvent(QKeyEvent *e)
3245 #ifdef QT_KEYPAD_NAVIGATION
3246 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
3247 QListView::keyPressEvent(e);
3250 #endif // QT_KEYPAD_NAVIGATION
3252 if (!d_ptr->itemViewKeyboardEvent(e))
3253 QListView::keyPressEvent(e);
3257 QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent)
3261 void QFileDialogTreeView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)
3264 setSelectionBehavior(QAbstractItemView::SelectRows);
3265 setRootIsDecorated(false);
3266 setItemsExpandable(false);
3267 setSortingEnabled(true);
3268 header()->setSortIndicator(0, Qt::AscendingOrder);
3269 header()->setStretchLastSection(false);
3270 setTextElideMode(Qt::ElideMiddle);
3271 setEditTriggers(QAbstractItemView::EditKeyPressed);
3272 setContextMenuPolicy(Qt::CustomContextMenu);
3273 #ifndef QT_NO_DRAGANDDROP
3274 setDragDropMode(QAbstractItemView::InternalMove);
3278 void QFileDialogTreeView::keyPressEvent(QKeyEvent *e)
3280 #ifdef QT_KEYPAD_NAVIGATION
3281 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
3282 QTreeView::keyPressEvent(e);
3285 #endif // QT_KEYPAD_NAVIGATION
3287 if (!d_ptr->itemViewKeyboardEvent(e))
3288 QTreeView::keyPressEvent(e);
3292 QSize QFileDialogTreeView::sizeHint() const
3294 int height = qMax(10, sizeHintForRow(0));
3295 QSize sizeHint = header()->sizeHint();
3296 return QSize(sizeHint.width() * 4, height * 30);
3300 // FIXME: this is a hack to avoid propagating key press events
3301 // to the dialog and from there to the "Ok" button
3303 void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
3305 #ifdef QT_KEYPAD_NAVIGATION
3306 if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
3307 QLineEdit::keyPressEvent(e);
3310 #endif // QT_KEYPAD_NAVIGATION
3313 QLineEdit::keyPressEvent(e);
3314 if (key != Qt::Key_Escape)
3316 if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) {
3319 d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason);
3323 #ifndef QT_NO_FSCOMPLETER
3325 QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
3327 const QFileSystemModel *dirModel;
3329 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
3331 dirModel = sourceModel;
3332 QString currentLocation = dirModel->rootPath();
3333 QString path = index.data(QFileSystemModel::FilePathRole).toString();
3334 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
3335 #if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
3336 if (currentLocation == QDir::separator())
3337 return path.mid(currentLocation.length());
3339 if (currentLocation.endsWith(QLatin1Char('/')))
3340 return path.mid(currentLocation.length());
3342 return path.mid(currentLocation.length()+1);
3344 return index.data(QFileSystemModel::FilePathRole).toString();
3347 QStringList QFSCompleter::splitPath(const QString &path) const
3350 return QStringList(completionPrefix());
3352 QString pathCopy = QDir::toNativeSeparators(path);
3353 QString sep = QDir::separator();
3354 #if defined(Q_OS_WIN)
3355 if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
3356 return QStringList(pathCopy);
3357 QString doubleSlash(QLatin1String("\\\\"));
3358 if (pathCopy.startsWith(doubleSlash))
3359 pathCopy = pathCopy.mid(2);
3361 doubleSlash.clear();
3362 #elif defined(Q_OS_UNIX)
3364 pathCopy = qt_tildeExpansion(pathCopy, &expanded);
3366 QFileSystemModel *dirModel;
3368 dirModel = qobject_cast<QFileSystemModel *>(proxyModel->sourceModel());
3370 dirModel = sourceModel;
3371 dirModel->fetchMore(dirModel->index(pathCopy));
3375 QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
3377 #if defined(Q_OS_WIN)
3378 QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
3379 if (!doubleSlash.isEmpty() && !parts.isEmpty())
3380 parts[0].prepend(doubleSlash);
3381 if (pathCopy.endsWith(sep))
3382 parts.append(QString());
3384 QStringList parts = pathCopy.split(re);
3385 if (pathCopy[0] == sep[0]) // read the "/" at the beginning as the split removed it
3389 #if defined(Q_OS_WIN)
3390 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
3392 bool startsFromRoot = pathCopy[0] == sep[0];
3394 if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) {
3395 const QFileSystemModel *dirModel;
3397 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
3399 dirModel = sourceModel;
3400 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
3401 #if defined(Q_OS_WIN)
3402 if (currentLocation.endsWith(QLatin1Char(':')))
3403 currentLocation.append(sep);
3405 if (currentLocation.contains(sep) && path != currentLocation) {
3406 QStringList currentLocationList = splitPath(currentLocation);
3407 while (!currentLocationList.isEmpty()
3408 && parts.count() > 0
3409 && parts.at(0) == QLatin1String("..")) {
3410 parts.removeFirst();
3411 currentLocationList.removeLast();
3413 if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty())
3414 currentLocationList.removeLast();
3415 return currentLocationList + parts;
3421 #endif // QT_NO_COMPLETER
3426 #include "moc_qfiledialog.cpp"
3428 #endif // QT_NO_FILEDIALOG