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 #ifndef QFILEDIALOG_P_H
43 #define QFILEDIALOG_P_H
44
45 //
46 // W A R N I N G
47 // -------------
48 //
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #ifndef QT_NO_FILEDIALOG
57
58 #include "qfiledialog.h"
59 #include "private/qdialog_p.h"
60 #include "qplatformdefs.h"
61
62 #include "qfilesystemmodel_p.h"
63 #include <qlistview.h>
64 #include <qtreeview.h>
65 #include <qcombobox.h>
66 #include <qtoolbutton.h>
67 #include <qlabel.h>
68 #include <qevent.h>
69 #include <qlineedit.h>
70 #include <qurl.h>
71 #include <qstackedwidget.h>
72 #include <qdialogbuttonbox.h>
73 #include <qabstractproxymodel.h>
74 #include <qcompleter.h>
75 #include <qpointer.h>
76 #include <qdebug.h>
77 #include "qsidebar_p.h"
78 #include "qfscompleter_p.h"
79 #include "private/qguiplatformplugin_p.h"
80
81
82 #if defined (Q_OS_UNIX)
83 #include <unistd.h>
84 #endif
85
86 QT_BEGIN_NAMESPACE
87
88 class QFileDialogListView;
89 class QFileDialogTreeView;
90 class QFileDialogLineEdit;
91 class QGridLayout;
92 class QCompleter;
93 class QHBoxLayout;
94 class Ui_QFileDialog;
95
96
97 struct QFileDialogArgs
98 {
QFileDialogArgsQFileDialogArgs99 QFileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {}
100
101 QWidget *parent;
102 QString caption;
103 QString directory;
104 QString selection;
105 QString filter;
106 QFileDialog::FileMode mode;
107 QFileDialog::Options options;
108 };
109
110 #define UrlRole (Qt::UserRole + 1)
111
112 class Q_AUTOTEST_EXPORT QFileDialogPrivate : public QDialogPrivate
113 {
114 Q_DECLARE_PUBLIC(QFileDialog)
115
116 public:
117 QFileDialogPrivate();
118
119 void createToolButtons();
120 void createMenuActions();
121 void createWidgets();
122
123 void init(const QString &directory = QString(), const QString &nameFilter = QString(),
124 const QString &caption = QString());
125 bool itemViewKeyboardEvent(QKeyEvent *event);
126 QString getEnvironmentVariable(const QString &string);
127 static QString workingDirectory(const QString &path);
128 static QString initialSelection(const QString &path);
129 QStringList typedFiles() const;
130 QStringList addDefaultSuffixToFiles(const QStringList filesToFix) const;
131 bool removeDirectory(const QString &path);
132
133 inline QModelIndex mapToSource(const QModelIndex &index) const;
134 inline QModelIndex mapFromSource(const QModelIndex &index) const;
135 inline QModelIndex rootIndex() const;
136 inline void setRootIndex(const QModelIndex &index) const;
137 inline QModelIndex select(const QModelIndex &index) const;
138 inline QString rootPath() const;
139
140 QLineEdit *lineEdit() const;
141
maxNameLength(const QString & path)142 int maxNameLength(const QString &path) {
143 #if defined(Q_OS_UNIX)
144 return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
145 #elif defined(Q_OS_WIN)
146 #ifndef Q_OS_WINCE
147 DWORD maxLength;
148 QString drive = path.left(3);
149 if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == FALSE)
150 return -1;
151 return maxLength;
152 #else
153 Q_UNUSED(path);
154 return MAX_PATH;
155 #endif //Q_OS_WINCE
156 #else
157 Q_UNUSED(path);
158 #endif
159 return -1;
160 }
161
basename(const QString & path)162 QString basename(const QString &path) const
163 {
164 int separator = QDir::toNativeSeparators(path).lastIndexOf(QDir::separator());
165 if (separator != -1)
166 return path.mid(separator + 1);
167 return path;
168 }
169
filterForMode(QDir::Filters filters)170 QDir::Filters filterForMode(QDir::Filters filters) const
171 {
172 if (fileMode == QFileDialog::DirectoryOnly) {
173 filters |= QDir::Drives | QDir::AllDirs | QDir::Dirs;
174 filters &= ~QDir::Files;
175 } else {
176 filters |= QDir::Drives | QDir::AllDirs | QDir::Files | QDir::Dirs;
177 }
178 return filters;
179 }
180
181 QAbstractItemView *currentView() const;
182
toInternal(const QString & path)183 static inline QString toInternal(const QString &path)
184 {
185 #if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
186 QString n(path);
187 for (int i = 0; i < (int)n.length(); ++i)
188 if (n[i] == QLatin1Char('\\')) n[i] = QLatin1Char('/');
189 #if defined(Q_OS_WINCE)
190 if ((n.size() > 1) && (n.startsWith(QLatin1String("//"))))
191 n = n.mid(1);
192 #endif
193 return n;
194 #else // the compile should optimize away this
195 return path;
196 #endif
197 }
198
199 void setLastVisitedDirectory(const QString &dir);
200 void retranslateWindowTitle();
201 void retranslateStrings();
202 void emitFilesSelected(const QStringList &files);
203
204 void _q_goHome();
205 void _q_pathChanged(const QString &);
206 void _q_navigateBackward();
207 void _q_navigateForward();
208 void _q_navigateToParent();
209 void _q_createDirectory();
210 void _q_showListView();
211 void _q_showDetailsView();
212 void _q_showContextMenu(const QPoint &position);
213 void _q_renameCurrent();
214 void _q_deleteCurrent();
215 void _q_showHidden();
216 void _q_showHeader(QAction *);
217 void _q_updateOkButton();
218 void _q_currentChanged(const QModelIndex &index);
219 void _q_enterDirectory(const QModelIndex &index);
220 void _q_goToDirectory(const QString &);
221 void _q_useNameFilter(int index);
222 void _q_selectionChanged();
223 void _q_goToUrl(const QUrl &url);
224 void _q_autoCompleteFileName(const QString &);
225 void _q_rowsInserted(const QModelIndex & parent);
226 void _q_fileRenamed(const QString &path, const QString oldName, const QString newName);
227
228 // layout
229 #ifndef QT_NO_PROXYMODEL
230 QAbstractProxyModel *proxyModel;
231 #endif
232
233 // data
234 QStringList watching;
235 QFileSystemModel *model;
236
237 #ifndef QT_NO_FSCOMPLETER
238 QFSCompleter *completer;
239 #endif //QT_NO_FSCOMPLETER
240
241 QFileDialog::FileMode fileMode;
242 QFileDialog::AcceptMode acceptMode;
243 bool confirmOverwrite;
244 QString defaultSuffix;
245 QString setWindowTitle;
246
247 QStringList currentHistory;
248 int currentHistoryLocation;
249
250 QAction *renameAction;
251 QAction *deleteAction;
252 QAction *showHiddenAction;
253 QAction *newFolderAction;
254
255 bool useDefaultCaption;
256 bool defaultFileTypes;
257 bool fileNameLabelExplicitlySat;
258 QStringList nameFilters;
259
260 // Members for using native dialogs:
261 bool nativeDialogInUse;
262 // setVisible_sys returns true if it ends up showing a native
263 // dialog. Returning false means that a non-native dialog must be
264 // used instead.
265 bool canBeNativeDialog();
266 bool setVisible_sys(bool visible);
267 void deleteNativeDialog_sys();
268 QDialog::DialogCode dialogResultCode_sys();
269
270 void setDirectory_sys(const QString &directory);
271 QString directory_sys() const;
272 void selectFile_sys(const QString &filename);
273 QStringList selectedFiles_sys() const;
274 void setFilter_sys();
275 void setNameFilters_sys(const QStringList &filters);
276 void selectNameFilter_sys(const QString &filter);
277 QString selectedNameFilter_sys() const;
278 //////////////////////////////////////////////
279
280 #if defined(Q_WS_MAC)
281 void *mDelegate;
282 #ifndef QT_MAC_USE_COCOA
283 NavDialogRef mDialog;
284 bool mDialogStarted;
285 bool mDialogClosed;
286 QString mCurrentLocation;
287 QString mCurrentSelection;
288 QStringList mCurrentSelectionList;
289
290 struct QtMacFilterName {
291 QString description;
292 QString regexp;
293 QString filter;
294 };
295 struct QtMacNavFilterInfo {
QtMacNavFilterInfoQtMacNavFilterInfo296 QtMacNavFilterInfo() : currentSelection(-1) {}
297 int currentSelection;
298 QList<QtMacFilterName> filters;
299 } filterInfo;
300
301 static void qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg, NavCBRecPtr p,
302 NavCallBackUserData data);
303 static Boolean qt_mac_filedialog_filter_proc(AEDesc *theItem, void *info, void *data,
304 NavFilterModes);
305 bool showCarbonNavServicesDialog();
306 bool hideCarbonNavServicesDialog();
307 void createNavServicesDialog();
308 #else
309 bool showCocoaFilePanel();
310 bool hideCocoaFilePanel();
311 #endif
312 void createNSOpenSavePanelDelegate();
313 void QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath);
314 void QNSOpenSavePanelDelegate_panelClosed(bool accepted);
315 void QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir);
316 void QNSOpenSavePanelDelegate_filterSelected(int menuIndex);
317 void _q_macRunNativeAppModalPanel();
318 void mac_nativeDialogModalHelp();
319 #endif
320
321 QScopedPointer<Ui_QFileDialog> qFileDialogUi;
322
323 QString acceptLabel;
324
325 QPointer<QObject> receiverToDisconnectOnClose;
326 QByteArray memberToDisconnectOnClose;
327 QByteArray signalToDisconnectOnClose;
328
329 QFileDialog::Options opts;
330
331 ~QFileDialogPrivate();
332
333 private:
334 Q_DISABLE_COPY(QFileDialogPrivate)
335 };
336
337 class QFileDialogLineEdit : public QLineEdit
338 {
339 public:
QLineEdit(parent)340 QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), hideOnEsc(false), d_ptr(0){}
init(QFileDialogPrivate * d_pointer)341 void init(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; }
342 void keyPressEvent(QKeyEvent *e);
343 bool hideOnEsc;
344 private:
345 QFileDialogPrivate *d_ptr;
346 };
347
348 class QFileDialogComboBox : public QComboBox
349 {
350 public:
QComboBox(parent)351 QFileDialogComboBox(QWidget *parent = 0) : QComboBox(parent), urlModel(0) {}
352 void init(QFileDialogPrivate *d_pointer);
353 void showPopup();
354 void setHistory(const QStringList &paths);
history()355 QStringList history() const { return m_history; }
356 void paintEvent(QPaintEvent *);
357
358 private:
359 QUrlModel *urlModel;
360 QFileDialogPrivate *d_ptr;
361 QStringList m_history;
362 };
363
364 class QFileDialogListView : public QListView
365 {
366 public:
367 QFileDialogListView(QWidget *parent = 0);
368 void init(QFileDialogPrivate *d_pointer);
369 QSize sizeHint() const;
370 protected:
371 void keyPressEvent(QKeyEvent *e);
372 private:
373 QFileDialogPrivate *d_ptr;
374 };
375
376 class QFileDialogTreeView : public QTreeView
377 {
378 public:
379 QFileDialogTreeView(QWidget *parent);
380 void init(QFileDialogPrivate *d_pointer);
381 QSize sizeHint() const;
382
383 protected:
384 void keyPressEvent(QKeyEvent *e);
385 private:
386 QFileDialogPrivate *d_ptr;
387 };
388
mapToSource(const QModelIndex & index)389 inline QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const {
390 #ifdef QT_NO_PROXYMODEL
391 return index;
392 #else
393 return proxyModel ? proxyModel->mapToSource(index) : index;
394 #endif
395 }
mapFromSource(const QModelIndex & index)396 inline QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) const {
397 #ifdef QT_NO_PROXYMODEL
398 return index;
399 #else
400 return proxyModel ? proxyModel->mapFromSource(index) : index;
401 #endif
402 }
403
rootPath()404 inline QString QFileDialogPrivate::rootPath() const {
405 return model->rootPath();
406 }
407
408 #ifndef Q_WS_MAC
409 // Dummies for platforms that don't use native dialogs:
deleteNativeDialog_sys()410 inline void QFileDialogPrivate::deleteNativeDialog_sys() { qt_guiPlatformPlugin()->fileDialogDelete(q_func()); }
setVisible_sys(bool visible)411 inline bool QFileDialogPrivate::setVisible_sys(bool visible) { return qt_guiPlatformPlugin()->fileDialogSetVisible(q_func(), visible); }
dialogResultCode_sys()412 inline QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys(){ return qt_guiPlatformPlugin()->fileDialogResultCode(q_func()); }
setDirectory_sys(const QString & directory)413 inline void QFileDialogPrivate::setDirectory_sys(const QString &directory) { qt_guiPlatformPlugin()->fileDialogSetDirectory(q_func(), directory); }
directory_sys()414 inline QString QFileDialogPrivate::directory_sys() const { return qt_guiPlatformPlugin()->fileDialogDirectory(q_func()); }
selectFile_sys(const QString & filename)415 inline void QFileDialogPrivate::selectFile_sys(const QString &filename) { qt_guiPlatformPlugin()->fileDialogSelectFile(q_func(), filename); }
selectedFiles_sys()416 inline QStringList QFileDialogPrivate::selectedFiles_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedFiles(q_func()); }
setFilter_sys()417 inline void QFileDialogPrivate::setFilter_sys() { qt_guiPlatformPlugin()->fileDialogSetFilter(q_func()); }
setNameFilters_sys(const QStringList & filters)418 inline void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters) { qt_guiPlatformPlugin()->fileDialogSetNameFilters(q_func(), filters); }
selectNameFilter_sys(const QString & filter)419 inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) { qt_guiPlatformPlugin()->fileDialogSelectNameFilter(q_func(), filter); }
selectedNameFilter_sys()420 inline QString QFileDialogPrivate::selectedNameFilter_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedNameFilter(q_func()); }
421 #endif
422
423 QT_END_NAMESPACE
424
425 #endif // QT_NO_FILEDIALOG
426
427 #endif // QFILEDIALOG_P_H
428