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

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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