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