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