source: trunk/src/gui/dialogs/qfiledialog.cpp@ 187

Last change on this file since 187 was 172, checked in by Dmitry A. Kuminov, 16 years ago

corelib/io, gui/dialogs: Handle DOS-like filesystem details (drives, slashes) on OS/2 similarly to Win32.

File size: 106.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qvariant.h>
43#include <private/qwidgetitemdata_p.h>
44#include "qfiledialog.h"
45
46#ifndef QT_NO_FILEDIALOG
47#include "qfiledialog_p.h"
48#include <qfontmetrics.h>
49#include <qaction.h>
50#include <qheaderview.h>
51#include <qshortcut.h>
52#include <qgridlayout.h>
53#include <qmenu.h>
54#include <qmessagebox.h>
55#include <qinputdialog.h>
56#include <stdlib.h>
57#include <qsettings.h>
58#include <qdebug.h>
59#include <qapplication.h>
60#include <qstylepainter.h>
61#ifndef Q_OS_WINCE
62#include "ui_qfiledialog.h"
63#else
64#include "ui_qfiledialog_wince.h"
65extern bool qt_priv_ptr_valid;
66#endif
67
68QT_BEGIN_NAMESPACE
69
70Q_GLOBAL_STATIC(QString, lastVisitedDir)
71
72/*
73 \internal
74
75 Exported hooks that can be used to customize the static functions.
76 */
77typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
78Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0;
79
80typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
81Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0;
82
83typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
84Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0;
85
86typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
87Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook = 0;
88
89/*!
90 \class QFileDialog
91 \brief The QFileDialog class provides a dialog that allow users to select files or directories.
92 \ingroup dialogs
93 \mainclass
94
95 The QFileDialog class enables a user to traverse the file system in
96 order to select one or many files or a directory.
97
98 The easiest way to create a QFileDialog is to use the static
99 functions. On Windows, these static functions will call the native
100 Windows file dialog, and on Mac OS X these static function will call
101 the native Mac OS X file dialog.
102
103 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 0
104
105 In the above example, a modal QFileDialog is created using a static
106 function. The dialog initially displays the contents of the "/home/jana"
107 directory, and displays files matching the patterns given in the
108 string "Image Files (*.png *.jpg *.bmp)". The parent of the file dialog
109 is set to \e this, and the window title is set to "Open Image".
110
111 If you want to use multiple filters, separate each one with
112 \e two semicolons. For example:
113
114 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 1
115
116 You can create your own QFileDialog without using the static
117 functions. By calling setFileMode(), you can specify what the user must
118 select in the dialog:
119
120 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 2
121
122 In the above example, the mode of the file dialog is set to
123 AnyFile, meaning that the user can select any file, or even specify a
124 file that doesn't exist. This mode is useful for creating a
125 "Save As" file dialog. Use ExistingFile if the user must select an
126 existing file, or \l Directory if only a directory may be selected.
127 See the \l QFileDialog::FileMode enum for the complete list of modes.
128
129 The fileMode property contains the mode of operation for the dialog;
130 this indicates what types of objects the user is expected to select.
131 Use setNameFilter() to set the dialog's file filter. For example:
132
133 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 3
134
135 In the above example, the filter is set to \c{"Images (*.png *.xpm *.jpg)"},
136 this means that only files with the extension \c png, \c xpm,
137 or \c jpg will be shown in the QFileDialog. You can apply
138 several filters by using setNameFilters(). Use selectNameFilter() to select
139 one of the filters you've given as the file dialog's default filter.
140
141 The file dialog has two view modes: \l{QFileDialog::}{List} and
142 \l{QFileDialog::}{Detail}.
143 \l{QFileDialog::}{List} presents the contents of the current directory
144 as a list of file and directory names. \l{QFileDialog::}{Detail} also
145 displays a list of file and directory names, but provides additional
146 information alongside each name, such as the file size and modification
147 date. Set the mode with setViewMode():
148
149 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 4
150
151 The last important function you will need to use when creating your
152 own file dialog is selectedFiles().
153
154 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 5
155
156 In the above example, a modal file dialog is created and shown. If
157 the user clicked OK, the file they selected is put in \c fileName.
158
159 The dialog's working directory can be set with setDirectory().
160 Each file in the current directory can be selected using
161 the selectFile() function.
162
163 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
164 how to use QFileDialog as well as other built-in Qt dialogs.
165
166 \sa QDir, QFileInfo, QFile, QPrintDialog, QColorDialog, QFontDialog, {Standard Dialogs Example},
167 {Application Example}
168*/
169
170/*!
171 \enum QFileDialog::AcceptMode
172
173 \value AcceptOpen
174 \value AcceptSave
175*/
176
177/*!
178 \enum QFileDialog::ViewMode
179
180 This enum describes the view mode of the file dialog; i.e. what
181 information about each file will be displayed.
182
183 \value Detail Displays an icon, a name, and details for each item in
184 the directory.
185 \value List Displays only an icon and a name for each item in the
186 directory.
187
188 \sa setViewMode()
189*/
190
191/*!
192 \enum QFileDialog::FileMode
193
194 This enum is used to indicate what the user may select in the file
195 dialog; i.e. what the dialog will return if the user clicks OK.
196
197 \value AnyFile The name of a file, whether it exists or not.
198 \value ExistingFile The name of a single existing file.
199 \value Directory The name of a directory. Both files and
200 directories are displayed.
201 \value ExistingFiles The names of zero or more existing files.
202
203 This value is obsolete since Qt 4.5:
204
205 \value DirectoryOnly Use \c Directory and setOption(ShowDirsOnly, true) instead.
206
207 \sa setFileMode()
208*/
209
210/*!
211 \enum QFileDialog::Option
212
213 \value ShowDirsOnly Only show directories in the file dialog. By default both files and
214 directories are shown. (Valid only in the \l Directory file mode.)
215 \value DontResolveSymlinks Don't resolve symlinks in the file dialog. By default symlinks
216 are resolved.
217 \value DontConfirmOverwrite Don't ask for confirmation if an existing file is selected.
218 By default confirmation is requested.
219 \value DontUseNativeDialog Don't use the native file dialog. By default on Mac OS X and Windows,
220 the native file dialog is used unless you use a subclass of QFileDialog that contains the
221 Q_OBJECT macro.
222 \value ReadOnly Indicates that the model is readonly.
223 \value HideNameFilterDetails Indicates if the is hidden or not.
224
225 This value is obsolete and does nothing since Qt 4.5:
226
227 \value DontUseSheet In previous versions of Qt, the static functions would
228 create a sheet by default if the static function was given a parent. This
229 is no longer supported in Qt 4.5, The static functions will always be an
230 application modal dialog. If you want to use sheets, use
231 QFileDialog::open() instead.
232
233*/
234
235/*!
236 \enum QFileDialog::DialogLabel
237
238 \value LookIn
239 \value FileName
240 \value FileType
241 \value Accept
242 \value Reject
243*/
244
245/*!
246 \fn void QFileDialog::filesSelected(const QStringList &selected)
247
248 When the selection changes and the dialog is accepted, this signal is
249 emitted with the (possibly empty) list of \a selected files.
250
251 \sa currentChanged(), QDialog::Accepted
252*/
253
254
255/*!
256 \fn void QFileDialog::fileSelected(const QString &file)
257
258 When the selection changes and the dialog is accepted, this signal is
259 emitted with the (possibly empty) selected \a file.
260
261 \sa currentChanged(), QDialog::Accepted
262*/
263
264
265/*!
266 \fn void QFileDialog::currentChanged(const QString &path)
267
268 When the current file changes, this signal is emitted with the
269 new file name as the \a path parameter.
270
271 \sa filesSelected()
272*/
273
274/*!
275 \fn void QFileDialog::directoryEntered(const QString &directory)
276 \since 4.3
277
278 This signal is emitted when the user enters a \a directory.
279*/
280
281/*!
282 \fn void QFileDialog::filterSelected(const QString &filter)
283 \since 4.3
284
285 This signal is emitted when the user selects a \a filter.
286*/
287
288#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
289bool Q_GUI_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API
290#endif
291
292QT_BEGIN_INCLUDE_NAMESPACE
293#ifdef Q_WS_WIN
294#include <qwindowsstyle.h>
295#endif
296#include <qshortcut.h>
297#ifdef Q_WS_MAC
298#include <private/qunicodetables_p.h>
299#include <qmacstyle_mac.h>
300#endif
301QT_END_INCLUDE_NAMESPACE
302
303/*!
304 \fn QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags flags)
305
306 Constructs a file dialog with the given \a parent and widget \a flags.
307*/
308QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
309 : QDialog(*new QFileDialogPrivate, parent, f)
310{
311 Q_D(QFileDialog);
312 d->init();
313}
314
315/*!
316 Constructs a file dialog with the given \a parent and \a caption that
317 initially displays the contents of the specified \a directory.
318 The contents of the directory are filtered before being shown in the
319 dialog, using a semicolon-separated list of filters specified by
320 \a filter.
321*/
322QFileDialog::QFileDialog(QWidget *parent,
323 const QString &caption,
324 const QString &directory,
325 const QString &filter)
326 : QDialog(*new QFileDialogPrivate, parent, 0)
327{
328 Q_D(QFileDialog);
329 d->init(directory, filter, caption);
330}
331
332/*!
333 \internal
334*/
335QFileDialog::QFileDialog(const QFileDialogArgs &args)
336 : QDialog(*new QFileDialogPrivate, args.parent, 0)
337{
338 Q_D(QFileDialog);
339 d->init(args.directory, args.filter, args.caption);
340 setFileMode(args.mode);
341 setOptions(args.options);
342 selectFile(args.selection);
343 d->lineEdit()->selectAll();
344}
345
346/*!
347 Destroys the file dialog.
348*/
349QFileDialog::~QFileDialog()
350{
351 Q_D(QFileDialog);
352#ifndef QT_NO_SETTINGS
353 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
354 settings.beginGroup(QLatin1String("Qt"));
355 settings.setValue(QLatin1String("filedialog"), saveState());
356#endif
357 delete d->qFileDialogUi;
358 d->deleteNativeDialog_sys();
359}
360
361/*!
362 \since 4.3
363 Sets the \a urls that are located in the sidebar.
364
365 For instance:
366
367 \snippet doc/src/snippets/filedialogurls.cpp 0
368
369 The file dialog will then look like this:
370
371 \image filedialogurls.png
372
373 \sa sidebarUrls()
374*/
375void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
376{
377 Q_D(QFileDialog);
378 d->qFileDialogUi->sidebar->setUrls(urls);
379}
380
381/*!
382 \since 4.3
383 Returns a list of urls that are currently in the sidebar
384*/
385QList<QUrl> QFileDialog::sidebarUrls() const
386{
387 Q_D(const QFileDialog);
388 return d->qFileDialogUi->sidebar->urls();
389}
390
391static const qint32 QFileDialogMagic = 0xbe;
392
393/*!
394 \since 4.3
395 Saves the state of the dialog's layout, history and current directory.
396
397 Typically this is used in conjunction with QSettings to remember the size
398 for a future session. A version number is stored as part of the data.
399*/
400QByteArray QFileDialog::saveState() const
401{
402 Q_D(const QFileDialog);
403 int version = 3;
404 QByteArray data;
405 QDataStream stream(&data, QIODevice::WriteOnly);
406
407 stream << qint32(QFileDialogMagic);
408 stream << qint32(version);
409 stream << d->qFileDialogUi->splitter->saveState();
410 stream << d->qFileDialogUi->sidebar->urls();
411 stream << history();
412 stream << *lastVisitedDir();
413 stream << d->qFileDialogUi->treeView->header()->saveState();
414 stream << qint32(viewMode());
415 return data;
416}
417
418/*!
419 \since 4.3
420 Restores the dialogs's layout, history and current directory to the \a state specified.
421
422 Typically this is used in conjunction with QSettings to restore the size
423 from a past session.
424
425 Returns false if there are errors
426*/
427bool QFileDialog::restoreState(const QByteArray &state)
428{
429 Q_D(QFileDialog);
430 int version = 3;
431 QByteArray sd = state;
432 QDataStream stream(&sd, QIODevice::ReadOnly);
433 if (stream.atEnd())
434 return false;
435 QByteArray splitterState;
436 QByteArray headerData;
437 QList<QUrl> bookmarks;
438 QStringList history;
439 QString currentDirectory;
440 qint32 marker;
441 qint32 v;
442 qint32 viewMode;
443 stream >> marker;
444 stream >> v;
445 if (marker != QFileDialogMagic || v != version)
446 return false;
447
448 stream >> splitterState
449 >> bookmarks
450 >> history
451 >> currentDirectory
452 >> headerData
453 >> viewMode;
454
455 if (!d->qFileDialogUi->splitter->restoreState(splitterState))
456 return false;
457 QList<int> list = d->qFileDialogUi->splitter->sizes();
458 if (list.count() >= 2 && list.at(0) == 0 && list.at(1) == 0) {
459 for (int i = 0; i < list.count(); ++i)
460 list[i] = d->qFileDialogUi->splitter->widget(i)->sizeHint().width();
461 d->qFileDialogUi->splitter->setSizes(list);
462 }
463
464 d->qFileDialogUi->sidebar->setUrls(bookmarks);
465 while (history.count() > 5)
466 history.pop_front();
467 setHistory(history);
468 setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
469 if (!d->qFileDialogUi->treeView->header()->restoreState(headerData))
470 return false;
471
472 setViewMode(ViewMode(viewMode));
473 return true;
474}
475
476/*!
477 \reimp
478*/
479void QFileDialog::changeEvent(QEvent *e)
480{
481 Q_D(QFileDialog);
482 if (e->type() == QEvent::LanguageChange) {
483 d->retranslateWindowTitle();
484 d->retranslateStrings();
485 }
486 QDialog::changeEvent(e);
487}
488
489void QFileDialogPrivate::retranslateWindowTitle()
490{
491 Q_Q(QFileDialog);
492 if (!useDefaultCaption || setWindowTitle != q->windowTitle())
493 return;
494 if (acceptMode == QFileDialog::AcceptOpen) {
495 if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory)
496 q->setWindowTitle(QFileDialog::tr("Find Directory"));
497 else
498 q->setWindowTitle(QFileDialog::tr("Open"));
499 } else
500 q->setWindowTitle(QFileDialog::tr("Save As"));
501
502 setWindowTitle = q->windowTitle();
503}
504
505void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
506{
507 *lastVisitedDir() = dir;
508}
509
510void QFileDialogPrivate::retranslateStrings()
511{
512 Q_Q(QFileDialog);
513 /* WIDGETS */
514 if (defaultFileTypes)
515 q->setNameFilter(QFileDialog::tr("All Files (*)"));
516
517 QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
518 QAbstractItemModel *abstractModel = model;
519#ifndef QT_NO_PROXYMODEL
520 if (proxyModel)
521 abstractModel = proxyModel;
522#endif
523 int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
524 for (int i = 1; i < total; ++i) {
525 actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
526 }
527
528 /* MENU ACTIONS */
529 renameAction->setText(QFileDialog::tr("&Rename"));
530 deleteAction->setText(QFileDialog::tr("&Delete"));
531 showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
532 newFolderAction->setText(QFileDialog::tr("&New Folder"));
533 qFileDialogUi->retranslateUi(q);
534
535 if (!fileNameLabelExplicitlySat){
536 if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory) {
537 q->setLabelText(QFileDialog::FileName, QFileDialog::tr("Directory:"));
538 } else {
539 q->setLabelText(QFileDialog::FileName, QFileDialog::tr("File &name:"));
540 }
541 fileNameLabelExplicitlySat = false;
542 }
543}
544
545void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
546{
547 Q_Q(QFileDialog);
548 emit q->filesSelected(files);
549 if (files.count() == 1)
550 emit q->fileSelected(files.first());
551}
552
553bool QFileDialogPrivate::canBeNativeDialog()
554{
555 Q_Q(QFileDialog);
556 if (nativeDialogInUse)
557 return true;
558 if (q->testAttribute(Qt::WA_DontShowOnScreen))
559 return false;
560 if (opts & QFileDialog::DontUseNativeDialog)
561 return false;
562
563 QLatin1String staticName(QFileDialog::staticMetaObject.className());
564 QLatin1String dynamicName(q->metaObject()->className());
565 return (staticName == dynamicName);
566}
567
568/*!
569 Sets the given \a option to be enabled if \a on is true;
570 otherwise, clears the given \a option.
571
572 \sa options, testOption()
573*/
574void QFileDialog::setOption(Option option, bool on)
575{
576 Q_D(QFileDialog);
577 if (!(d->opts & option) != !on)
578 setOptions(d->opts ^ option);
579}
580
581/*!
582 \since 4.5
583
584 Returns true if the given \a option is enabled; otherwise, returns
585 false.
586
587 \sa options, setOption()
588*/
589bool QFileDialog::testOption(Option option) const
590{
591 Q_D(const QFileDialog);
592 return (d->opts & option) != 0;
593}
594
595/*!
596 \property QFileDialog::options
597 \brief the various options that affect the look and feel of the dialog
598 \since 4.5
599
600 By default, all options are disabled.
601
602 Options should be set before showing the dialog. Setting them while the
603 dialog is visible is not guaranteed to have an immediate effect on the
604 dialog (depending on the option and on the platform).
605
606 \sa setOption(), testOption()
607*/
608void QFileDialog::setOptions(Options options)
609{
610 Q_D(QFileDialog);
611
612 Options changed = (options ^ d->opts);
613 if (!changed)
614 return;
615
616 d->opts = options;
617 if (changed & DontResolveSymlinks)
618 d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
619 if (changed & ReadOnly) {
620 bool ro = (options & ReadOnly);
621 d->model->setReadOnly(ro);
622 d->qFileDialogUi->newFolderButton->setEnabled(!ro);
623 d->renameAction->setEnabled(!ro);
624 d->deleteAction->setEnabled(!ro);
625 }
626 if (changed & HideNameFilterDetails)
627 setNameFilters(d->nameFilters);
628}
629
630QFileDialog::Options QFileDialog::options() const
631{
632 Q_D(const QFileDialog);
633 return d->opts;
634}
635
636/*!
637 \overload
638
639 \since 4.5
640
641 Opens the dialog and connects its accepted() signal to the slot specified
642 by \a receiver and \a member.
643
644 The signal will be disconnected from the slot when the dialog is closed.
645*/
646void QFileDialog::open(QObject *receiver, const char *member)
647{
648 Q_D(QFileDialog);
649 const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(const QStringList&))
650 : SIGNAL(fileSelected(const QString&));
651 connect(this, signal, receiver, member);
652 d->signalToDisconnectOnClose = signal;
653 d->receiverToDisconnectOnClose = receiver;
654 d->memberToDisconnectOnClose = member;
655
656 QDialog::open();
657}
658
659
660/*!
661 \reimp
662*/
663void QFileDialog::setVisible(bool visible)
664{
665 Q_D(QFileDialog);
666 if (visible){
667 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
668 return;
669 } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
670 return;
671
672 if (d->canBeNativeDialog()){
673 if (d->setVisible_sys(visible)){
674 d->nativeDialogInUse = true;
675 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
676 // updates the state correctly, but skips showing the non-native version:
677 setAttribute(Qt::WA_DontShowOnScreen);
678 } else {
679 d->nativeDialogInUse = false;
680 setAttribute(Qt::WA_DontShowOnScreen, false);
681 }
682 }
683
684 if (!d->nativeDialogInUse)
685 d->qFileDialogUi->fileNameEdit->setFocus();
686
687 QDialog::setVisible(visible);
688}
689
690/*!
691 \internal
692 set the directory to url
693*/
694void QFileDialogPrivate::_q_goToUrl(const QUrl &url)
695{
696 QModelIndex idx = model->index(url.toLocalFile());
697 _q_enterDirectory(idx);
698}
699
700/*!
701 \fn void QFileDialog::setDirectory(const QDir &directory)
702
703 \overload
704*/
705
706/*!
707 Sets the file dialog's current \a directory.
708*/
709void QFileDialog::setDirectory(const QString &directory)
710{
711 Q_D(QFileDialog);
712 QString newDirectory = directory;
713 QFileInfo info(directory);
714 //we remove .. and . from the given path if exist
715 if (!directory.isEmpty())
716 newDirectory = QDir::cleanPath(directory);
717
718 if (!directory.isEmpty() && newDirectory.isEmpty())
719 return;
720
721 d->setLastVisitedDirectory(newDirectory);
722
723 if (d->nativeDialogInUse){
724 d->setDirectory_sys(newDirectory);
725 return;
726 }
727 if (d->rootPath() == newDirectory)
728 return;
729 QModelIndex root = d->model->setRootPath(newDirectory);
730 d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
731 if (root != d->rootIndex()) {
732#ifndef QT_NO_COMPLETER
733 if (directory.endsWith(QLatin1Char('/')))
734 d->completer->setCompletionPrefix(newDirectory);
735 else
736 d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/'));
737#endif
738 d->setRootIndex(root);
739 }
740 d->qFileDialogUi->listView->selectionModel()->clear();
741}
742
743/*!
744 Returns the directory currently being displayed in the dialog.
745*/
746QDir QFileDialog::directory() const
747{
748 Q_D(const QFileDialog);
749 return QDir(d->nativeDialogInUse ? d->directory_sys() : d->rootPath());
750}
751
752/*!
753 Selects the given \a filename in the file dialog.
754
755 \sa selectedFiles()
756*/
757void QFileDialog::selectFile(const QString &filename)
758{
759 Q_D(QFileDialog);
760 if (filename.isEmpty())
761 return;
762
763 if (d->nativeDialogInUse){
764 d->selectFile_sys(filename);
765 return;
766 }
767
768 if (!QDir::isRelativePath(filename)) {
769 QFileInfo info(filename);
770 QString filenamePath = info.absoluteDir().path();
771
772 if (d->model->rootPath() != filenamePath)
773 setDirectory(filenamePath);
774 }
775
776 QModelIndex index = d->model->index(filename);
777 if (!index.isValid()) {
778 // save as dialog where we want to input a default value
779 QString text = filename;
780 if (QFileInfo(filename).isAbsolute()) {
781 QString current = d->rootPath();
782 text.remove(current);
783 if (text.at(0) == QDir::separator()
784#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
785 //On Windows and OS/2 both cases can happen
786 || text.at(0) == QLatin1Char('/')
787#endif
788 )
789 text = text.remove(0,1);
790 }
791 if (!isVisible() || !d->lineEdit()->hasFocus())
792 d->lineEdit()->setText(text);
793 } else {
794 d->qFileDialogUi->listView->selectionModel()->clear();
795 if (!isVisible() || !d->lineEdit()->hasFocus())
796 d->lineEdit()->setText(index.data().toString());
797 }
798}
799
800/**
801 Returns the text in the line edit which can be one or more file names
802 */
803QStringList QFileDialogPrivate::typedFiles() const
804{
805 QStringList files;
806 QString editText = lineEdit()->text();
807 if (!editText.contains(QLatin1Char('"')))
808 files << editText;
809 else {
810 // " is used to separate files like so: "file1" "file2" "file3" ...
811 // ### need escape character for filenames with quotes (")
812 QStringList tokens = editText.split(QLatin1Char('\"'));
813 for (int i=0; i<tokens.size(); ++i) {
814 if ((i % 2) == 0)
815 continue; // Every even token is a separator
816 files << toInternal(tokens.at(i));
817 }
818 }
819 return addDefaultSuffixToFiles(files);
820}
821
822QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesToFix) const
823{
824 QStringList files;
825 for (int i=0; i<filesToFix.size(); ++i) {
826 QString name = toInternal(filesToFix.at(i));
827 QFileInfo info(name);
828 // if the filename has no suffix, add the default suffix
829 if (!defaultSuffix.isEmpty() && !info.isDir() && name.lastIndexOf(QLatin1Char('.')) == -1)
830 name += QLatin1Char('.') + defaultSuffix;
831 if (info.isAbsolute()) {
832 files.append(name);
833 } else {
834 // at this point the path should only have Qt path separators.
835 // This check is needed since we might be at the root directory
836 // and on Windows it already ends with slash.
837 QString path = rootPath();
838 if (!path.endsWith(QLatin1String("/")))
839 path += QLatin1String("/");
840 path += name;
841 files.append(path);
842 }
843 }
844 return files;
845}
846
847
848/*!
849 Returns a list of strings containing the absolute paths of the
850 selected files in the dialog. If no files are selected, or
851 the mode is not ExistingFiles or ExistingFile, selectedFiles() contains the current path in the viewport.
852
853 \sa selectedNameFilter(), selectFile()
854*/
855QStringList QFileDialog::selectedFiles() const
856{
857 Q_D(const QFileDialog);
858 if (d->nativeDialogInUse)
859 return d->addDefaultSuffixToFiles(d->selectedFiles_sys());
860
861 QModelIndexList indexes = d->qFileDialogUi->listView->selectionModel()->selectedRows();
862 QStringList files;
863 for (int i = 0; i < indexes.count(); ++i)
864 files.append(indexes.at(i).data(QFileSystemModel::FilePathRole).toString());
865
866 if (files.isEmpty() && !d->lineEdit()->text().isEmpty())
867 files = d->typedFiles();
868
869 if (files.isEmpty() && !(d->fileMode == ExistingFile || d->fileMode == ExistingFiles))
870 files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
871 return files;
872}
873
874/*
875 Makes a list of filters from ;;-separated text.
876 Used by the mac and windows implementations
877*/
878QStringList qt_make_filter_list(const QString &filter)
879{
880 QString f(filter);
881
882 if (f.isEmpty())
883 return QStringList();
884
885 QString sep(QLatin1String(";;"));
886 int i = f.indexOf(sep, 0);
887 if (i == -1) {
888 if (f.indexOf(QLatin1Char('\n'), 0) != -1) {
889 sep = QLatin1Char('\n');
890 i = f.indexOf(sep, 0);
891 }
892 }
893
894 return f.split(sep);
895}
896
897/*!
898 \since 4.4
899
900 Sets the filter used in the file dialog to the given \a filter.
901
902 If \a filter contains a pair of parentheses containing one or more
903 of \bold{anything*something}, separated by spaces, then only the
904 text contained in the parentheses is used as the filter. This means
905 that these calls are all equivalent:
906
907 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 6
908
909 \sa setNameFilters()
910*/
911void QFileDialog::setNameFilter(const QString &filter)
912{
913 setNameFilters(qt_make_filter_list(filter));
914}
915
916/*!
917 \obsolete
918
919 Use setNameFilter() instead.
920*/
921void QFileDialog::setFilter(const QString &filter)
922{
923 setNameFilter(filter);
924}
925
926/*!
927 \property QFileDialog::nameFilterDetailsVisible
928 \obsolete
929 \brief This property holds whether the filter details is shown or not.
930 \since 4.4
931
932 When this property is true (the default), the filter details are shown
933 in the combo box. When the property is set to false, these are hidden.
934
935 Use setOption(HideNameFilterDetails, !\e enabled) or
936 !testOption(HideNameFilterDetails).
937*/
938void QFileDialog::setNameFilterDetailsVisible(bool enabled)
939{
940 setOption(HideNameFilterDetails, !enabled);
941}
942
943bool QFileDialog::isNameFilterDetailsVisible() const
944{
945 return !testOption(HideNameFilterDetails);
946}
947
948
949/*!
950 \since 4.4
951
952 Sets the \a filters used in the file dialog.
953
954 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 7
955*/
956void QFileDialog::setNameFilters(const QStringList &filters)
957{
958 Q_D(QFileDialog);
959 d->defaultFileTypes = (filters == QStringList(QFileDialog::tr("All Files (*)")));
960 d->nameFilters = filters;
961
962 if (d->nativeDialogInUse){
963 d->setNameFilters_sys(filters);
964 return;
965 }
966
967 d->qFileDialogUi->fileTypeCombo->clear();
968 if (filters.isEmpty())
969 return;
970
971 if (testOption(HideNameFilterDetails)) {
972 QStringList strippedFilters;
973 for (int i = 0; i < filters.count(); ++i) {
974 strippedFilters.append(filters[i].mid(0, filters[i].indexOf(QLatin1String(" ("))));
975 }
976 d->qFileDialogUi->fileTypeCombo->addItems(strippedFilters);
977 } else {
978 d->qFileDialogUi->fileTypeCombo->addItems(filters);
979 }
980 d->_q_useNameFilter(0);
981}
982
983/*!
984 \obsolete
985
986 Use setNameFilters() instead.
987*/
988void QFileDialog::setFilters(const QStringList &filters)
989{
990 setNameFilters(filters);
991}
992
993/*!
994 \since 4.4
995
996 Returns the file type filters that are in operation on this file
997 dialog.
998*/
999QStringList QFileDialog::nameFilters() const
1000{
1001 return d_func()->nameFilters;
1002}
1003
1004/*!
1005 \obsolete
1006
1007 Use nameFilters() instead.
1008*/
1009
1010QStringList QFileDialog::filters() const
1011{
1012 return nameFilters();
1013}
1014
1015/*!
1016 \since 4.4
1017
1018 Sets the current file type \a filter. Multiple filters can be
1019 passed in \a filter by separating them with semicolons or spaces.
1020
1021 \sa setNameFilter(), setNameFilters(), selectedNameFilter()
1022*/
1023void QFileDialog::selectNameFilter(const QString &filter)
1024{
1025 Q_D(QFileDialog);
1026 if (d->nativeDialogInUse) {
1027 d->selectNameFilter_sys(filter);
1028 return;
1029 }
1030
1031 int i = d->qFileDialogUi->fileTypeCombo->findText(filter);
1032 if (i >= 0) {
1033 d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
1034 d->_q_useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
1035 }
1036}
1037
1038/*!
1039 \obsolete
1040
1041 Use selectNameFilter() instead.
1042*/
1043
1044void QFileDialog::selectFilter(const QString &filter)
1045{
1046 selectNameFilter(filter);
1047}
1048
1049/*!
1050 \since 4.4
1051
1052 Returns the filter that the user selected in the file dialog.
1053
1054 \sa selectedFiles()
1055*/
1056QString QFileDialog::selectedNameFilter() const
1057{
1058 Q_D(const QFileDialog);
1059 if (d->nativeDialogInUse)
1060 return d->selectedNameFilter_sys();
1061
1062 return d->qFileDialogUi->fileTypeCombo->currentText();
1063}
1064
1065/*!
1066 \obsolete
1067
1068 Use selectedNameFilter() instead.
1069*/
1070QString QFileDialog::selectedFilter() const
1071{
1072 return selectedNameFilter();
1073}
1074
1075/*!
1076 \since 4.4
1077
1078 Returns the filter that is used when displaying files.
1079
1080 \sa setFilter()
1081*/
1082QDir::Filters QFileDialog::filter() const
1083{
1084 Q_D(const QFileDialog);
1085 return d->model->filter();
1086}
1087
1088/*!
1089 \since 4.4
1090
1091 Sets the filter used by the model to \a filters. The filter is used
1092 to specify the kind of files that should be shown.
1093
1094 \sa filter()
1095*/
1096
1097void QFileDialog::setFilter(QDir::Filters filters)
1098{
1099 Q_D(QFileDialog);
1100 d->model->setFilter(filters);
1101 if (d->nativeDialogInUse){
1102 d->setFilter_sys();
1103 return;
1104 }
1105
1106 d->showHiddenAction->setChecked((filters & QDir::Hidden));
1107}
1108
1109/*!
1110 \property QFileDialog::viewMode
1111 \brief the way files and directories are displayed in the dialog
1112
1113 By default, the \c Detail mode is used to display information about
1114 files and directories.
1115
1116 \sa ViewMode
1117*/
1118void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
1119{
1120 Q_D(QFileDialog);
1121 if (mode == Detail)
1122 d->_q_showDetailsView();
1123 else
1124 d->_q_showListView();
1125}
1126
1127QFileDialog::ViewMode QFileDialog::viewMode() const
1128{
1129 Q_D(const QFileDialog);
1130 return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
1131}
1132
1133/*!
1134 \property QFileDialog::fileMode
1135 \brief the file mode of the dialog
1136
1137 The file mode defines the number and type of items that the user is
1138 expected to select in the dialog.
1139
1140 By default, this property is set to AnyFile.
1141
1142 This function will set the labels for the FileName and
1143 \l{QFileDialog::}{Accept} \l{DialogLabel}s. It is possible to set
1144 custom text after the call to setFileMode().
1145
1146 \sa FileMode
1147*/
1148void QFileDialog::setFileMode(QFileDialog::FileMode mode)
1149{
1150 Q_D(QFileDialog);
1151 if (d->nativeDialogInUse){
1152 d->model->setFilter(d->filterForMode(filter()));
1153 d->setFilter_sys();
1154 return;
1155 }
1156
1157 d->fileMode = mode;
1158 d->retranslateWindowTitle();
1159
1160 // keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete)
1161 setOption(ShowDirsOnly, mode == DirectoryOnly);
1162
1163 // set selection mode and behavior
1164 QAbstractItemView::SelectionMode selectionMode;
1165 if (mode == QFileDialog::ExistingFiles)
1166 selectionMode = QAbstractItemView::ExtendedSelection;
1167 else
1168 selectionMode = QAbstractItemView::SingleSelection;
1169 d->qFileDialogUi->listView->setSelectionMode(selectionMode);
1170 d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
1171 // set filter
1172 d->model->setFilter(d->filterForMode(filter()));
1173 // setup file type for directory
1174 QString buttonText = (d->acceptMode == AcceptOpen ? tr("&Open") : tr("&Save"));
1175 if (mode == DirectoryOnly || mode == Directory) {
1176 d->qFileDialogUi->fileTypeCombo->clear();
1177 d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
1178 d->qFileDialogUi->fileTypeCombo->setEnabled(false);
1179
1180 if (!d->fileNameLabelExplicitlySat){
1181 setLabelText(FileName, tr("Directory:"));
1182 d->fileNameLabelExplicitlySat = false;
1183 }
1184 buttonText = tr("&Choose");
1185 } else {
1186 if (!d->fileNameLabelExplicitlySat){
1187 setLabelText(FileName, tr("File &name:"));
1188 d->fileNameLabelExplicitlySat = false;
1189 }
1190 }
1191 setLabelText(Accept, buttonText);
1192 d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
1193 d->_q_updateOkButton();
1194}
1195
1196QFileDialog::FileMode QFileDialog::fileMode() const
1197{
1198 Q_D(const QFileDialog);
1199 return d->fileMode;
1200}
1201
1202/*!
1203 \property QFileDialog::acceptMode
1204 \brief the accept mode of the dialog
1205
1206 The action mode defines whether the dialog is for opening or saving files.
1207
1208 By default, this property is set to \l{AcceptOpen}.
1209
1210 \sa AcceptMode
1211*/
1212void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
1213{
1214 Q_D(QFileDialog);
1215 d->acceptMode = mode;
1216 bool directoryMode = (d->fileMode == Directory || d->fileMode == DirectoryOnly);
1217 QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
1218 d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
1219 d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
1220 d->_q_updateOkButton();
1221 if (mode == AcceptOpen && directoryMode)
1222 setLabelText(Accept, tr("&Choose"));
1223 else
1224 setLabelText(Accept, (mode == AcceptOpen ? tr("&Open") : tr("&Save")));
1225 if (mode == AcceptSave) {
1226 d->qFileDialogUi->lookInCombo->setEditable(false);
1227 }
1228 d->retranslateWindowTitle();
1229}
1230
1231/*
1232 Returns the file system model index that is the root index in the
1233 views
1234*/
1235QModelIndex QFileDialogPrivate::rootIndex() const {
1236 return mapToSource(qFileDialogUi->listView->rootIndex());
1237}
1238
1239QAbstractItemView *QFileDialogPrivate::currentView() const {
1240 if (!qFileDialogUi->stackedWidget)
1241 return 0;
1242 if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
1243 return qFileDialogUi->listView;
1244 return qFileDialogUi->treeView;
1245}
1246
1247QLineEdit *QFileDialogPrivate::lineEdit() const {
1248 return (QLineEdit*)qFileDialogUi->fileNameEdit;
1249}
1250
1251/*
1252 Sets the view root index to be the file system model index
1253*/
1254void QFileDialogPrivate::setRootIndex(const QModelIndex &index) const {
1255 Q_ASSERT(index.isValid() ? index.model() == model : true);
1256 QModelIndex idx = mapFromSource(index);
1257 qFileDialogUi->treeView->setRootIndex(idx);
1258 qFileDialogUi->listView->setRootIndex(idx);
1259}
1260/*
1261 Select a file system model index
1262 returns the index that was selected (or not depending upon sortfilterproxymodel)
1263*/
1264QModelIndex QFileDialogPrivate::select(const QModelIndex &index) const {
1265 Q_ASSERT(index.isValid() ? index.model() == model : true);
1266
1267 QModelIndex idx = mapFromSource(index);
1268 if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
1269 qFileDialogUi->listView->selectionModel()->select(idx,
1270 QItemSelectionModel::Select | QItemSelectionModel::Rows);
1271 return idx;
1272}
1273
1274QFileDialog::AcceptMode QFileDialog::acceptMode() const
1275{
1276 Q_D(const QFileDialog);
1277 return d->acceptMode;
1278}
1279
1280/*!
1281 \property QFileDialog::readOnly
1282 \obsolete
1283 \brief Whether the filedialog is read-only
1284
1285 If this property is set to false, the file dialog will allow renaming,
1286 and deleting of files and directories and creating directories.
1287
1288 Use setOption(ReadOnly, \e enabled) or testOption(ReadOnly) instead.
1289*/
1290void QFileDialog::setReadOnly(bool enabled)
1291{
1292 setOption(ReadOnly, enabled);
1293}
1294
1295bool QFileDialog::isReadOnly() const
1296{
1297 return testOption(ReadOnly);
1298}
1299
1300/*!
1301 \property QFileDialog::resolveSymlinks
1302 \obsolete
1303 \brief whether the filedialog should resolve shortcuts
1304
1305 If this property is set to true, the file dialog will resolve
1306 shortcuts or symbolic links.
1307
1308 Use setOption(DontResolveSymlinks, !\a enabled) or
1309 !testOption(DontResolveSymlinks).
1310*/
1311void QFileDialog::setResolveSymlinks(bool enabled)
1312{
1313 setOption(DontResolveSymlinks, !enabled);
1314}
1315
1316bool QFileDialog::resolveSymlinks() const
1317{
1318 return !testOption(DontResolveSymlinks);
1319}
1320
1321/*!
1322 \property QFileDialog::confirmOverwrite
1323 \obsolete
1324 \brief whether the filedialog should ask before accepting a selected file,
1325 when the accept mode is AcceptSave
1326
1327 Use setOption(DontConfirmOverwrite, !\e enabled) or
1328 !testOption(DontConfirmOverwrite) instead.
1329*/
1330void QFileDialog::setConfirmOverwrite(bool enabled)
1331{
1332 setOption(DontConfirmOverwrite, !enabled);
1333}
1334
1335bool QFileDialog::confirmOverwrite() const
1336{
1337 return !testOption(DontConfirmOverwrite);
1338}
1339
1340/*!
1341 \property QFileDialog::defaultSuffix
1342 \brief suffix added to the filename if no other suffix was specified
1343
1344 This property specifies a string that will be added to the
1345 filename if it has no suffix already. The suffix is typically
1346 used to indicate the file type (e.g. "txt" indicates a text
1347 file).
1348*/
1349void QFileDialog::setDefaultSuffix(const QString &suffix)
1350{
1351 Q_D(QFileDialog);
1352 d->defaultSuffix = suffix;
1353}
1354
1355QString QFileDialog::defaultSuffix() const
1356{
1357 Q_D(const QFileDialog);
1358 return d->defaultSuffix;
1359}
1360
1361/*!
1362 Sets the browsing history of the filedialog to contain the given
1363 \a paths.
1364*/
1365void QFileDialog::setHistory(const QStringList &paths)
1366{
1367 Q_D(QFileDialog);
1368 d->qFileDialogUi->lookInCombo->setHistory(paths);
1369}
1370
1371void QFileDialogComboBox::setHistory(const QStringList &paths)
1372{
1373 m_history = paths;
1374 // Only populate the first item, showPopup will populate the rest if needed
1375 QList<QUrl> list;
1376 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
1377 //On windows the popup display the "C:\", convert to nativeSeparators
1378 QUrl url = QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()));
1379 if (url.isValid())
1380 list.append(url);
1381 urlModel->setUrls(list);
1382}
1383
1384/*!
1385 Returns the browsing history of the filedialog as a list of paths.
1386*/
1387QStringList QFileDialog::history() const
1388{
1389 Q_D(const QFileDialog);
1390 QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
1391 //On windows the popup display the "C:\", convert to nativeSeparators
1392 QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
1393 if (!currentHistory.contains(newHistory))
1394 currentHistory << newHistory;
1395 return currentHistory;
1396}
1397
1398/*!
1399 Sets the item delegate used to render items in the views in the
1400 file dialog to the given \a delegate.
1401
1402 \warning You should not share the same instance of a delegate between views.
1403 Doing so can cause incorrect or unintuitive editing behavior since each
1404 view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
1405 signal, and attempt to access, modify or close an editor that has already been closed.
1406
1407 Note that the model used is QFileSystemModel. It has custom item data roles, which is
1408 described by the \l{QFileSystemModel::}{Roles} enum. You can use a QFileIconProvider if
1409 you only want custom icons.
1410
1411 \sa itemDelegate(), setIconProvider(), QFileSystemModel
1412*/
1413void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
1414{
1415 Q_D(QFileDialog);
1416 d->qFileDialogUi->listView->setItemDelegate(delegate);
1417 d->qFileDialogUi->treeView->setItemDelegate(delegate);
1418}
1419
1420/*!
1421 Returns the item delegate used to render the items in the views in the filedialog.
1422*/
1423QAbstractItemDelegate *QFileDialog::itemDelegate() const
1424{
1425 Q_D(const QFileDialog);
1426 return d->qFileDialogUi->listView->itemDelegate();
1427}
1428
1429/*!
1430 Sets the icon provider used by the filedialog to the specified \a provider.
1431*/
1432void QFileDialog::setIconProvider(QFileIconProvider *provider)
1433{
1434 Q_D(QFileDialog);
1435 d->model->setIconProvider(provider);
1436}
1437
1438/*!
1439 Returns the icon provider used by the filedialog.
1440*/
1441QFileIconProvider *QFileDialog::iconProvider() const
1442{
1443 Q_D(const QFileDialog);
1444 return d->model->iconProvider();
1445}
1446
1447/*!
1448 Sets the \a text shown in the filedialog in the specified \a label.
1449*/
1450void QFileDialog::setLabelText(DialogLabel label, const QString &text)
1451{
1452 Q_D(QFileDialog);
1453 QPushButton *button;
1454 switch (label) {
1455 case LookIn:
1456 d->qFileDialogUi->lookInLabel->setText(text);
1457 break;
1458 case FileName:
1459 d->qFileDialogUi->fileNameLabel->setText(text);
1460 d->fileNameLabelExplicitlySat = true;
1461 break;
1462 case FileType:
1463 d->qFileDialogUi->fileTypeLabel->setText(text);
1464 break;
1465 case Accept:
1466 d->acceptLabel = text;
1467 if (acceptMode() == AcceptOpen)
1468 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
1469 else
1470 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
1471 if (button)
1472 button->setText(text);
1473 break;
1474 case Reject:
1475 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
1476 if (button)
1477 button->setText(text);
1478 break;
1479 }
1480}
1481
1482/*!
1483 Returns the text shown in the filedialog in the specified \a label.
1484*/
1485QString QFileDialog::labelText(DialogLabel label) const
1486{
1487 QPushButton *button;
1488 Q_D(const QFileDialog);
1489 switch (label) {
1490 case LookIn:
1491 return d->qFileDialogUi->lookInLabel->text();
1492 case FileName:
1493 return d->qFileDialogUi->fileNameLabel->text();
1494 case FileType:
1495 return d->qFileDialogUi->fileTypeLabel->text();
1496 case Accept:
1497 if (acceptMode() == AcceptOpen)
1498 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
1499 else
1500 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
1501 if (button)
1502 return button->text();
1503 case Reject:
1504 button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
1505 if (button)
1506 return button->text();
1507 }
1508 return QString();
1509}
1510
1511/*
1512 For the native file dialogs
1513*/
1514
1515#if defined(Q_WS_WIN)
1516extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
1517 QString *initialDirectory,
1518 QString *selectedFilter);
1519
1520extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
1521 QString *initialDirectory,
1522 QString *selectedFilter);
1523
1524extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
1525 QString *initialDirectory,
1526 QString *selectedFilter);
1527
1528extern QString qt_win_get_existing_directory(const QFileDialogArgs &args);
1529#endif
1530
1531/*!
1532 This is a convenience static function that returns an existing file
1533 selected by the user. If the user presses Cancel, it returns a null
1534 string.
1535
1536 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8
1537
1538 The function creates a modal file dialog with the given \a parent widget.
1539 If the parent is not 0, the dialog will be shown centered over the
1540 parent widget.
1541
1542 The file dialog's working directory will be set to \a dir. If \a
1543 dir includes a file name, the file will be selected. Only files
1544 that match the given \a filter are shown. The filter selected is
1545 set to \a selectedFilter. The parameters \a dir, \a
1546 selectedFilter, and \a filter may be empty strings. If you want
1547 multiple filters, separate them with ';;', for example:
1548
1549 \code
1550 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1551 \endcode
1552
1553 The \a options argument holds various
1554 options about how to run the dialog, see the QFileDialog::Option enum for
1555 more information on the flags you can pass.
1556
1557 The dialog's caption is set to \a caption. If \a caption is not
1558 specified then a default caption will be used.
1559
1560 Under Windows and Mac OS X, this static function will use the native
1561 file dialog and not a QFileDialog.
1562
1563 Note that on Windows the dialog will spin a blocking modal event loop
1564 that will not dispatch any QTimers, and if parent is not 0 then it will
1565 position the dialog just under the parent's title bar.
1566
1567 Under Unix/X11, the normal behavior of the file dialog is to resolve
1568 and follow symlinks. For example, if \c{/usr/tmp} is a symlink to
1569 \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after
1570 entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks,
1571 the file dialog will treat symlinks as regular directories.
1572
1573 \warning Do not delete \a parent during the execution of the dialog.
1574 If you want to do this, you should create the dialog
1575 yourself using one of the QFileDialog constructors.
1576
1577 \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory()
1578*/
1579QString QFileDialog::getOpenFileName(QWidget *parent,
1580 const QString &caption,
1581 const QString &dir,
1582 const QString &filter,
1583 QString *selectedFilter,
1584 Options options)
1585{
1586 if (qt_filedialog_open_filename_hook && !(options & DontUseNativeDialog))
1587 return qt_filedialog_open_filename_hook(parent, caption, dir, filter, selectedFilter, options);
1588 QFileDialogArgs args;
1589 args.parent = parent;
1590 args.caption = caption;
1591 args.directory = QFileDialogPrivate::workingDirectory(dir);
1592 args.selection = QFileDialogPrivate::initialSelection(dir);
1593 args.filter = filter;
1594 args.mode = ExistingFile;
1595 args.options = options;
1596#if defined(Q_WS_WIN)
1597 if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
1598 return qt_win_get_open_file_name(args, &(args.directory), selectedFilter);
1599 }
1600#endif
1601
1602 // create a qt dialog
1603 QFileDialog dialog(args);
1604 if (selectedFilter)
1605 dialog.selectNameFilter(*selectedFilter);
1606 if (dialog.exec() == QDialog::Accepted) {
1607 if (selectedFilter)
1608 *selectedFilter = dialog.selectedFilter();
1609 return dialog.selectedFiles().value(0);
1610 }
1611 return QString();
1612}
1613
1614/*!
1615 This is a convenience static function that will return one or more
1616 existing files selected by the user.
1617
1618 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9
1619
1620 This function creates a modal file dialog with the given \a parent
1621 widget. If the parent is not 0, the dialog will be shown centered
1622 over the parent widget.
1623
1624 The file dialog's working directory will be set to \a dir. If \a
1625 dir includes a file name, the file will be selected. The filter
1626 is set to \a filter so that only those files which match the filter
1627 are shown. The filter selected is set to \a selectedFilter. The parameters
1628 \a dir, \a selectedFilter and \a filter may be empty strings. If you
1629 need multiple filters, separate them with ';;', for instance:
1630
1631 \code
1632 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1633 \endcode
1634
1635 The dialog's caption is set to \a caption. If \a caption is not
1636 specified then a default caption will be used.
1637
1638 Under Windows and Mac OS X, this static function will use the native
1639 file dialog and not a QFileDialog. On Mac OS X, the \a dir argument
1640 is ignored, the native dialog always displays the last visited directory.
1641
1642 Note that on Windows the dialog will spin a blocking modal event loop
1643 that will not dispatch any QTimers, and if parent is not 0 then it will
1644 position the dialog just under the parent's title bar.
1645
1646 Under Unix/X11, the normal behavior of the file dialog is to resolve
1647 and follow symlinks. For example, if \c{/usr/tmp} is a symlink to
1648 \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after
1649 entering \c{/usr/tmp}. The \a options argument holds various
1650 options about how to run the dialog, see the QFileDialog::Option enum for
1651 more information on the flags you can pass.
1652
1653 Note that if you want to iterate over the list of files, you should
1654 iterate over a copy. For example:
1655
1656 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 10
1657
1658 \warning Do not delete \a parent during the execution of the dialog.
1659 If you want to do this, you should create the dialog
1660 yourself using one of the QFileDialog constructors.
1661
1662 \sa getOpenFileName(), getSaveFileName(), getExistingDirectory()
1663*/
1664QStringList QFileDialog::getOpenFileNames(QWidget *parent,
1665 const QString &caption,
1666 const QString &dir,
1667 const QString &filter,
1668 QString *selectedFilter,
1669 Options options)
1670{
1671 if (qt_filedialog_open_filenames_hook)
1672 return qt_filedialog_open_filenames_hook(parent, caption, dir, filter, selectedFilter, options);
1673 QFileDialogArgs args;
1674 args.parent = parent;
1675 args.caption = caption;
1676 args.directory = QFileDialogPrivate::workingDirectory(dir);
1677 args.selection = QFileDialogPrivate::initialSelection(dir);
1678 args.filter = filter;
1679 args.mode = ExistingFiles;
1680 args.options = options;
1681
1682#if defined(Q_WS_WIN)
1683 if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
1684 return qt_win_get_open_file_names(args, &(args.directory), selectedFilter);
1685 }
1686#endif
1687
1688 // create a qt dialog
1689 QFileDialog dialog(args);
1690 if (selectedFilter)
1691 dialog.selectNameFilter(*selectedFilter);
1692 if (dialog.exec() == QDialog::Accepted) {
1693 if (selectedFilter)
1694 *selectedFilter = dialog.selectedFilter();
1695 return dialog.selectedFiles();
1696 }
1697 return QStringList();
1698}
1699
1700/*!
1701 This is a convenience static function that will return a file name
1702 selected by the user. The file does not have to exist.
1703
1704 It creates a modal file dialog with the given \a parent widget. If the
1705 parent is not 0, the dialog will be shown centered over the parent
1706 widget.
1707
1708 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11
1709
1710 The file dialog's working directory will be set to \a dir. If \a
1711 dir includes a file name, the file will be selected. Only files that
1712 match the \a filter are shown. The filter selected is set to
1713 \a selectedFilter. The parameters \a dir, \a selectedFilter, and
1714 \a filter may be empty strings. Multiple filters are separated with ';;'.
1715 For instance:
1716
1717 \code
1718 "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
1719 \endcode
1720
1721 The \a options argument holds various
1722 options about how to run the dialog, see the QFileDialog::Option enum for
1723 more information on the flags you can pass.
1724
1725 The default filter can be chosen by setting \a selectedFilter to the desired value.
1726
1727 The dialog's caption is set to \a caption. If \a caption is not
1728 specified then a default caption will be used.
1729
1730 Under Windows and Mac OS X, this static function will use the native
1731 file dialog and not a QFileDialog.
1732
1733 Note that on Windows the dialog will spin a blocking modal event loop
1734 that will not dispatch any QTimers, and if parent is not 0 then it will
1735 position the dialog just under the parent's title bar.
1736 On Mac OS X, the filter argument is ignored.
1737
1738 Under Unix/X11, the normal behavior of the file dialog is to resolve
1739 and follow symlinks. For example, if \c{/usr/tmp} is a symlink to
1740 \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after
1741 entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks,
1742 the file dialog will treat symlinks as regular directories.
1743
1744 \warning Do not delete \a parent during the execution of the dialog.
1745 If you want to do this, you should create the dialog
1746 yourself using one of the QFileDialog constructors.
1747
1748 \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory()
1749*/
1750QString QFileDialog::getSaveFileName(QWidget *parent,
1751 const QString &caption,
1752 const QString &dir,
1753 const QString &filter,
1754 QString *selectedFilter,
1755 Options options)
1756{
1757 if (qt_filedialog_save_filename_hook)
1758 return qt_filedialog_save_filename_hook(parent, caption, dir, filter, selectedFilter, options);
1759 QFileDialogArgs args;
1760 args.parent = parent;
1761 args.caption = caption;
1762 args.directory = QFileDialogPrivate::workingDirectory(dir);
1763 args.selection = QFileDialogPrivate::initialSelection(dir);
1764 args.filter = filter;
1765 args.mode = AnyFile;
1766 args.options = options;
1767
1768#if defined(Q_WS_WIN)
1769 if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
1770 return qt_win_get_save_file_name(args, &(args.directory), selectedFilter);
1771 }
1772#endif
1773
1774 // create a qt dialog
1775 QFileDialog dialog(args);
1776 dialog.setAcceptMode(AcceptSave);
1777 if (selectedFilter)
1778 dialog.selectNameFilter(*selectedFilter);
1779 if (dialog.exec() == QDialog::Accepted) {
1780 if (selectedFilter)
1781 *selectedFilter = dialog.selectedFilter();
1782 return dialog.selectedFiles().value(0);
1783 }
1784
1785 return QString();
1786}
1787
1788/*!
1789 This is a convenience static function that will return an existing
1790 directory selected by the user.
1791
1792 \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12
1793
1794 This function creates a modal file dialog with the given \a parent
1795 widget. If the parent is not 0, the dialog will be shown centered over
1796 the parent widget.
1797
1798 The dialog's working directory is set to \a dir, and the caption is
1799 set to \a caption. Either of these may be an empty string in which case
1800 the current directory and a default caption will be used
1801 respectively.
1802
1803 The \a options argument holds various
1804 options about how to run the dialog, see the QFileDialog::Option enum for
1805 more information on the flags you can pass. Note that \l{QFileDialog::}{ShowDirsOnly}
1806 must be set to ensure a native file dialog.
1807
1808 Under Windows and Mac OS X, this static function will use the native
1809 file dialog and not a QFileDialog. On Mac OS X, the \a dir argument
1810 is ignored, the native dialog always displays the last visited directory.
1811 On Windows CE, if the device has no native file dialog, a QFileDialog
1812 will be used.
1813
1814 Under Unix/X11, the normal behavior of the file dialog is to resolve
1815 and follow symlinks. For example, if \c{/usr/tmp} is a symlink to
1816 \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after
1817 entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks,
1818 the file dialog will treat symlinks as regular directories.
1819
1820 Note that on Windows the dialog will spin a blocking modal event loop
1821 that will not dispatch any QTimers, and if parent is not 0 then it will
1822 position the dialog just under the parent's title bar.
1823
1824 \warning Do not delete \a parent during the execution of the dialog.
1825 If you want to do this, you should create the dialog
1826 yourself using one of the QFileDialog constructors.
1827
1828 \sa getOpenFileName(), getOpenFileNames(), getSaveFileName()
1829*/
1830QString QFileDialog::getExistingDirectory(QWidget *parent,
1831 const QString &caption,
1832 const QString &dir,
1833 Options options)
1834{
1835 if (qt_filedialog_existing_directory_hook)
1836 return qt_filedialog_existing_directory_hook(parent, caption, dir, options);
1837 QFileDialogArgs args;
1838 args.parent = parent;
1839 args.caption = caption;
1840 args.directory = QFileDialogPrivate::workingDirectory(dir);
1841 args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
1842 args.options = options;
1843
1844#if defined(Q_WS_WIN)
1845 if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
1846#if defined(Q_OS_WINCE)
1847 && qt_priv_ptr_valid
1848#endif
1849 ) {
1850 return qt_win_get_existing_directory(args);
1851 }
1852#endif
1853
1854 // create a qt dialog
1855 QFileDialog dialog(args);
1856 if (dialog.exec() == QDialog::Accepted) {
1857 return dialog.selectedFiles().value(0);
1858 }
1859 return QString();
1860}
1861
1862inline static QString _qt_get_directory(const QString &path)
1863{
1864 QFileInfo info = QFileInfo(QDir::current(), path);
1865 if (info.exists() && info.isDir())
1866 return QDir::cleanPath(info.absoluteFilePath());
1867 info.setFile(info.absolutePath());
1868 if (info.exists() && info.isDir())
1869 return info.absoluteFilePath();
1870 return QString();
1871}
1872/*
1873 Get the initial directory path
1874
1875 \sa initialSelection()
1876 */
1877QString QFileDialogPrivate::workingDirectory(const QString &path)
1878{
1879 if (!path.isEmpty()) {
1880 QString directory = _qt_get_directory(path);
1881 if (!directory.isEmpty())
1882 return directory;
1883 }
1884 QString directory = _qt_get_directory(*lastVisitedDir());
1885 if (!directory.isEmpty())
1886 return directory;
1887 return QDir::currentPath();
1888}
1889
1890/*
1891 Get the initial selection given a path. The initial directory
1892 can contain both the initial directory and initial selection
1893 /home/user/foo.txt
1894
1895 \sa workingDirectory()
1896 */
1897QString QFileDialogPrivate::initialSelection(const QString &path)
1898{
1899 if (!path.isEmpty()) {
1900 QFileInfo info(path);
1901 if (!info.isDir())
1902 return info.fileName();
1903 }
1904 return QString();
1905}
1906
1907/*!
1908 \reimp
1909*/
1910void QFileDialog::done(int result)
1911{
1912 Q_D(QFileDialog);
1913
1914 QDialog::done(result);
1915
1916 if (d->receiverToDisconnectOnClose) {
1917 disconnect(this, d->signalToDisconnectOnClose,
1918 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
1919 d->receiverToDisconnectOnClose = 0;
1920 }
1921 d->memberToDisconnectOnClose.clear();
1922 d->signalToDisconnectOnClose.clear();
1923}
1924
1925/*!
1926 \reimp
1927*/
1928void QFileDialog::accept()
1929{
1930 Q_D(QFileDialog);
1931 QStringList files = selectedFiles();
1932 if (files.isEmpty())
1933 return;
1934 if (d->nativeDialogInUse){
1935 d->emitFilesSelected(files);
1936 QDialog::accept();
1937 return;
1938 }
1939
1940 QString lineEditText = d->lineEdit()->text();
1941 // "hidden feature" type .. and then enter, and it will move up a dir
1942 // special case for ".."
1943 if (lineEditText == QLatin1String("..")) {
1944 d->_q_navigateToParent();
1945 bool block = d->qFileDialogUi->fileNameEdit->blockSignals(true);
1946 d->lineEdit()->selectAll();
1947 d->qFileDialogUi->fileNameEdit->blockSignals(block);
1948 return;
1949 }
1950
1951 switch (d->fileMode) {
1952 case DirectoryOnly:
1953 case Directory: {
1954 QString fn = files.first();
1955 QFileInfo info(fn);
1956 if (!info.exists())
1957 info = QFileInfo(d->getEnvironmentVariable(fn));
1958 if (!info.exists()) {
1959#ifndef QT_NO_MESSAGEBOX
1960 QString message = tr("%1\nDirectory not found.\nPlease verify the "
1961 "correct directory name was given.");
1962 QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
1963#endif // QT_NO_MESSAGEBOX
1964 return;
1965 }
1966 if (info.isDir()) {
1967 d->emitFilesSelected(files);
1968 QDialog::accept();
1969 }
1970 return;
1971 }
1972
1973 case AnyFile: {
1974 QString fn = files.first();
1975 QFileInfo info(fn);
1976 if (info.isDir()) {
1977 setDirectory(info.absoluteFilePath());
1978 return;
1979 }
1980
1981 if (!info.exists()) {
1982 int maxNameLength = d->maxNameLength(info.path());
1983 if (maxNameLength >= 0 && info.fileName().length() > maxNameLength)
1984 return;
1985 }
1986
1987 // check if we have to ask for permission to overwrite the file
1988 if (!info.exists() || !confirmOverwrite() || acceptMode() == AcceptOpen) {
1989 d->emitFilesSelected(QStringList(fn));
1990 QDialog::accept();
1991#ifndef QT_NO_MESSAGEBOX
1992 } else {
1993 if (QMessageBox::warning(this, windowTitle(),
1994 tr("%1 already exists.\nDo you want to replace it?")
1995 .arg(info.fileName()),
1996 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
1997 == QMessageBox::Yes) {
1998 d->emitFilesSelected(QStringList(fn));
1999 QDialog::accept();
2000 }
2001#endif
2002 }
2003 return;
2004 }
2005
2006 case ExistingFile:
2007 case ExistingFiles:
2008 for (int i = 0; i < files.count(); ++i) {
2009 QFileInfo info(files.at(i));
2010 if (!info.exists())
2011 info = QFileInfo(d->getEnvironmentVariable(files.at(i)));
2012 if (!info.exists()) {
2013#ifndef QT_NO_MESSAGEBOX
2014 QString message = tr("%1\nFile not found.\nPlease verify the "
2015 "correct file name was given.");
2016 QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
2017#endif // QT_NO_MESSAGEBOX
2018 return;
2019 }
2020 if (info.isDir()) {
2021 setDirectory(info.absoluteFilePath());
2022 d->lineEdit()->clear();
2023 return;
2024 }
2025 }
2026 d->emitFilesSelected(files);
2027 QDialog::accept();
2028 return;
2029 }
2030}
2031
2032/*!
2033 \internal
2034
2035 Create widgets, layout and set default values
2036*/
2037void QFileDialogPrivate::init(const QString &directory, const QString &nameFilter,
2038 const QString &caption)
2039{
2040 Q_Q(QFileDialog);
2041 if (!caption.isEmpty()) {
2042 useDefaultCaption = false;
2043 setWindowTitle = caption;
2044 q->setWindowTitle(caption);
2045 }
2046
2047 createWidgets();
2048 createMenuActions();
2049 retranslateStrings();
2050 q->setFileMode(fileMode);
2051
2052#ifndef QT_NO_SETTINGS
2053 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
2054 settings.beginGroup(QLatin1String("Qt"));
2055 if (!directory.isEmpty())
2056 setLastVisitedDirectory(workingDirectory(directory));
2057 q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
2058#endif
2059
2060#ifdef Q_OS_WINCE
2061 qFileDialogUi->lookInLabel->setVisible(false);
2062 qFileDialogUi->fileNameLabel->setVisible(false);
2063 qFileDialogUi->fileTypeLabel->setVisible(false);
2064 qFileDialogUi->sidebar->hide();
2065#endif
2066 // Default case
2067 if (!nameFilter.isEmpty())
2068 q->setNameFilter(nameFilter);
2069 q->setAcceptMode(QFileDialog::AcceptOpen);
2070 q->setDirectory(workingDirectory(directory));
2071 q->selectFile(initialSelection(directory));
2072
2073 _q_updateOkButton();
2074 q->resize(q->sizeHint());
2075}
2076
2077/*!
2078 \internal
2079
2080 Create the widgets, set properties and connections
2081*/
2082void QFileDialogPrivate::createWidgets()
2083{
2084 Q_Q(QFileDialog);
2085 model = new QFileSystemModel(q);
2086 model->setObjectName(QLatin1String("qt_filesystem_model"));
2087#ifdef Q_WS_MAC
2088 model->setNameFilterDisables(true);
2089#else
2090 model->setNameFilterDisables(false);
2091#endif
2092 QFileDialog::connect(model, SIGNAL(fileRenamed(const QString &, const QString &, const QString &)), q, SLOT(_q_fileRenamed(const QString &, const QString &, const QString &)));
2093 QFileDialog::connect(model, SIGNAL(rootPathChanged(const QString &)),
2094 q, SLOT(_q_pathChanged(const QString &)));
2095 QFileDialog::connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
2096 q, SLOT(_q_rowsInserted(const QModelIndex &)));
2097 model->setReadOnly(false);
2098
2099 qFileDialogUi = new Ui_QFileDialog();
2100 qFileDialogUi->setupUi(q);
2101
2102 QList<QUrl> initialBookmarks;
2103 initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
2104 << QUrl::fromLocalFile(QDir::homePath());
2105 qFileDialogUi->sidebar->init(model, initialBookmarks);
2106 QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(const QUrl &)),
2107 q, SLOT(_q_goToUrl(const QUrl &)));
2108
2109 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
2110 QObject::connect(qFileDialogUi->buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
2111
2112
2113 qFileDialogUi->lookInCombo->init(this);
2114 QObject::connect(qFileDialogUi->lookInCombo, SIGNAL(activated(QString)), q, SLOT(_q_goToDirectory(QString)));
2115
2116 qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
2117 qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
2118
2119 // filename
2120 qFileDialogUi->fileNameEdit->init(this);
2121#ifndef QT_NO_SHORTCUT
2122 qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
2123#endif
2124#ifndef QT_NO_COMPLETER
2125 completer = new QFSCompletor(model, q);
2126 qFileDialogUi->fileNameEdit->setCompleter(completer);
2127 completer->sourceModel = model;
2128 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
2129 q, SLOT(_q_autoCompleteFileName(QString)));
2130#endif // QT_NO_COMPLETER
2131 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
2132 q, SLOT(_q_updateOkButton()));
2133
2134 QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(returnPressed()), q, SLOT(accept()));
2135
2136 // filetype
2137 qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
2138 qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
2139 qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
2140 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(int)),
2141 q, SLOT(_q_useNameFilter(int)));
2142 QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(const QString &)),
2143 q, SIGNAL(filterSelected(const QString &)));
2144
2145 qFileDialogUi->listView->init(this);
2146 qFileDialogUi->listView->setModel(model);
2147 QObject::connect(qFileDialogUi->listView, SIGNAL(activated(QModelIndex)),
2148 q, SLOT(_q_enterDirectory(QModelIndex)));
2149 QObject::connect(qFileDialogUi->listView, SIGNAL(customContextMenuRequested(QPoint)),
2150 q, SLOT(_q_showContextMenu(QPoint)));
2151#ifndef QT_NO_SHORTCUT
2152 QShortcut *shortcut = new QShortcut(qFileDialogUi->listView);
2153 shortcut->setKey(QKeySequence(QLatin1String("Delete")));
2154 QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
2155#endif
2156
2157 qFileDialogUi->treeView->init(this);
2158 qFileDialogUi->treeView->setModel(model);
2159 QHeaderView *treeHeader = qFileDialogUi->treeView->header();
2160 QFontMetrics fm(q->font());
2161 treeHeader->resizeSection(0, fm.width(QLatin1String("wwwwwwwwwwwwwwwwwwwwwwwwww")));
2162 treeHeader->resizeSection(1, fm.width(QLatin1String("128.88 GB")));
2163 treeHeader->resizeSection(2, fm.width(QLatin1String("mp3Folder")));
2164 treeHeader->resizeSection(3, fm.width(QLatin1String("10/29/81 02:02PM")));
2165 treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
2166
2167 QActionGroup *showActionGroup = new QActionGroup(q);
2168 showActionGroup->setExclusive(false);
2169 QObject::connect(showActionGroup, SIGNAL(triggered(QAction *)),
2170 q, SLOT(_q_showHeader(QAction *)));;
2171
2172 QAbstractItemModel *abstractModel = model;
2173#ifndef QT_NO_PROXYMODEL
2174 if (proxyModel)
2175 abstractModel = proxyModel;
2176#endif
2177 for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
2178 QAction *showHeader = new QAction(showActionGroup);
2179 showHeader->setCheckable(true);
2180 showHeader->setChecked(true);
2181 treeHeader->addAction(showHeader);
2182 }
2183
2184 QItemSelectionModel *selModel = qFileDialogUi->treeView->selectionModel();
2185 qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
2186 delete selModel;
2187 QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
2188 q, SLOT(_q_enterDirectory(QModelIndex)));
2189 QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
2190 q, SLOT(_q_showContextMenu(QPoint)));
2191#ifndef QT_NO_SHORTCUT
2192 shortcut = new QShortcut(qFileDialogUi->treeView);
2193 shortcut->setKey(QKeySequence(QLatin1String("Delete")));
2194 QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
2195#endif
2196
2197 // Selections
2198 QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
2199 QObject::connect(selections, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
2200 q, SLOT(_q_selectionChanged()));
2201 QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
2202 q, SLOT(_q_currentChanged(QModelIndex)));
2203 qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
2204
2205 createToolButtons();
2206}
2207
2208void QFileDialogPrivate::_q_showHeader(QAction *action)
2209{
2210 Q_Q(QFileDialog);
2211 QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
2212 qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked());
2213}
2214
2215#ifndef QT_NO_PROXYMODEL
2216/*!
2217 \since 4.3
2218
2219 Sets the model for the views to the given \a proxyModel. This is useful if you
2220 want to modify the underlying model; for example, to add columns, filter
2221 data or add drives.
2222
2223 Any existing proxy model will be removed, but not deleted. The file dialog
2224 will take ownership of the \a proxyModel.
2225
2226 \sa proxyModel()
2227*/
2228void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
2229{
2230 Q_D(QFileDialog);
2231 if ((!proxyModel && !d->proxyModel)
2232 || (proxyModel == d->proxyModel))
2233 return;
2234
2235 QModelIndex idx = d->rootIndex();
2236 if (d->proxyModel) {
2237 disconnect(d->proxyModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
2238 this, SLOT(_q_rowsInserted(const QModelIndex &)));
2239 } else {
2240 disconnect(d->model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
2241 this, SLOT(_q_rowsInserted(const QModelIndex &)));
2242 }
2243
2244 if (proxyModel != 0) {
2245 proxyModel->setParent(this);
2246 d->proxyModel = proxyModel;
2247 proxyModel->setSourceModel(d->model);
2248 d->qFileDialogUi->listView->setModel(d->proxyModel);
2249 d->qFileDialogUi->treeView->setModel(d->proxyModel);
2250#ifndef QT_NO_COMPLETER
2251 d->completer->setModel(d->proxyModel);
2252 d->completer->proxyModel = d->proxyModel;
2253#endif
2254 connect(d->proxyModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
2255 this, SLOT(_q_rowsInserted(const QModelIndex &)));
2256 } else {
2257 d->proxyModel = 0;
2258 d->qFileDialogUi->listView->setModel(d->model);
2259 d->qFileDialogUi->treeView->setModel(d->model);
2260#ifndef QT_NO_COMPLETER
2261 d->completer->setModel(d->model);
2262 d->completer->sourceModel = d->model;
2263 d->completer->proxyModel = 0;
2264#endif
2265 connect(d->model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
2266 this, SLOT(_q_rowsInserted(const QModelIndex &)));
2267 }
2268 QItemSelectionModel *selModel = d->qFileDialogUi->treeView->selectionModel();
2269 d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
2270 delete selModel;
2271 d->setRootIndex(idx);
2272
2273 // reconnect selection
2274 QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
2275 QObject::connect(selections, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
2276 this, SLOT(_q_selectionChanged()));
2277 QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
2278 this, SLOT(_q_currentChanged(QModelIndex)));
2279}
2280
2281/*!
2282 Returns the proxy model used by the file dialog. By default no proxy is set.
2283
2284 \sa setProxyModel()
2285*/
2286QAbstractProxyModel *QFileDialog::proxyModel() const
2287{
2288 Q_D(const QFileDialog);
2289 return d->proxyModel;
2290}
2291#endif // QT_NO_PROXYMODEL
2292
2293/*!
2294 \internal
2295
2296 Create tool buttons, set properties and connections
2297*/
2298void QFileDialogPrivate::createToolButtons()
2299{
2300 Q_Q(QFileDialog);
2301 qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, 0, q));
2302 qFileDialogUi->backButton->setAutoRaise(true);
2303 qFileDialogUi->backButton->setEnabled(false);
2304 QObject::connect(qFileDialogUi->backButton, SIGNAL(clicked()), q, SLOT(_q_navigateBackward()));
2305
2306 qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, 0, q));
2307 qFileDialogUi->forwardButton->setAutoRaise(true);
2308 qFileDialogUi->forwardButton->setEnabled(false);
2309 QObject::connect(qFileDialogUi->forwardButton, SIGNAL(clicked()), q, SLOT(_q_navigateForward()));
2310
2311 qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, 0, q));
2312 qFileDialogUi->toParentButton->setAutoRaise(true);
2313 qFileDialogUi->toParentButton->setEnabled(false);
2314 QObject::connect(qFileDialogUi->toParentButton, SIGNAL(clicked()), q, SLOT(_q_navigateToParent()));
2315
2316 qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, 0, q));
2317 qFileDialogUi->listModeButton->setAutoRaise(true);
2318 qFileDialogUi->listModeButton->setDown(true);
2319 QObject::connect(qFileDialogUi->listModeButton, SIGNAL(clicked()), q, SLOT(_q_showListView()));
2320
2321 qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, 0, q));
2322 qFileDialogUi->detailModeButton->setAutoRaise(true);
2323 QObject::connect(qFileDialogUi->detailModeButton, SIGNAL(clicked()), q, SLOT(_q_showDetailsView()));
2324
2325 QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
2326 qFileDialogUi->backButton->setFixedSize(toolSize);
2327 qFileDialogUi->listModeButton->setFixedSize(toolSize);
2328 qFileDialogUi->detailModeButton->setFixedSize(toolSize);
2329 qFileDialogUi->forwardButton->setFixedSize(toolSize);
2330 qFileDialogUi->toParentButton->setFixedSize(toolSize);
2331
2332 qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, 0, q));
2333 qFileDialogUi->newFolderButton->setFixedSize(toolSize);
2334 qFileDialogUi->newFolderButton->setAutoRaise(true);
2335 qFileDialogUi->newFolderButton->setEnabled(false);
2336 QObject::connect(qFileDialogUi->newFolderButton, SIGNAL(clicked()), q, SLOT(_q_createDirectory()));
2337}
2338
2339/*!
2340 \internal
2341
2342 Create actions which will be used in the right click.
2343*/
2344void QFileDialogPrivate::createMenuActions()
2345{
2346 Q_Q(QFileDialog);
2347
2348 QAction *goHomeAction = new QAction(q);
2349#ifndef QT_NO_SHORTCUT
2350 goHomeAction->setShortcut(Qt::CTRL + Qt::Key_H + Qt::SHIFT);
2351#endif
2352 QObject::connect(goHomeAction, SIGNAL(triggered()), q, SLOT(_q_goHome()));
2353 q->addAction(goHomeAction);
2354
2355 // ### TODO add Desktop & Computer actions
2356
2357 QAction *goToParent = new QAction(q);
2358 goToParent->setObjectName(QLatin1String("qt_goto_parent_action"));
2359#ifndef QT_NO_SHORTCUT
2360 goToParent->setShortcut(Qt::CTRL + Qt::UpArrow);
2361#endif
2362 QObject::connect(goToParent, SIGNAL(triggered()), q, SLOT(_q_navigateToParent()));
2363 q->addAction(goToParent);
2364
2365 renameAction = new QAction(q);
2366 renameAction->setEnabled(false);
2367 renameAction->setObjectName(QLatin1String("qt_rename_action"));
2368 QObject::connect(renameAction, SIGNAL(triggered()), q, SLOT(_q_renameCurrent()));
2369
2370 deleteAction = new QAction(q);
2371 deleteAction->setEnabled(false);
2372 deleteAction->setObjectName(QLatin1String("qt_delete_action"));
2373 QObject::connect(deleteAction, SIGNAL(triggered()), q, SLOT(_q_deleteCurrent()));
2374
2375 showHiddenAction = new QAction(q);
2376 showHiddenAction->setObjectName(QLatin1String("qt_show_hidden_action"));
2377 showHiddenAction->setCheckable(true);
2378 QObject::connect(showHiddenAction, SIGNAL(triggered()), q, SLOT(_q_showHidden()));
2379
2380 newFolderAction = new QAction(q);
2381 newFolderAction->setObjectName(QLatin1String("qt_new_folder_action"));
2382 QObject::connect(newFolderAction, SIGNAL(triggered()), q, SLOT(_q_createDirectory()));
2383}
2384
2385void QFileDialogPrivate::_q_goHome()
2386{
2387 Q_Q(QFileDialog);
2388 q->setDirectory(QDir::homePath());
2389}
2390
2391/*!
2392 \internal
2393
2394 Update history with new path, buttons, and combo
2395*/
2396void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
2397{
2398 Q_Q(QFileDialog);
2399 QDir dir(model->rootDirectory());
2400 qFileDialogUi->toParentButton->setEnabled(dir.exists());
2401 qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
2402 q->setHistory(qFileDialogUi->lookInCombo->history());
2403
2404 if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) {
2405 while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) {
2406 currentHistory.removeLast();
2407 }
2408 currentHistory.append(QDir::toNativeSeparators(newPath));
2409 ++currentHistoryLocation;
2410 }
2411 qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
2412 qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
2413}
2414
2415/*!
2416 \internal
2417
2418 Navigates to the last directory viewed in the dialog.
2419*/
2420void QFileDialogPrivate::_q_navigateBackward()
2421{
2422 Q_Q(QFileDialog);
2423 if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
2424 --currentHistoryLocation;
2425 QString previousHistory = currentHistory.at(currentHistoryLocation);
2426 q->setDirectory(previousHistory);
2427 }
2428}
2429
2430/*!
2431 \internal
2432
2433 Navigates to the last directory viewed in the dialog.
2434*/
2435void QFileDialogPrivate::_q_navigateForward()
2436{
2437 Q_Q(QFileDialog);
2438 if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
2439 ++currentHistoryLocation;
2440 QString nextHistory = currentHistory.at(currentHistoryLocation);
2441 q->setDirectory(nextHistory);
2442 }
2443}
2444
2445/*!
2446 \internal
2447
2448 Navigates to the parent directory of the currently displayed directory
2449 in the dialog.
2450*/
2451void QFileDialogPrivate::_q_navigateToParent()
2452{
2453 Q_Q(QFileDialog);
2454 QDir dir(model->rootDirectory());
2455 QString newDirectory;
2456 if (dir.isRoot()) {
2457 newDirectory = model->myComputer().toString();
2458 } else {
2459 dir.cdUp();
2460 newDirectory = dir.absolutePath();
2461 }
2462 q->setDirectory(newDirectory);
2463 emit q->directoryEntered(newDirectory);
2464}
2465
2466/*!
2467 \internal
2468
2469 Creates a new directory, first asking the user for a suitable name.
2470*/
2471void QFileDialogPrivate::_q_createDirectory()
2472{
2473 Q_Q(QFileDialog);
2474 qFileDialogUi->listView->clearSelection();
2475
2476 QString newFolderString = QFileDialog::tr("New Folder");
2477 QString folderName = newFolderString;
2478 QString prefix = q->directory().absolutePath() + QDir::separator();
2479 if (QFile::exists(prefix + folderName)) {
2480 qlonglong suffix = 2;
2481 while (QFile::exists(prefix + folderName)) {
2482 folderName = newFolderString + QString::number(suffix++);
2483 }
2484 }
2485
2486 QModelIndex parent = rootIndex();
2487 QModelIndex index = model->mkdir(parent, folderName);
2488 if (!index.isValid())
2489 return;
2490
2491 index = select(index);
2492 if (index.isValid()) {
2493 qFileDialogUi->treeView->setCurrentIndex(index);
2494 currentView()->edit(index);
2495 }
2496}
2497
2498void QFileDialogPrivate::_q_showListView()
2499{
2500 qFileDialogUi->listModeButton->setDown(true);
2501 qFileDialogUi->detailModeButton->setDown(false);
2502 qFileDialogUi->treeView->hide();
2503 qFileDialogUi->listView->show();
2504 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
2505 qFileDialogUi->listView->doItemsLayout();
2506}
2507
2508void QFileDialogPrivate::_q_showDetailsView()
2509{
2510 qFileDialogUi->listModeButton->setDown(false);
2511 qFileDialogUi->detailModeButton->setDown(true);
2512 qFileDialogUi->listView->hide();
2513 qFileDialogUi->treeView->show();
2514 qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
2515 qFileDialogUi->treeView->doItemsLayout();
2516}
2517
2518/*!
2519 \internal
2520
2521 Show the context menu for the file/dir under position
2522*/
2523void QFileDialogPrivate::_q_showContextMenu(const QPoint &position)
2524{
2525#ifdef QT_NO_MENU
2526 Q_UNUSED(position);
2527#else
2528 Q_Q(QFileDialog);
2529 QAbstractItemView *view = 0;
2530 if (q->viewMode() == QFileDialog::Detail)
2531 view = qFileDialogUi->treeView;
2532 else
2533 view = qFileDialogUi->listView;
2534 QModelIndex index = view->indexAt(position);
2535 index = mapToSource(index.sibling(index.row(), 0));
2536
2537 QMenu menu(view);
2538 if (index.isValid()) {
2539 // file context menu
2540 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
2541 renameAction->setEnabled(p & QFile::WriteUser);
2542 menu.addAction(renameAction);
2543 deleteAction->setEnabled(p & QFile::WriteUser);
2544 menu.addAction(deleteAction);
2545 menu.addSeparator();
2546 }
2547 menu.addAction(showHiddenAction);
2548 if (qFileDialogUi->newFolderButton->isVisible()) {
2549 newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
2550 menu.addAction(newFolderAction);
2551 }
2552 menu.exec(view->viewport()->mapToGlobal(position));
2553#endif // QT_NO_MENU
2554}
2555
2556/*!
2557 \internal
2558*/
2559void QFileDialogPrivate::_q_renameCurrent()
2560{
2561 Q_Q(QFileDialog);
2562 QModelIndex index = qFileDialogUi->listView->currentIndex();
2563 index = index.sibling(index.row(), 0);
2564 if (q->viewMode() == QFileDialog::List)
2565 qFileDialogUi->listView->edit(index);
2566 else
2567 qFileDialogUi->treeView->edit(index);
2568}
2569
2570bool QFileDialogPrivate::removeDirectory(const QString &path)
2571{
2572 QModelIndex modelIndex = model->index(path);
2573 return model->remove(modelIndex);
2574}
2575
2576/*!
2577 \internal
2578
2579 Deletes the currently selected item in the dialog.
2580*/
2581void QFileDialogPrivate::_q_deleteCurrent()
2582{
2583 if (model->isReadOnly())
2584 return;
2585
2586 QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
2587 for (int i = list.count() - 1; i >= 0; --i) {
2588 QModelIndex index = list.at(i);
2589 if (index == qFileDialogUi->listView->rootIndex())
2590 continue;
2591
2592 index = mapToSource(index.sibling(index.row(), 0));
2593 if (!index.isValid())
2594 continue;
2595
2596 QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
2597 QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
2598 bool isDir = model->isDir(index);
2599
2600 QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
2601#ifndef QT_NO_MESSAGEBOX
2602 Q_Q(QFileDialog);
2603 if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), q_func()->windowTitle(),
2604 QFileDialog::tr("'%1' is write protected.\nDo you want to delete it anyway?")
2605 .arg(fileName),
2606 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
2607 return;
2608 else if (QMessageBox::warning(q_func(), q_func()->windowTitle(),
2609 QFileDialog::tr("Are sure you want to delete '%1'?")
2610 .arg(fileName),
2611 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
2612 return;
2613
2614#else
2615 if (!(p & QFile::WriteUser))
2616 return;
2617#endif // QT_NO_MESSAGEBOX
2618
2619 // the event loop has run, we can NOT reuse index because the model might have removed it.
2620 if (isDir) {
2621 if (!removeDirectory(filePath)) {
2622#ifndef QT_NO_MESSAGEBOX
2623 QMessageBox::warning(q, q->windowTitle(),
2624 QFileDialog::tr("Could not delete directory."));
2625#endif
2626 }
2627 } else {
2628 model->remove(index);
2629 }
2630 }
2631}
2632
2633void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
2634{
2635 if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1String("\\"))) {
2636 qFileDialogUi->listView->selectionModel()->clearSelection();
2637 return;
2638 }
2639
2640 QStringList multipleFiles = typedFiles();
2641 if (multipleFiles.count() > 0) {
2642 QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
2643 QModelIndexList newFiles;
2644 for (int i = 0; i < multipleFiles.count(); ++i) {
2645 QModelIndex idx = model->index(multipleFiles.at(i));
2646 if (oldFiles.contains(idx))
2647 oldFiles.removeAll(idx);
2648 else
2649 newFiles.append(idx);
2650 }
2651 for (int i = 0; i < newFiles.count(); ++i)
2652 select(newFiles.at(i));
2653 if (lineEdit()->hasFocus())
2654 for (int i = 0; i < oldFiles.count(); ++i)
2655 qFileDialogUi->listView->selectionModel()->select(oldFiles.at(i),
2656 QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
2657 }
2658}
2659
2660/*!
2661 \internal
2662*/
2663void QFileDialogPrivate::_q_updateOkButton()
2664{
2665 Q_Q(QFileDialog);
2666 QPushButton *button = qFileDialogUi->buttonBox->button((acceptMode == QFileDialog::AcceptOpen)
2667 ? QDialogButtonBox::Open : QDialogButtonBox::Save);
2668 if (!button)
2669 return;
2670
2671 bool enableButton = true;
2672 bool isOpenDirectory = false;
2673
2674 QStringList files = q->selectedFiles();
2675 QString lineEditText = lineEdit()->text();
2676
2677 if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1String("\\"))) {
2678 button->setEnabled(true);
2679 if (acceptMode == QFileDialog::AcceptSave)
2680 button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
2681 return;
2682 }
2683
2684 if (files.isEmpty()) {
2685 enableButton = false;
2686 } else if (lineEditText == QLatin1String("..")) {
2687 isOpenDirectory = true;
2688 } else {
2689 switch (fileMode) {
2690 case QFileDialog::DirectoryOnly:
2691 case QFileDialog::Directory: {
2692 QString fn = files.first();
2693 QModelIndex idx = model->index(fn);
2694 if (!idx.isValid())
2695 idx = model->index(getEnvironmentVariable(fn));
2696 if (!idx.isValid() || !model->isDir(idx))
2697 enableButton = false;
2698 break;
2699 }
2700 case QFileDialog::AnyFile: {
2701 QString fn = files.first();
2702 QFileInfo info(fn);
2703 QModelIndex idx = model->index(fn);
2704 QString fileDir;
2705 QString fileName;
2706 if (info.isDir()) {
2707 fileDir = info.canonicalFilePath();
2708 } else {
2709 fileDir = fn.mid(0, fn.lastIndexOf(QLatin1Char('/')));
2710 fileName = fn.mid(fileDir.length() + 1);
2711 }
2712 if (lineEditText.contains(QLatin1String(".."))) {
2713 fileDir = info.canonicalFilePath();
2714 fileName = info.fileName();
2715 }
2716
2717 if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
2718 enableButton = false;
2719 break;
2720 }
2721 if (idx.isValid() && model->isDir(idx)) {
2722 isOpenDirectory = true;
2723 enableButton = true;
2724 break;
2725 }
2726 if (!idx.isValid()) {
2727 int maxLength = maxNameLength(fileDir);
2728 enableButton = maxLength < 0 || fileName.length() <= maxLength;
2729 }
2730 break;
2731 }
2732 case QFileDialog::ExistingFile:
2733 case QFileDialog::ExistingFiles:
2734 for (int i = 0; i < files.count(); ++i) {
2735 QModelIndex idx = model->index(files.at(i));
2736 if (!idx.isValid())
2737 idx = model->index(getEnvironmentVariable(files.at(i)));
2738 if (!idx.isValid()) {
2739 enableButton = false;
2740 break;
2741 }
2742 if (idx.isValid() && model->isDir(idx)) {
2743 isOpenDirectory = true;
2744 break;
2745 }
2746 }
2747 break;
2748 default:
2749 break;
2750 }
2751 }
2752
2753 button->setEnabled(enableButton);
2754 if (acceptMode == QFileDialog::AcceptSave)
2755 button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
2756}
2757
2758/*!
2759 \internal
2760*/
2761void QFileDialogPrivate::_q_currentChanged(const QModelIndex &index)
2762{
2763 _q_updateOkButton();
2764 emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
2765}
2766
2767/*!
2768 \internal
2769
2770 This is called when the user double clicks on a file with the corresponding
2771 model item \a index.
2772*/
2773void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index)
2774{
2775 Q_Q(QFileDialog);
2776 // My Computer or a directory
2777 QModelIndex sourceIndex = mapToSource(index);
2778 QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
2779 if (path.isEmpty() || model->isDir(sourceIndex)) {
2780 q->setDirectory(path);
2781 emit q->directoryEntered(path);
2782 if (fileMode == QFileDialog::Directory
2783 || fileMode == QFileDialog::DirectoryOnly) {
2784 // ### find out why you have to do both of these.
2785 lineEdit()->setText(QString());
2786 lineEdit()->clear();
2787 }
2788 } else {
2789 q->accept();
2790 }
2791}
2792
2793/*!
2794 \internal
2795
2796 Changes the file dialog's current directory to the one specified
2797 by \a path.
2798*/
2799void QFileDialogPrivate::_q_goToDirectory(const QString &path)
2800{
2801 #ifndef QT_NO_MESSAGEBOX
2802 Q_Q(QFileDialog);
2803#endif
2804 QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
2805 qFileDialogUi->lookInCombo->modelColumn(),
2806 qFileDialogUi->lookInCombo->rootModelIndex());
2807 QString path2 = path;
2808 if (!index.isValid())
2809 index = mapFromSource(model->index(getEnvironmentVariable(path)));
2810 else {
2811 path2 = index.data(UrlRole).toUrl().toLocalFile();
2812 index = mapFromSource(model->index(path2));
2813 }
2814 QDir dir(path2);
2815 if (!dir.exists())
2816 dir = getEnvironmentVariable(path2);
2817
2818 if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
2819 _q_enterDirectory(index);
2820#ifndef QT_NO_MESSAGEBOX
2821 } else {
2822 QString message = QFileDialog::tr("%1\nDirectory not found.\nPlease verify the "
2823 "correct directory name was given.");
2824 QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
2825#endif // QT_NO_MESSAGEBOX
2826 }
2827}
2828
2829const char *qt_file_dialog_filter_reg_exp =
2830 "^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
2831
2832// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
2833QStringList qt_clean_filter_list(const QString &filter)
2834{
2835 QRegExp regexp(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
2836 QString f = filter;
2837 int i = regexp.indexIn(f);
2838 if (i >= 0)
2839 f = regexp.cap(2);
2840 return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
2841}
2842
2843/*!
2844 \internal
2845
2846 Sets the current name filter to be nameFilter and
2847 update the qFileDialogUi->fileNameEdit when in AcceptSave mode with the new extension.
2848*/
2849void QFileDialogPrivate::_q_useNameFilter(int index)
2850{
2851 if (index == nameFilters.size()) {
2852 QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
2853 nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
2854 }
2855
2856 QString nameFilter = nameFilters.at(index);
2857 QStringList newNameFilters = qt_clean_filter_list(nameFilter);
2858 if (acceptMode == QFileDialog::AcceptSave) {
2859 QString newNameFilterExtension;
2860 if (newNameFilters.count() > 0)
2861 newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
2862
2863 QString fileName = lineEdit()->text();
2864 const QString fileNameExtension = QFileInfo(fileName).suffix();
2865 if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
2866 const int fileNameExtensionLength = fileNameExtension.count();
2867 fileName.replace(fileName.count() - fileNameExtensionLength,
2868 fileNameExtensionLength, newNameFilterExtension);
2869 lineEdit()->setText(fileName);
2870 }
2871 }
2872
2873 model->setNameFilters(newNameFilters);
2874}
2875
2876/*!
2877 \internal
2878
2879 This is called when the model index corresponding to the current file is changed
2880 from \a index to \a current.
2881*/
2882void QFileDialogPrivate::_q_selectionChanged()
2883{
2884 QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
2885 bool stripDirs = (fileMode != QFileDialog::DirectoryOnly && fileMode != QFileDialog::Directory);
2886
2887 QStringList allFiles;
2888 for (int i = 0; i < indexes.count(); ++i) {
2889 if (stripDirs && model->isDir(mapToSource(indexes.at(i))))
2890 continue;
2891 allFiles.append(indexes.at(i).data().toString());
2892 }
2893 if (allFiles.count() > 1)
2894 for (int i = 0; i < allFiles.count(); ++i) {
2895 allFiles.replace(i, QString(QLatin1Char('"') + allFiles.at(i) + QLatin1Char('"')));
2896 }
2897
2898 QString finalFiles = allFiles.join(QLatin1String(" "));
2899 if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
2900 lineEdit()->setText(finalFiles);
2901 else
2902 _q_updateOkButton();
2903}
2904
2905/*!
2906 \internal
2907
2908 Includes hidden files and directories in the items displayed in the dialog.
2909*/
2910void QFileDialogPrivate::_q_showHidden()
2911{
2912 Q_Q(QFileDialog);
2913 QDir::Filters dirFilters = q->filter();
2914 if (showHiddenAction->isChecked())
2915 dirFilters |= QDir::Hidden;
2916 else
2917 dirFilters &= ~QDir::Hidden;
2918 q->setFilter(dirFilters);
2919}
2920
2921/*!
2922 \internal
2923
2924 When parent is root and rows have been inserted when none was there before
2925 then select the first one.
2926*/
2927void QFileDialogPrivate::_q_rowsInserted(const QModelIndex &parent)
2928{
2929 if (!qFileDialogUi->treeView
2930 || parent != qFileDialogUi->treeView->rootIndex()
2931 || !qFileDialogUi->treeView->selectionModel()
2932 || qFileDialogUi->treeView->selectionModel()->hasSelection()
2933 || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
2934 return;
2935}
2936
2937void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldName, const QString newName)
2938{
2939 if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
2940 if (path == rootPath() && lineEdit()->text() == oldName)
2941 lineEdit()->setText(newName);
2942 }
2943}
2944
2945/*!
2946 \internal
2947
2948 For the list and tree view watch keys to goto parent and back in the history
2949
2950 returns true if handled
2951*/
2952bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
2953
2954 Q_Q(QFileDialog);
2955 switch (event->key()) {
2956 case Qt::Key_Backspace:
2957 _q_navigateToParent();
2958 return true;
2959 case Qt::Key_Back:
2960#ifdef QT_KEYPAD_NAVIGATION
2961 if (QApplication::keypadNavigationEnabled())
2962 return false;
2963#endif
2964 case Qt::Key_Left:
2965 if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
2966 _q_navigateBackward();
2967 return true;
2968 }
2969 break;
2970 case Qt::Key_Escape:
2971 q->hide();
2972 return true;
2973 default:
2974 break;
2975 }
2976 return false;
2977}
2978
2979QString QFileDialogPrivate::getEnvironmentVariable(const QString &string)
2980{
2981#ifdef Q_OS_UNIX
2982 if (string.size() > 1 && string.startsWith(QLatin1Char('$'))) {
2983 return QString::fromLocal8Bit(getenv(string.mid(1).toLatin1().constData()));
2984 }
2985#else
2986 if (string.size() > 2 && string.startsWith(QLatin1Char('%')) && string.endsWith(QLatin1Char('%'))) {
2987 return QString::fromLocal8Bit(qgetenv(string.mid(1, string.size() - 2).toLatin1().constData()));
2988 }
2989#endif
2990 return string;
2991}
2992
2993void QFileDialogComboBox::init(QFileDialogPrivate *d_pointer) {
2994 d_ptr = d_pointer;
2995 urlModel = new QUrlModel(this);
2996 urlModel->showFullPath = true;
2997 urlModel->setFileSystemModel(d_ptr->model);
2998 setModel(urlModel);
2999}
3000
3001void QFileDialogComboBox::showPopup()
3002{
3003 if (model()->rowCount() > 1)
3004 QComboBox::showPopup();
3005
3006 urlModel->setUrls(QList<QUrl>());
3007 QList<QUrl> list;
3008 QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
3009 while (idx.isValid()) {
3010 QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
3011 if (url.isValid())
3012 list.append(url);
3013 idx = idx.parent();
3014 }
3015 // add "my computer"
3016 list.append(QUrl::fromLocalFile(QLatin1String("")));
3017 urlModel->addUrls(list, 0);
3018 idx = model()->index(model()->rowCount() - 1, 0);
3019
3020 // append history
3021 QList<QUrl> urls;
3022 for (int i = 0; i < m_history.count(); ++i) {
3023 QUrl path = QUrl::fromLocalFile(m_history.at(i));
3024 if (!urls.contains(path))
3025 urls.prepend(path);
3026 }
3027 if (urls.count() > 0) {
3028 model()->insertRow(model()->rowCount());
3029 idx = model()->index(model()->rowCount()-1, 0);
3030 // ### TODO maybe add a horizontal line before this
3031 model()->setData(idx, QFileDialog::tr("Recent Places"));
3032 QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
3033 if (m) {
3034 Qt::ItemFlags flags = m->flags(idx);
3035 flags &= ~Qt::ItemIsEnabled;
3036 m->item(idx.row(), idx.column())->setFlags(flags);
3037 }
3038 urlModel->addUrls(urls, -1, false);
3039 }
3040 setCurrentIndex(0);
3041
3042 QComboBox::showPopup();
3043}
3044
3045// Exact same as QComboBox::paintEvent(), except we elide the text.
3046void QFileDialogComboBox::paintEvent(QPaintEvent *)
3047{
3048 QStylePainter painter(this);
3049 painter.setPen(palette().color(QPalette::Text));
3050
3051 // draw the combobox frame, focusrect and selected etc.
3052 QStyleOptionComboBox opt;
3053 initStyleOption(&opt);
3054
3055 QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
3056 QStyle::SC_ComboBoxEditField, this);
3057 int size = editRect.width() - opt.iconSize.width() - 4;
3058 opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
3059 painter.drawComplexControl(QStyle::CC_ComboBox, opt);
3060
3061 // draw the icon and text
3062 painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
3063}
3064
3065QFileDialogListView::QFileDialogListView(QWidget *parent) : QListView(parent)
3066{
3067}
3068
3069void QFileDialogListView::init(QFileDialogPrivate *d_pointer)
3070{
3071 d_ptr = d_pointer;
3072 setSelectionBehavior(QAbstractItemView::SelectRows);
3073 setWrapping(true);
3074 setResizeMode(QListView::Adjust);
3075 setEditTriggers(QAbstractItemView::EditKeyPressed);
3076 setContextMenuPolicy(Qt::CustomContextMenu);
3077#ifndef QT_NO_DRAGANDDROP
3078 setDragDropMode(QAbstractItemView::InternalMove);
3079#endif
3080}
3081
3082QSize QFileDialogListView::sizeHint() const
3083{
3084 int height = qMax(10, sizeHintForRow(0));
3085 return QSize(QListView::sizeHint().width() * 2, height * 30);
3086}
3087
3088void QFileDialogListView::keyPressEvent(QKeyEvent *e)
3089{
3090 if (!d_ptr->itemViewKeyboardEvent(e)) {
3091 QListView::keyPressEvent(e);
3092 }
3093 e->accept();
3094}
3095
3096QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent)
3097{
3098}
3099
3100void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer)
3101{
3102 d_ptr = d_pointer;
3103 setSelectionBehavior(QAbstractItemView::SelectRows);
3104 setRootIsDecorated(false);
3105 setItemsExpandable(false);
3106 setSortingEnabled(true);
3107 header()->setSortIndicator(0, Qt::AscendingOrder);
3108 header()->setStretchLastSection(false);
3109 setTextElideMode(Qt::ElideMiddle);
3110 setEditTriggers(QAbstractItemView::EditKeyPressed);
3111 setContextMenuPolicy(Qt::CustomContextMenu);
3112#ifndef QT_NO_DRAGANDDROP
3113 setDragDropMode(QAbstractItemView::InternalMove);
3114#endif
3115}
3116
3117void QFileDialogTreeView::keyPressEvent(QKeyEvent *e)
3118{
3119 if (!d_ptr->itemViewKeyboardEvent(e)) {
3120 QTreeView::keyPressEvent(e);
3121 }
3122 e->accept();
3123}
3124
3125QSize QFileDialogTreeView::sizeHint() const
3126{
3127 int height = qMax(10, sizeHintForRow(0));
3128 QSize sizeHint = header()->sizeHint();
3129 return QSize(sizeHint.width() * 4, height * 30);
3130}
3131
3132/*!
3133 // FIXME: this is a hack to avoid propagating key press events
3134 // to the dialog and from there to the "Ok" button
3135*/
3136void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
3137{
3138 int key = e->key();
3139 QLineEdit::keyPressEvent(e);
3140 if (key != Qt::Key_Escape)
3141 e->accept();
3142 if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) {
3143 e->accept();
3144 hide();
3145 d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason);
3146 }
3147}
3148
3149#ifndef QT_NO_COMPLETER
3150
3151QString QFSCompletor::pathFromIndex(const QModelIndex &index) const
3152{
3153 const QFileSystemModel *dirModel;
3154 if (proxyModel)
3155 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
3156 else
3157 dirModel = sourceModel;
3158 QString currentLocation = dirModel->rootPath();
3159 QString path = index.data(QFileSystemModel::FilePathRole).toString();
3160 if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
3161 return path.mid(currentLocation.length() + 1);
3162 }
3163 return index.data(QFileSystemModel::FilePathRole).toString();
3164}
3165
3166QStringList QFSCompletor::splitPath(const QString &path) const
3167{
3168 if (path.isEmpty())
3169 return QStringList(completionPrefix());
3170
3171 QString pathCopy = QDir::toNativeSeparators(path);
3172 QString sep = QDir::separator();
3173#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
3174 if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
3175 return QStringList(pathCopy);
3176 QString doubleSlash(QLatin1String("\\\\"));
3177 if (pathCopy.startsWith(doubleSlash))
3178 pathCopy = pathCopy.mid(2);
3179 else
3180 doubleSlash.clear();
3181#endif
3182
3183 QRegExp re(QLatin1String("[") + QRegExp::escape(sep) + QLatin1String("]"));
3184
3185#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
3186 QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
3187 if (!doubleSlash.isEmpty() && !parts.isEmpty())
3188 parts[0].prepend(doubleSlash);
3189 if (pathCopy.endsWith(sep))
3190 parts.append(QString());
3191#else
3192 QStringList parts = pathCopy.split(re);
3193 if (path[0] == sep[0]) // read the "/" at the beginning as the split removed it
3194 parts[0] = sep[0];
3195#endif
3196
3197#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
3198 bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
3199#else
3200 bool startsFromRoot = path[0] == sep[0];
3201#endif
3202 if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) {
3203 const QFileSystemModel *dirModel;
3204 if (proxyModel)
3205 dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
3206 else
3207 dirModel = sourceModel;
3208 QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
3209 if (currentLocation.contains(sep) && path != currentLocation) {
3210 QStringList currentLocationList = splitPath(currentLocation);
3211 while (!currentLocationList.isEmpty()
3212 && parts.count() > 0
3213 && parts.at(0) == QLatin1String("..")) {
3214 parts.removeFirst();
3215 currentLocationList.removeLast();
3216 }
3217 if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty())
3218 currentLocationList.removeLast();
3219 return currentLocationList + parts;
3220 }
3221 }
3222 return parts;
3223}
3224
3225#endif // QT_NO_COMPLETER
3226
3227#ifdef QT3_SUPPORT
3228/*!
3229 Use selectedFiles() instead.
3230
3231 \oldcode
3232 QString selected = dialog->selectedFile();
3233 \newcode
3234 QStringList files = dialog->selectedFiles();
3235 QString selected;
3236 if (!files.isEmpty())
3237 selected = files[0];
3238 \endcode
3239*/
3240QString QFileDialog::selectedFile() const
3241{
3242 QStringList files = selectedFiles();
3243 return files.size() ? files.at(0) : QString();
3244}
3245
3246/*!
3247 \typedef QFileDialog::Mode
3248
3249 Use QFileDialog::FileMode instead.
3250*/
3251
3252/*!
3253 \fn void QFileDialog::setMode(FileMode m)
3254
3255 Use setFileMode() instead.
3256*/
3257
3258/*!
3259 \fn FileMode QFileDialog::mode() const
3260
3261 Use fileMode() instead.
3262*/
3263
3264/*!
3265 \fn void QFileDialog::setDir(const QString &directory)
3266
3267 Use setDirectory() instead.
3268*/
3269
3270/*!
3271 \fn void QFileDialog::setDir( const QDir &directory )
3272
3273 Use setDirectory() instead.
3274*/
3275
3276/*!
3277 \fn QStringList QFileDialog::getOpenFileNames(const QString &filter,
3278 const QString &dir, QWidget *parent, const char* name,
3279 const QString &caption, QString *selectedFilter, bool resolveSymlinks)
3280
3281 Use the getOpenFileNames() overload that takes \a parent as the first
3282 argument instead.
3283*/
3284
3285/*!
3286 \fn QString QFileDialog::getOpenFileName(const QString &dir,
3287 const QString &filter, QWidget *parent = 0, const char *name,
3288 const QString &caption, QString *selectedFilter, bool resolveSymlinks)
3289
3290 Use the getOpenFileName() overload that takes \a parent as the first
3291 argument instead.
3292*/
3293
3294/*!
3295 \fn QString QFileDialog::getSaveFileName(const QString &dir,
3296 const QString &filter, QWidget *parent, const char *name,
3297 const QString &caption, QString *selectedFilter, bool resolveSymlinks)
3298
3299 Use the getSaveFileName() overload that takes \a parent as the first
3300 argument instead.
3301*/
3302
3303/*!
3304 \fn QString QFileDialog::getExistingDirectory(const QString &dir,
3305 QWidget *parent, const char *name, const QString &caption,
3306 bool dirOnly, bool resolveSymlinks)
3307
3308 Use the getExistingDirectory() overload that takes \a parent as
3309 the first argument instead.
3310*/
3311
3312#endif // QT3_SUPPORT
3313
3314QT_END_NAMESPACE
3315
3316#include "moc_qfiledialog.cpp"
3317
3318#endif // QT_NO_FILEDIALOG
Note: See TracBrowser for help on using the repository browser.