src/gui/dialogs/qfiledialog.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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)
       
    67 extern bool qt_priv_ptr_valid;
       
    68 #endif
       
    69 #endif
       
    70 
       
    71 QT_BEGIN_NAMESPACE
       
    72 
       
    73 Q_GLOBAL_STATIC(QString, lastVisitedDir)
       
    74 
       
    75 /*
       
    76     \internal
       
    77 
       
    78     Exported hooks that can be used to customize the static functions.
       
    79  */
       
    80 typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
       
    81 Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0;
       
    82 
       
    83 typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
       
    84 Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0;
       
    85 
       
    86 typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
       
    87 Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0;
       
    88 
       
    89 typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
       
    90 Q_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)
       
   296 bool Q_GUI_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API
       
   297 #endif
       
   298 
       
   299 QT_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
       
   308 QT_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 */
       
   315 QFileDialog::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 */
       
   330 QFileDialog::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 */
       
   344 QFileDialog::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 */
       
   358 QFileDialog::~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 */
       
   383 void 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 */
       
   393 QList<QUrl> QFileDialog::sidebarUrls() const
       
   394 {
       
   395     Q_D(const QFileDialog);
       
   396     return d->qFileDialogUi->sidebar->urls();
       
   397 }
       
   398 
       
   399 static const qint32 QFileDialogMagic = 0xbe;
       
   400 
       
   401 const 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 */
       
   411 QByteArray 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 */
       
   438 bool 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 */
       
   490 void 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 
       
   500 QFileDialogPrivate::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 
       
   528 QFileDialogPrivate::~QFileDialogPrivate()
       
   529 {
       
   530 }
       
   531 
       
   532 void 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 
       
   548 void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
       
   549 {
       
   550     *lastVisitedDir() = dir;
       
   551 }
       
   552 
       
   553 void 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 
       
   588 void 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 
       
   596 bool 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 */
       
   618 void 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 */
       
   633 bool 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 */
       
   652 void 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 
       
   674 QFileDialog::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 */
       
   691 void QFileDialog::open(QObject *receiver, const char *member)
       
   692 {
       
   693     Q_D(QFileDialog);
       
   694     const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(const QStringList&))
       
   695                                                        : SIGNAL(fileSelected(const 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 */
       
   708 void 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 */
       
   739 void 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 */
       
   757 void 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_COMPLETER
       
   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 */
       
   794 QDir 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 */
       
   805 void 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 #ifdef Q_OS_WIN
       
   834                 //On Windows 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   */
       
   852 QStringList 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 
       
   871 QStringList 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 */
       
   904 QStringList 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 */
       
   927 QStringList 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 */
       
   960 void QFileDialog::setNameFilter(const QString &filter)
       
   961 {
       
   962     setNameFilters(qt_make_filter_list(filter));
       
   963 }
       
   964 
       
   965 /*!
       
   966   \obsolete
       
   967 
       
   968   Use setNameFilter() instead.
       
   969 */
       
   970 void 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 */
       
   987 void QFileDialog::setNameFilterDetailsVisible(bool enabled)
       
   988 {
       
   989     setOption(HideNameFilterDetails, !enabled);
       
   990 }
       
   991 
       
   992 bool 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 */
       
  1005 void 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 */
       
  1046 void 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 */
       
  1057 QStringList QFileDialog::nameFilters() const
       
  1058 {
       
  1059     return d_func()->nameFilters;
       
  1060 }
       
  1061 
       
  1062 /*!
       
  1063     \obsolete
       
  1064 
       
  1065     Use nameFilters() instead.
       
  1066 */
       
  1067 
       
  1068 QStringList 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 */
       
  1081 void 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 
       
  1102 void 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 */
       
  1114 QString 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 */
       
  1128 QString 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 */
       
  1140 QDir::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 
       
  1155 void 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 */
       
  1176 void 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 
       
  1185 QFileDialog::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 */
       
  1206 void 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 
       
  1254 QFileDialog::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 */
       
  1270 void 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 */
       
  1293 QModelIndex QFileDialogPrivate::rootIndex() const {
       
  1294     return mapToSource(qFileDialogUi->listView->rootIndex());
       
  1295 }
       
  1296 
       
  1297 QAbstractItemView *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 
       
  1305 QLineEdit *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 */
       
  1312 void 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 */
       
  1322 QModelIndex 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 
       
  1332 QFileDialog::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 */
       
  1348 void QFileDialog::setReadOnly(bool enabled)
       
  1349 {
       
  1350     setOption(ReadOnly, enabled);
       
  1351 }
       
  1352 
       
  1353 bool 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 */
       
  1369 void QFileDialog::setResolveSymlinks(bool enabled)
       
  1370 {
       
  1371     setOption(DontResolveSymlinks, !enabled);
       
  1372 }
       
  1373 
       
  1374 bool 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 */
       
  1388 void QFileDialog::setConfirmOverwrite(bool enabled)
       
  1389 {
       
  1390     setOption(DontConfirmOverwrite, !enabled);
       
  1391 }
       
  1392 
       
  1393 bool 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 */
       
  1407 void QFileDialog::setDefaultSuffix(const QString &suffix)
       
  1408 {
       
  1409     Q_D(QFileDialog);
       
  1410     d->defaultSuffix = suffix;
       
  1411 }
       
  1412 
       
  1413 QString 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 */
       
  1423 void QFileDialog::setHistory(const QStringList &paths)
       
  1424 {
       
  1425     Q_D(QFileDialog);
       
  1426     d->qFileDialogUi->lookInCombo->setHistory(paths);
       
  1427 }
       
  1428 
       
  1429 void 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 */
       
  1445 QStringList 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 */
       
  1471 void 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 */
       
  1481 QAbstractItemDelegate *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 */
       
  1490 void 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 */
       
  1501 QFileIconProvider *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 */
       
  1510 void 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 */
       
  1545 QString 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)
       
  1576 extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
       
  1577                                          QString *initialDirectory,
       
  1578                                          QString *selectedFilter);
       
  1579 
       
  1580 extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
       
  1581                                          QString *initialDirectory,
       
  1582                                          QString *selectedFilter);
       
  1583 
       
  1584 extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
       
  1585                                               QString *initialDirectory,
       
  1586                                               QString *selectedFilter);
       
  1587 
       
  1588 extern 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 */
       
  1638 QString 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 */
       
  1722 QStringList 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 */
       
  1808 QString 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 */
       
  1885 QString 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 
       
  1917 inline 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  */
       
  1932 QString 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  */
       
  1952 QString 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 */
       
  1965 void 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 */
       
  1983 void 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 */
       
  2092 void 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 */
       
  2137 void 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(const QString &, const QString &, const QString &)), q, SLOT(_q_fileRenamed(const QString &, const QString &, const QString &)));
       
  2149     QFileDialog::connect(model, SIGNAL(rootPathChanged(const QString &)),
       
  2150             q, SLOT(_q_pathChanged(const QString &)));
       
  2151     QFileDialog::connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
       
  2152             q, SLOT(_q_rowsInserted(const 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(const QUrl &)),
       
  2163                          q, SLOT(_q_goToUrl(const 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_COMPLETER
       
  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_COMPLETER
       
  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(const QString &)),
       
  2198                      q, SIGNAL(filterSelected(const 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(const QItemSelection &, const 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 
       
  2263 void 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 */
       
  2283 void 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(const QModelIndex &, int, int)),
       
  2293             this, SLOT(_q_rowsInserted(const QModelIndex &)));
       
  2294     } else {
       
  2295         disconnect(d->model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
       
  2296             this, SLOT(_q_rowsInserted(const 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_COMPLETER
       
  2306         d->completer->setModel(d->proxyModel);
       
  2307         d->completer->proxyModel = d->proxyModel;
       
  2308 #endif
       
  2309         connect(d->proxyModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
       
  2310             this, SLOT(_q_rowsInserted(const 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_COMPLETER
       
  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(const QModelIndex &, int, int)),
       
  2321             this, SLOT(_q_rowsInserted(const 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(const QItemSelection &, const 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 */
       
  2341 QAbstractProxyModel *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 */
       
  2353 void 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 */
       
  2399 void 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 
       
  2440 void 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 */
       
  2451 void 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 */
       
  2475 void 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 */
       
  2490 void 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 */
       
  2506 void 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 */
       
  2526 void 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 
       
  2553 void 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 
       
  2563 void 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 */
       
  2578 void 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 */
       
  2614 void 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 
       
  2625 bool 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 */
       
  2636 void 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 
       
  2688 void 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 */
       
  2718 void 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 */
       
  2816 void 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 */
       
  2828 void 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 */
       
  2854 void 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)"
       
  2885 QStringList 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 */
       
  2901 void 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 */
       
  2934 void 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 */
       
  2962 void 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 */
       
  2979 void 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 
       
  2989 void 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 */
       
  3004 bool 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 #ifdef QT_KEYPAD_NAVIGATION
       
  3026     case Qt::Key_Down:
       
  3027     case Qt::Key_Up:
       
  3028         return (QApplication::navigationMode() != Qt::NavigationModeKeypadTabOrder
       
  3029                 && QApplication::navigationMode() != Qt::NavigationModeKeypadDirectional);
       
  3030 #endif
       
  3031     default:
       
  3032         break;
       
  3033     }
       
  3034     return false;
       
  3035 }
       
  3036 
       
  3037 QString QFileDialogPrivate::getEnvironmentVariable(const QString &string)
       
  3038 {
       
  3039 #ifdef Q_OS_UNIX
       
  3040     if (string.size() > 1 && string.startsWith(QLatin1Char('$'))) {
       
  3041         return QString::fromLocal8Bit(getenv(string.mid(1).toLatin1().constData()));
       
  3042     }
       
  3043 #else
       
  3044     if (string.size() > 2 && string.startsWith(QLatin1Char('%')) && string.endsWith(QLatin1Char('%'))) {
       
  3045         return QString::fromLocal8Bit(qgetenv(string.mid(1, string.size() - 2).toLatin1().constData()));
       
  3046     }
       
  3047 #endif
       
  3048     return string;
       
  3049 }
       
  3050 
       
  3051 void QFileDialogComboBox::init(QFileDialogPrivate *d_pointer) {
       
  3052     d_ptr = d_pointer;
       
  3053     urlModel = new QUrlModel(this);
       
  3054     urlModel->showFullPath = true;
       
  3055     urlModel->setFileSystemModel(d_ptr->model);
       
  3056     setModel(urlModel);
       
  3057 }
       
  3058 
       
  3059 void QFileDialogComboBox::showPopup()
       
  3060 {
       
  3061     if (model()->rowCount() > 1)
       
  3062         QComboBox::showPopup();
       
  3063 
       
  3064     urlModel->setUrls(QList<QUrl>());
       
  3065     QList<QUrl> list;
       
  3066     QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
       
  3067     while (idx.isValid()) {
       
  3068         QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
       
  3069         if (url.isValid())
       
  3070             list.append(url);
       
  3071         idx = idx.parent();
       
  3072     }
       
  3073     // add "my computer"
       
  3074     list.append(QUrl::fromLocalFile(QLatin1String("")));
       
  3075     urlModel->addUrls(list, 0);
       
  3076     idx = model()->index(model()->rowCount() - 1, 0);
       
  3077 
       
  3078     // append history
       
  3079     QList<QUrl> urls;
       
  3080     for (int i = 0; i < m_history.count(); ++i) {
       
  3081         QUrl path = QUrl::fromLocalFile(m_history.at(i));
       
  3082         if (!urls.contains(path))
       
  3083             urls.prepend(path);
       
  3084     }
       
  3085     if (urls.count() > 0) {
       
  3086         model()->insertRow(model()->rowCount());
       
  3087         idx = model()->index(model()->rowCount()-1, 0);
       
  3088         // ### TODO maybe add a horizontal line before this
       
  3089         model()->setData(idx, QFileDialog::tr("Recent Places"));
       
  3090         QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
       
  3091         if (m) {
       
  3092             Qt::ItemFlags flags = m->flags(idx);
       
  3093             flags &= ~Qt::ItemIsEnabled;
       
  3094             m->item(idx.row(), idx.column())->setFlags(flags);
       
  3095         }
       
  3096         urlModel->addUrls(urls, -1, false);
       
  3097     }
       
  3098     setCurrentIndex(0);
       
  3099 
       
  3100     QComboBox::showPopup();
       
  3101 }
       
  3102 
       
  3103 // Exact same as QComboBox::paintEvent(), except we elide the text.
       
  3104 void QFileDialogComboBox::paintEvent(QPaintEvent *)
       
  3105 {
       
  3106     QStylePainter painter(this);
       
  3107     painter.setPen(palette().color(QPalette::Text));
       
  3108 
       
  3109     // draw the combobox frame, focusrect and selected etc.
       
  3110     QStyleOptionComboBox opt;
       
  3111     initStyleOption(&opt);
       
  3112 
       
  3113     QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
       
  3114                                                 QStyle::SC_ComboBoxEditField, this);
       
  3115     int size = editRect.width() - opt.iconSize.width() - 4;
       
  3116     opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
       
  3117     painter.drawComplexControl(QStyle::CC_ComboBox, opt);
       
  3118 
       
  3119     // draw the icon and text
       
  3120     painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
       
  3121 }
       
  3122 
       
  3123 QFileDialogListView::QFileDialogListView(QWidget *parent) : QListView(parent)
       
  3124 {
       
  3125 }
       
  3126 
       
  3127 void QFileDialogListView::init(QFileDialogPrivate *d_pointer)
       
  3128 {
       
  3129     d_ptr = d_pointer;
       
  3130     setSelectionBehavior(QAbstractItemView::SelectRows);
       
  3131     setWrapping(true);
       
  3132     setResizeMode(QListView::Adjust);
       
  3133     setEditTriggers(QAbstractItemView::EditKeyPressed);
       
  3134     setContextMenuPolicy(Qt::CustomContextMenu);
       
  3135 #ifndef QT_NO_DRAGANDDROP
       
  3136     setDragDropMode(QAbstractItemView::InternalMove);
       
  3137 #endif
       
  3138 }
       
  3139 
       
  3140 QSize QFileDialogListView::sizeHint() const
       
  3141 {
       
  3142     int height = qMax(10, sizeHintForRow(0));
       
  3143     return QSize(QListView::sizeHint().width() * 2, height * 30);
       
  3144 }
       
  3145 
       
  3146 void QFileDialogListView::keyPressEvent(QKeyEvent *e)
       
  3147 {
       
  3148     if (!d_ptr->itemViewKeyboardEvent(e)) {
       
  3149         QListView::keyPressEvent(e);
       
  3150     }
       
  3151 #ifdef QT_KEYPAD_NAVIGATION
       
  3152     else if ((QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder
       
  3153          || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional)
       
  3154          && !hasEditFocus()) {
       
  3155          e->ignore();
       
  3156     } else {
       
  3157         e->accept();
       
  3158     }
       
  3159 #else
       
  3160     e->accept();
       
  3161 #endif
       
  3162 }
       
  3163 
       
  3164 QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent)
       
  3165 {
       
  3166 }
       
  3167 
       
  3168 void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer)
       
  3169 {
       
  3170     d_ptr = d_pointer;
       
  3171     setSelectionBehavior(QAbstractItemView::SelectRows);
       
  3172     setRootIsDecorated(false);
       
  3173     setItemsExpandable(false);
       
  3174     setSortingEnabled(true);
       
  3175     header()->setSortIndicator(0, Qt::AscendingOrder);
       
  3176     header()->setStretchLastSection(false);
       
  3177     setTextElideMode(Qt::ElideMiddle);
       
  3178     setEditTriggers(QAbstractItemView::EditKeyPressed);
       
  3179     setContextMenuPolicy(Qt::CustomContextMenu);
       
  3180 #ifndef QT_NO_DRAGANDDROP
       
  3181     setDragDropMode(QAbstractItemView::InternalMove);
       
  3182 #endif
       
  3183 }
       
  3184 
       
  3185 void QFileDialogTreeView::keyPressEvent(QKeyEvent *e)
       
  3186 {
       
  3187     if (!d_ptr->itemViewKeyboardEvent(e)) {
       
  3188         QTreeView::keyPressEvent(e);
       
  3189     }
       
  3190     e->accept();
       
  3191 }
       
  3192 
       
  3193 QSize QFileDialogTreeView::sizeHint() const
       
  3194 {
       
  3195     int height = qMax(10, sizeHintForRow(0));
       
  3196     QSize sizeHint = header()->sizeHint();
       
  3197     return QSize(sizeHint.width() * 4, height * 30);
       
  3198 }
       
  3199 
       
  3200 /*!
       
  3201     // FIXME: this is a hack to avoid propagating key press events
       
  3202     // to the dialog and from there to the "Ok" button
       
  3203 */
       
  3204 void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
       
  3205 {
       
  3206     int key = e->key();
       
  3207     QLineEdit::keyPressEvent(e);
       
  3208     if (key != Qt::Key_Escape
       
  3209 #ifdef QT_KEYPAD_NAVIGATION
       
  3210         && QApplication::navigationMode() == Qt::NavigationModeNone
       
  3211 #endif
       
  3212         )
       
  3213         e->accept();
       
  3214     if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) {
       
  3215         e->accept();
       
  3216         hide();
       
  3217         d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason);
       
  3218     }
       
  3219 }
       
  3220 
       
  3221 #ifndef QT_NO_COMPLETER
       
  3222 
       
  3223 QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
       
  3224 {
       
  3225     const QFileSystemModel *dirModel;
       
  3226     if (proxyModel)
       
  3227         dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
       
  3228     else
       
  3229         dirModel = sourceModel;
       
  3230     QString currentLocation = dirModel->rootPath();
       
  3231     QString path = index.data(QFileSystemModel::FilePathRole).toString();
       
  3232     if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
       
  3233         return path.mid(currentLocation.length() + 1);
       
  3234     }
       
  3235     return index.data(QFileSystemModel::FilePathRole).toString();
       
  3236 }
       
  3237 
       
  3238 QStringList QFSCompleter::splitPath(const QString &path) const
       
  3239 {
       
  3240     if (path.isEmpty())
       
  3241         return QStringList(completionPrefix());
       
  3242 
       
  3243     QString pathCopy = QDir::toNativeSeparators(path);
       
  3244     QString sep = QDir::separator();
       
  3245 #if defined(Q_OS_SYMBIAN)
       
  3246     if (pathCopy == QLatin1String("\\"))
       
  3247         return QStringList(pathCopy);
       
  3248 #elif defined(Q_OS_WIN)
       
  3249     if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
       
  3250         return QStringList(pathCopy);
       
  3251     QString doubleSlash(QLatin1String("\\\\"));
       
  3252     if (pathCopy.startsWith(doubleSlash))
       
  3253         pathCopy = pathCopy.mid(2);
       
  3254     else
       
  3255         doubleSlash.clear();
       
  3256 #endif
       
  3257 
       
  3258     QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
       
  3259 
       
  3260 #if defined(Q_OS_SYMBIAN)
       
  3261     QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
       
  3262     if (pathCopy.endsWith(sep))
       
  3263         parts.append(QString());
       
  3264 #elif defined(Q_OS_WIN)
       
  3265     QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
       
  3266     if (!doubleSlash.isEmpty() && !parts.isEmpty())
       
  3267         parts[0].prepend(doubleSlash);
       
  3268     if (pathCopy.endsWith(sep))
       
  3269         parts.append(QString());
       
  3270 #else
       
  3271     QStringList parts = pathCopy.split(re);
       
  3272     if (path[0] == sep[0]) // read the "/" at the beginning as the split removed it
       
  3273         parts[0] = sep[0];
       
  3274 #endif
       
  3275 
       
  3276 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
       
  3277     bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
       
  3278 #else
       
  3279     bool startsFromRoot = path[0] == sep[0];
       
  3280 #endif
       
  3281     if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) {
       
  3282         const QFileSystemModel *dirModel;
       
  3283         if (proxyModel)
       
  3284             dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
       
  3285         else
       
  3286             dirModel = sourceModel;
       
  3287         QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
       
  3288         if (currentLocation.contains(sep) && path != currentLocation) {
       
  3289             QStringList currentLocationList = splitPath(currentLocation);
       
  3290             while (!currentLocationList.isEmpty()
       
  3291                    && parts.count() > 0
       
  3292                    && parts.at(0) == QLatin1String("..")) {
       
  3293                 parts.removeFirst();
       
  3294                 currentLocationList.removeLast();
       
  3295             }
       
  3296             if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty())
       
  3297                 currentLocationList.removeLast();
       
  3298             return currentLocationList + parts;
       
  3299         }
       
  3300     }
       
  3301     return parts;
       
  3302 }
       
  3303 
       
  3304 #endif // QT_NO_COMPLETER
       
  3305 
       
  3306 #ifdef QT3_SUPPORT
       
  3307 /*!
       
  3308     Use selectedFiles() instead.
       
  3309 
       
  3310     \oldcode
       
  3311        QString selected = dialog->selectedFile();
       
  3312     \newcode
       
  3313         QStringList files = dialog->selectedFiles();
       
  3314         QString selected;
       
  3315         if (!files.isEmpty())
       
  3316             selected = files[0];
       
  3317     \endcode
       
  3318 */
       
  3319 QString QFileDialog::selectedFile() const
       
  3320 {
       
  3321     QStringList files = selectedFiles();
       
  3322     return files.size() ? files.at(0) : QString();
       
  3323 }
       
  3324 
       
  3325 /*!
       
  3326     \typedef QFileDialog::Mode
       
  3327 
       
  3328     Use QFileDialog::FileMode instead.
       
  3329 */
       
  3330 
       
  3331 /*!
       
  3332     \fn void QFileDialog::setMode(FileMode m)
       
  3333 
       
  3334     Use setFileMode() instead.
       
  3335 */
       
  3336 
       
  3337 /*!
       
  3338     \fn FileMode QFileDialog::mode() const
       
  3339 
       
  3340     Use fileMode() instead.
       
  3341 */
       
  3342 
       
  3343 /*!
       
  3344     \fn void QFileDialog::setDir(const QString &directory)
       
  3345 
       
  3346     Use setDirectory() instead.
       
  3347 */
       
  3348 
       
  3349 /*!
       
  3350     \fn void QFileDialog::setDir( const QDir &directory )
       
  3351 
       
  3352     Use setDirectory() instead.
       
  3353 */
       
  3354 
       
  3355 /*!
       
  3356     \fn QStringList QFileDialog::getOpenFileNames(const QString &filter,
       
  3357         const QString &dir, QWidget *parent, const char* name,
       
  3358         const QString &caption, QString *selectedFilter, bool resolveSymlinks)
       
  3359 
       
  3360     Use the getOpenFileNames() overload that takes \a parent as the first
       
  3361     argument instead.
       
  3362 */
       
  3363 
       
  3364 /*!
       
  3365     \fn QString QFileDialog::getOpenFileName(const QString &dir,
       
  3366         const QString &filter, QWidget *parent = 0, const char *name,
       
  3367         const QString &caption, QString *selectedFilter, bool resolveSymlinks)
       
  3368 
       
  3369     Use the getOpenFileName() overload that takes \a parent as the first
       
  3370     argument instead.
       
  3371 */
       
  3372 
       
  3373 /*!
       
  3374     \fn QString QFileDialog::getSaveFileName(const QString &dir,
       
  3375         const QString &filter, QWidget *parent, const char *name,
       
  3376         const QString &caption, QString *selectedFilter, bool resolveSymlinks)
       
  3377 
       
  3378     Use the getSaveFileName() overload that takes \a parent as the first
       
  3379     argument instead.
       
  3380 */
       
  3381 
       
  3382 /*!
       
  3383     \fn QString QFileDialog::getExistingDirectory(const QString &dir,
       
  3384         QWidget *parent, const char *name, const QString &caption,
       
  3385         bool dirOnly, bool resolveSymlinks)
       
  3386 
       
  3387     Use the getExistingDirectory() overload that takes \a parent as
       
  3388     the first argument instead.
       
  3389 */
       
  3390 
       
  3391 #endif // QT3_SUPPORT
       
  3392 
       
  3393 QT_END_NAMESPACE
       
  3394 
       
  3395 #include "moc_qfiledialog.cpp"
       
  3396 
       
  3397 #endif // QT_NO_FILEDIALOG