|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt3Support module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qplatformdefs.h" |
|
43 |
|
44 #include "q3filedialog.h" |
|
45 |
|
46 #ifndef QT_NO_FILEDIALOG |
|
47 |
|
48 #include "private/qapplication_p.h" |
|
49 #include "q3buttongroup.h" |
|
50 #include "q3header.h" |
|
51 #include "q3listview.h" |
|
52 #include "qapplication.h" |
|
53 #include "qbitmap.h" |
|
54 #include "qcheckbox.h" |
|
55 #include "q3cleanuphandler.h" |
|
56 #include "qcombobox.h" |
|
57 #include "q3combobox.h" |
|
58 #include "q3cstring.h" |
|
59 #include "qcursor.h" |
|
60 #include "qdesktopwidget.h" |
|
61 #include "q3dragobject.h" |
|
62 #include "qevent.h" |
|
63 #include "qfile.h" |
|
64 #include "qlabel.h" |
|
65 #include "qlayout.h" |
|
66 #include "qlibrary.h" |
|
67 #include "qlineedit.h" |
|
68 #include "q3listbox.h" |
|
69 #include "qmap.h" |
|
70 #include "qmessagebox.h" |
|
71 #include "qmime.h" |
|
72 #include "qpainter.h" |
|
73 #include "qpointer.h" |
|
74 #include "q3popupmenu.h" |
|
75 #include "q3progressbar.h" |
|
76 #include "q3ptrvector.h" |
|
77 #include "qpushbutton.h" |
|
78 #include "qregexp.h" |
|
79 #include "qsplitter.h" |
|
80 #include "q3strlist.h" |
|
81 #include "qstyle.h" |
|
82 #include "qtimer.h" |
|
83 #include "qtoolbutton.h" |
|
84 #include "qtooltip.h" |
|
85 #include "q3widgetstack.h" |
|
86 #include "q3urloperator.h" |
|
87 #include "q3vbox.h" |
|
88 #include "qurlinfo.h" |
|
89 |
|
90 #ifdef Q_WS_WIN |
|
91 #ifndef QT_NO_THREAD |
|
92 # include "qwindowsstyle.h" |
|
93 # include "private/qmutexpool_p.h" |
|
94 #endif |
|
95 #endif // Q_WS_WIN |
|
96 |
|
97 #ifndef Q_OS_WINCE |
|
98 #include <time.h> |
|
99 #else |
|
100 #include <shellapi.h> |
|
101 #endif // Q_OS_WINCE |
|
102 #include <stdlib.h> |
|
103 #include <limits.h> |
|
104 #include <ctype.h> |
|
105 |
|
106 #ifdef Q_WS_MAC |
|
107 #include "qmacstyle_mac.h" |
|
108 #include "private/qt_mac_p.h" |
|
109 #include "private/qunicodetables_p.h" |
|
110 #undef check |
|
111 #endif |
|
112 |
|
113 #if defined(Q_OS_OPENBSD) |
|
114 #include <sys/param.h> |
|
115 #endif |
|
116 |
|
117 QT_BEGIN_NAMESPACE |
|
118 |
|
119 #ifndef QT_MAC_USE_COCOA |
|
120 |
|
121 /* XPM */ |
|
122 static const char * const start_xpm[]={ |
|
123 "16 15 8 1", |
|
124 "a c #cec6bd", |
|
125 "# c #000000", |
|
126 "e c #ffff00", |
|
127 "b c #999999", |
|
128 "f c #cccccc", |
|
129 "d c #dcdcdc", |
|
130 "c c #ffffff", |
|
131 ". c None", |
|
132 ".....######aaaaa", |
|
133 "...bb#cccc##aaaa", |
|
134 "..bcc#cccc#d#aaa", |
|
135 ".bcef#cccc#dd#aa", |
|
136 ".bcfe#cccc#####a", |
|
137 ".bcef#ccccccccc#", |
|
138 "bbbbbbbbbbbbccc#", |
|
139 "bccccccccccbbcc#", |
|
140 "bcefefefefee#bc#", |
|
141 ".bcefefefefef#c#", |
|
142 ".bcfefefefefe#c#", |
|
143 "..bcfefefefeeb##", |
|
144 "..bbbbbbbbbbbbb#", |
|
145 "...#############", |
|
146 "................"}; |
|
147 |
|
148 /* XPM */ |
|
149 static const char * const end_xpm[]={ |
|
150 "16 15 9 1", |
|
151 "d c #a0a0a0", |
|
152 "c c #c3c3c3", |
|
153 "# c #cec6bd", |
|
154 ". c #000000", |
|
155 "f c #ffff00", |
|
156 "e c #999999", |
|
157 "g c #cccccc", |
|
158 "b c #ffffff", |
|
159 "a c None", |
|
160 "......####aaaaaa", |
|
161 ".bbbb..###aaaaaa", |
|
162 ".bbbb.c.##aaaaaa", |
|
163 ".bbbb....ddeeeea", |
|
164 ".bbbbbbb.bbbbbe.", |
|
165 ".bbbbbbb.bcfgfe.", |
|
166 "eeeeeeeeeeeeefe.", |
|
167 "ebbbbbbbbbbeege.", |
|
168 "ebfgfgfgfgff.ee.", |
|
169 "aebfgfgfgfgfg.e.", |
|
170 "aebgfgfgfgfgf.e.", |
|
171 "aaebgfgfgfgffe..", |
|
172 "aaeeeeeeeeeeeee.", |
|
173 "aaa.............", |
|
174 "aaaaaaaaaaaaaaaa"}; |
|
175 |
|
176 /* XPM */ |
|
177 static const char* const open_xpm[]={ |
|
178 "16 16 6 1", |
|
179 ". c None", |
|
180 "b c #ffff00", |
|
181 "d c #000000", |
|
182 "* c #999999", |
|
183 "c c #cccccc", |
|
184 "a c #ffffff", |
|
185 "................", |
|
186 "................", |
|
187 "...*****........", |
|
188 "..*aaaaa*.......", |
|
189 ".*abcbcba******.", |
|
190 ".*acbcbcaaaaaa*d", |
|
191 ".*abcbcbcbcbcb*d", |
|
192 "*************b*d", |
|
193 "*aaaaaaaaaa**c*d", |
|
194 "*abcbcbcbcbbd**d", |
|
195 ".*abcbcbcbcbcd*d", |
|
196 ".*acbcbcbcbcbd*d", |
|
197 "..*acbcbcbcbb*dd", |
|
198 "..*************d", |
|
199 "...ddddddddddddd", |
|
200 "................"}; |
|
201 |
|
202 /* XPM */ |
|
203 static const char * const link_dir_xpm[]={ |
|
204 "16 16 10 1", |
|
205 "h c #808080", |
|
206 "g c #a0a0a0", |
|
207 "d c #000000", |
|
208 "b c #ffff00", |
|
209 "f c #303030", |
|
210 "# c #999999", |
|
211 "a c #cccccc", |
|
212 "e c #585858", |
|
213 "c c #ffffff", |
|
214 ". c None", |
|
215 "................", |
|
216 "................", |
|
217 "..#####.........", |
|
218 ".#ababa#........", |
|
219 "#abababa######..", |
|
220 "#cccccccccccc#d.", |
|
221 "#cbababababab#d.", |
|
222 "#cabababababa#d.", |
|
223 "#cbababdddddddd.", |
|
224 "#cababadccccccd.", |
|
225 "#cbababdcececcd.", |
|
226 "#cababadcefdfcd.", |
|
227 "#cbababdccgdhcd.", |
|
228 "#######dccchccd.", |
|
229 ".dddddddddddddd.", |
|
230 "................"}; |
|
231 |
|
232 /* XPM */ |
|
233 static const char * const link_file_xpm[]={ |
|
234 "16 16 10 1", |
|
235 "h c #808080", |
|
236 "g c #a0a0a0", |
|
237 "d c #c3c3c3", |
|
238 ". c #7f7f7f", |
|
239 "c c #000000", |
|
240 "b c #bfbfbf", |
|
241 "f c #303030", |
|
242 "e c #585858", |
|
243 "a c #ffffff", |
|
244 "# c None", |
|
245 "################", |
|
246 "..........######", |
|
247 ".aaaaaaaab.#####", |
|
248 ".aaaaaaaaba.####", |
|
249 ".aaaaaaaacccc###", |
|
250 ".aaaaaaaaaabc###", |
|
251 ".aaaaaaaaaabc###", |
|
252 ".aaaaaaaaaadc###", |
|
253 ".aaaaaaaaaadc###", |
|
254 ".aaaacccccccc###", |
|
255 ".aaaacaaaaaac###", |
|
256 ".aaaacaeaeaac###", |
|
257 ".aaaacaefcfac###", |
|
258 ".aaaacaagchac###", |
|
259 ".ddddcaaahaac###", |
|
260 "ccccccccccccc###"}; |
|
261 |
|
262 /* XPM */ |
|
263 static const char* const file_xpm[]={ |
|
264 "16 16 5 1", |
|
265 ". c #7f7f7f", |
|
266 "# c None", |
|
267 "c c #000000", |
|
268 "b c #bfbfbf", |
|
269 "a c #ffffff", |
|
270 "################", |
|
271 "..........######", |
|
272 ".aaaaaaaab.#####", |
|
273 ".aaaaaaaaba.####", |
|
274 ".aaaaaaaacccc###", |
|
275 ".aaaaaaaaaabc###", |
|
276 ".aaaaaaaaaabc###", |
|
277 ".aaaaaaaaaabc###", |
|
278 ".aaaaaaaaaabc###", |
|
279 ".aaaaaaaaaabc###", |
|
280 ".aaaaaaaaaabc###", |
|
281 ".aaaaaaaaaabc###", |
|
282 ".aaaaaaaaaabc###", |
|
283 ".aaaaaaaaaabc###", |
|
284 ".bbbbbbbbbbbc###", |
|
285 "ccccccccccccc###"}; |
|
286 |
|
287 /* XPM */ |
|
288 static const char * const closed_xpm[]={ |
|
289 "16 16 6 1", |
|
290 ". c None", |
|
291 "b c #ffff00", |
|
292 "d c #000000", |
|
293 "* c #999999", |
|
294 "a c #cccccc", |
|
295 "c c #ffffff", |
|
296 "................", |
|
297 "................", |
|
298 "..*****.........", |
|
299 ".*ababa*........", |
|
300 "*abababa******..", |
|
301 "*cccccccccccc*d.", |
|
302 "*cbababababab*d.", |
|
303 "*cabababababa*d.", |
|
304 "*cbababababab*d.", |
|
305 "*cabababababa*d.", |
|
306 "*cbababababab*d.", |
|
307 "*cabababababa*d.", |
|
308 "*cbababababab*d.", |
|
309 "**************d.", |
|
310 ".dddddddddddddd.", |
|
311 "................"}; |
|
312 |
|
313 |
|
314 /* XPM */ |
|
315 static const char* const cdtoparent_xpm[]={ |
|
316 "15 13 3 1", |
|
317 ". c None", |
|
318 "* c #000000", |
|
319 "a c #ffff99", |
|
320 "..*****........", |
|
321 ".*aaaaa*.......", |
|
322 "***************", |
|
323 "*aaaaaaaaaaaaa*", |
|
324 "*aaaa*aaaaaaaa*", |
|
325 "*aaa***aaaaaaa*", |
|
326 "*aa*****aaaaaa*", |
|
327 "*aaaa*aaaaaaaa*", |
|
328 "*aaaa*aaaaaaaa*", |
|
329 "*aaaa******aaa*", |
|
330 "*aaaaaaaaaaaaa*", |
|
331 "*aaaaaaaaaaaaa*", |
|
332 "***************"}; |
|
333 |
|
334 |
|
335 /* XPM */ |
|
336 static const char* const newfolder_xpm[] = { |
|
337 "15 14 4 1", |
|
338 " c None", |
|
339 ". c #000000", |
|
340 "+ c #FFFF00", |
|
341 "@ c #FFFFFF", |
|
342 " . ", |
|
343 " ", |
|
344 " . ", |
|
345 " . . ", |
|
346 " .... . . . ", |
|
347 " .+@+@. . . ", |
|
348 ".......... . .", |
|
349 ".@+@+@+@+@.. ", |
|
350 ".+@+@+@+@+. . ", |
|
351 ".@+@+@+@+@. . ", |
|
352 ".+@+@+@+@+. ", |
|
353 ".@+@+@+@+@. ", |
|
354 ".+@+@+@+@+. ", |
|
355 "........... "}; |
|
356 |
|
357 /* XPM */ |
|
358 static const char* const detailedview_xpm[]={ |
|
359 "14 11 3 1", |
|
360 ". c None", |
|
361 "* c #000000", |
|
362 "a c #000099", |
|
363 ".****.***.***.", |
|
364 "..............", |
|
365 "aaaaaaaaaaaaaa", |
|
366 "..............", |
|
367 ".****.***.***.", |
|
368 "..............", |
|
369 ".****.***.***.", |
|
370 "..............", |
|
371 ".****.***.***.", |
|
372 "..............", |
|
373 ".****.***.***."}; |
|
374 |
|
375 /* XPM */ |
|
376 static const char* const previewinfoview_xpm[]={ |
|
377 "13 13 4 1", |
|
378 ". c #00007f", |
|
379 "a c black", |
|
380 "# c #cec6bd", |
|
381 "b c #000000", |
|
382 "..#####aaaaaa", |
|
383 ".#.#bb#a#####", |
|
384 "...####a#bbb#", |
|
385 "#######a#####", |
|
386 "#######a#bb##", |
|
387 "..#####a#####", |
|
388 ".#.#bb#a#bbb#", |
|
389 "...####a#####", |
|
390 "#######a#bb##", |
|
391 "#######a#####", |
|
392 "..#####a#bbb#", |
|
393 ".#.#bb#a#####", |
|
394 "...####aaaaaa"}; |
|
395 |
|
396 /* XPM */ |
|
397 static const char* const previewcontentsview_xpm[]={ |
|
398 "14 13 5 1", |
|
399 ". c #00007f", |
|
400 "a c black", |
|
401 "c c #7f007f", |
|
402 "# c #cec6bd", |
|
403 "b c #000000", |
|
404 "..#####aaaaaaa", |
|
405 ".#.#bb#a#####a", |
|
406 "...####a#ccc#a", |
|
407 "#######a#ccc#a", |
|
408 "#######a#####a", |
|
409 "..#####a#bbb#a", |
|
410 ".#.#bb#a#####a", |
|
411 "...####a#bbb#a", |
|
412 "#######a#####a", |
|
413 "#######a#bbb#a", |
|
414 "..#####a#####a", |
|
415 ".#.#bb#a#####a", |
|
416 "...####aaaaaaa"}; |
|
417 |
|
418 /* XPM */ |
|
419 static const char* const mclistview_xpm[]={ |
|
420 "15 11 4 1", |
|
421 "* c None", |
|
422 "b c #000000", |
|
423 ". c #000099", |
|
424 "a c #ffffff", |
|
425 "...*****...****", |
|
426 ".a.*bbb*.a.*bbb", |
|
427 "...*****...****", |
|
428 "***************", |
|
429 "...*****...****", |
|
430 ".a.*bbb*.a.*bbb", |
|
431 "...*****...****", |
|
432 "***************", |
|
433 "...*****...****", |
|
434 ".a.*bbb*.a.*bbb", |
|
435 "...*****...****"}; |
|
436 |
|
437 /* XPM */ |
|
438 static const char * const back_xpm [] = { |
|
439 "13 11 3 1", |
|
440 "a c #00ffff", |
|
441 "# c #000000", |
|
442 ". c None", |
|
443 ".....#.......", |
|
444 "....##.......", |
|
445 "...#a#.......", |
|
446 "..#aa########", |
|
447 ".#aaaaaaaaaa#", |
|
448 "#aaaaaaaaaaa#", |
|
449 ".#aaaaaaaaaa#", |
|
450 "..#aa########", |
|
451 "...#a#.......", |
|
452 "....##.......", |
|
453 ".....#......."}; |
|
454 |
|
455 static QPixmap * openFolderIcon = 0; |
|
456 static QPixmap * closedFolderIcon = 0; |
|
457 static QPixmap * detailViewIcon = 0; |
|
458 static QPixmap * multiColumnListViewIcon = 0; |
|
459 static QPixmap * cdToParentIcon = 0; |
|
460 static QPixmap * newFolderIcon = 0; |
|
461 static QPixmap * fifteenTransparentPixels = 0; |
|
462 static QPixmap * symLinkDirIcon = 0; |
|
463 static QPixmap * symLinkFileIcon = 0; |
|
464 static QPixmap * fileIcon = 0; |
|
465 static QPixmap * startCopyIcon = 0; |
|
466 static QPixmap * endCopyIcon = 0; |
|
467 static QPixmap * previewContentsViewIcon = 0; |
|
468 static QPixmap * previewInfoViewIcon = 0; |
|
469 static QPixmap *goBackIcon = 0; |
|
470 static Q3FileIconProvider * fileIconProvider = 0; |
|
471 static int lastWidth = 0; |
|
472 static int lastHeight = 0; |
|
473 static QString * workingDirectory = 0; |
|
474 |
|
475 static bool bShowHiddenFiles = false; |
|
476 static int sortFilesBy = (int)QDir::Name; |
|
477 static bool sortAscending = true; |
|
478 static bool detailViewMode = false; |
|
479 |
|
480 static Q3CleanupHandler<QPixmap> qfd_cleanup_pixmap; |
|
481 static Q3CleanupHandler<QString> qfd_cleanup_string; |
|
482 |
|
483 static QString toRootIfNotExists( const QString &path ) |
|
484 { |
|
485 if ( !path.isEmpty() ) |
|
486 return path; |
|
487 |
|
488 QFileInfoList drives = QDir::drives(); |
|
489 Q_ASSERT( !drives.isEmpty() ); |
|
490 return drives.first().filePath(); |
|
491 } |
|
492 |
|
493 static bool isDirectoryMode(int m) |
|
494 { |
|
495 return m == Q3FileDialog::Directory || m == Q3FileDialog::DirectoryOnly; |
|
496 } |
|
497 |
|
498 static void updateLastSize(Q3FileDialog *that) |
|
499 { |
|
500 int extWidth = 0; |
|
501 int extHeight = 0; |
|
502 if (that->extension() && that->extension()->isVisible()) { |
|
503 if (that->orientation() == Qt::Vertical) |
|
504 extHeight = that->extension()->height(); |
|
505 else |
|
506 extWidth = that->extension()->width(); |
|
507 } |
|
508 lastWidth = that->width() - extWidth; |
|
509 lastHeight = that->height() - extHeight; |
|
510 } |
|
511 |
|
512 #if defined(Q_WS_WIN) |
|
513 class QWindowsIconProvider : public Q3FileIconProvider |
|
514 { |
|
515 public: |
|
516 QWindowsIconProvider(QObject *parent=0, const char *name=0); |
|
517 ~QWindowsIconProvider(); |
|
518 |
|
519 const QPixmap * pixmap(const QFileInfo &fi); |
|
520 |
|
521 private: |
|
522 QPixmap defaultFolder; |
|
523 QPixmap defaultFile; |
|
524 QPixmap defaultExe; |
|
525 QPixmap pix; |
|
526 int pixw, pixh; |
|
527 QMap< QString, QPixmap > cache; |
|
528 |
|
529 }; |
|
530 #endif |
|
531 |
|
532 static void makeVariables() { |
|
533 if (!openFolderIcon) { |
|
534 workingDirectory = new QString(toRootIfNotExists( QDir::currentDirPath() )); |
|
535 qfd_cleanup_string.add(&workingDirectory); |
|
536 |
|
537 openFolderIcon = new QPixmap((const char **)open_xpm); |
|
538 qfd_cleanup_pixmap.add(&openFolderIcon); |
|
539 symLinkDirIcon = new QPixmap((const char **)link_dir_xpm); |
|
540 qfd_cleanup_pixmap.add(&symLinkDirIcon); |
|
541 symLinkFileIcon = new QPixmap((const char **)link_file_xpm); |
|
542 qfd_cleanup_pixmap.add(&symLinkFileIcon); |
|
543 fileIcon = new QPixmap((const char **)file_xpm); |
|
544 qfd_cleanup_pixmap.add(&fileIcon); |
|
545 closedFolderIcon = new QPixmap((const char **)closed_xpm); |
|
546 qfd_cleanup_pixmap.add(&closedFolderIcon); |
|
547 detailViewIcon = new QPixmap((const char **)detailedview_xpm); |
|
548 qfd_cleanup_pixmap.add(&detailViewIcon); |
|
549 multiColumnListViewIcon = new QPixmap((const char **)mclistview_xpm); |
|
550 qfd_cleanup_pixmap.add(&multiColumnListViewIcon); |
|
551 cdToParentIcon = new QPixmap((const char **)cdtoparent_xpm); |
|
552 qfd_cleanup_pixmap.add(&cdToParentIcon); |
|
553 newFolderIcon = new QPixmap((const char **)newfolder_xpm); |
|
554 qfd_cleanup_pixmap.add(&newFolderIcon); |
|
555 previewInfoViewIcon |
|
556 = new QPixmap((const char **)previewinfoview_xpm); |
|
557 qfd_cleanup_pixmap.add(&previewInfoViewIcon); |
|
558 previewContentsViewIcon |
|
559 = new QPixmap((const char **)previewcontentsview_xpm); |
|
560 qfd_cleanup_pixmap.add(&previewContentsViewIcon); |
|
561 startCopyIcon = new QPixmap((const char **)start_xpm); |
|
562 qfd_cleanup_pixmap.add(&startCopyIcon); |
|
563 endCopyIcon = new QPixmap((const char **)end_xpm); |
|
564 qfd_cleanup_pixmap.add(&endCopyIcon); |
|
565 goBackIcon = new QPixmap((const char **)back_xpm); |
|
566 qfd_cleanup_pixmap.add(&goBackIcon); |
|
567 fifteenTransparentPixels = new QPixmap(closedFolderIcon->width(), 1); |
|
568 qfd_cleanup_pixmap.add(&fifteenTransparentPixels); |
|
569 QBitmap m(fifteenTransparentPixels->width(), 1); |
|
570 m.fill(Qt::color0); |
|
571 fifteenTransparentPixels->setMask(m); |
|
572 bShowHiddenFiles = false; |
|
573 sortFilesBy = (int)QDir::Name; |
|
574 detailViewMode = false; |
|
575 #if defined(Q_WS_WIN) |
|
576 if (!fileIconProvider) |
|
577 fileIconProvider = new QWindowsIconProvider(qApp); |
|
578 #endif |
|
579 } |
|
580 } |
|
581 |
|
582 /****************************************************************** |
|
583 * |
|
584 * Definitions of view classes |
|
585 * |
|
586 ******************************************************************/ |
|
587 |
|
588 class QRenameEdit : public QLineEdit |
|
589 { |
|
590 Q_OBJECT |
|
591 |
|
592 public: |
|
593 QRenameEdit(QWidget *parent); |
|
594 |
|
595 protected: |
|
596 void keyPressEvent(QKeyEvent *e); |
|
597 void focusOutEvent(QFocusEvent *e); |
|
598 void emitDoRename(); |
|
599 |
|
600 signals: |
|
601 void cancelRename(); |
|
602 void doRename(); |
|
603 |
|
604 private slots: |
|
605 void slotReturnPressed(); |
|
606 |
|
607 private: |
|
608 bool doRenameAlreadyEmitted; |
|
609 }; |
|
610 |
|
611 QRenameEdit::QRenameEdit(QWidget *parent) |
|
612 : QLineEdit(parent, "qt_rename_edit"), doRenameAlreadyEmitted(false) |
|
613 { |
|
614 connect(this, SIGNAL(returnPressed()), SLOT(slotReturnPressed())); |
|
615 } |
|
616 |
|
617 class QFileListBox : public Q3ListBox |
|
618 { |
|
619 friend class Q3FileDialog; |
|
620 |
|
621 Q_OBJECT |
|
622 |
|
623 private: |
|
624 QFileListBox(QWidget *parent, Q3FileDialog *d); |
|
625 |
|
626 void clear(); |
|
627 void show(); |
|
628 void startRename(bool check = true); |
|
629 void viewportMousePressEvent(QMouseEvent *e); |
|
630 void viewportMouseReleaseEvent(QMouseEvent *e); |
|
631 void viewportMouseDoubleClickEvent(QMouseEvent *e); |
|
632 void viewportMouseMoveEvent(QMouseEvent *e); |
|
633 #ifndef QT_NO_DRAGANDDROP |
|
634 void viewportDragEnterEvent(QDragEnterEvent *e); |
|
635 void viewportDragMoveEvent(QDragMoveEvent *e); |
|
636 void viewportDragLeaveEvent(QDragLeaveEvent *e); |
|
637 void viewportDropEvent(QDropEvent *e); |
|
638 bool acceptDrop(const QPoint &pnt, QWidget *source); |
|
639 void setCurrentDropItem(const QPoint &pnt); |
|
640 #endif |
|
641 void keyPressEvent(QKeyEvent *e); |
|
642 |
|
643 private slots: |
|
644 void rename(); |
|
645 void cancelRename(); |
|
646 void doubleClickTimeout(); |
|
647 void changeDirDuringDrag(); |
|
648 void dragObjDestroyed(); |
|
649 void contentsMoved(int, int); |
|
650 |
|
651 private: |
|
652 QRenameEdit *lined; |
|
653 Q3FileDialog *filedialog; |
|
654 bool renaming; |
|
655 QTimer* renameTimer; |
|
656 Q3ListBoxItem *renameItem, *dragItem; |
|
657 QPoint pressPos, oldDragPos; |
|
658 bool mousePressed; |
|
659 int urls; |
|
660 QString startDragDir; |
|
661 Q3ListBoxItem *currDropItem; |
|
662 QTimer *changeDirTimer; |
|
663 bool firstMousePressEvent; |
|
664 Q3UrlOperator startDragUrl; |
|
665 |
|
666 }; |
|
667 |
|
668 |
|
669 class Q3FileDialogQFileListView : public Q3ListView |
|
670 { |
|
671 Q_OBJECT |
|
672 |
|
673 public: |
|
674 Q3FileDialogQFileListView(QWidget *parent, Q3FileDialog *d); |
|
675 |
|
676 void clear(); |
|
677 void startRename(bool check = true); |
|
678 void setSorting(int column, bool increasing = true); |
|
679 |
|
680 QRenameEdit *lined; |
|
681 bool renaming; |
|
682 Q3ListViewItem *renameItem; |
|
683 |
|
684 private: |
|
685 void viewportMousePressEvent(QMouseEvent *e); |
|
686 void viewportMouseDoubleClickEvent(QMouseEvent *e); |
|
687 void keyPressEvent(QKeyEvent *e); |
|
688 void viewportMouseReleaseEvent(QMouseEvent *e); |
|
689 void viewportMouseMoveEvent(QMouseEvent *e); |
|
690 #ifndef QT_NO_DRAGANDDROP |
|
691 void viewportDragEnterEvent(QDragEnterEvent *e); |
|
692 void viewportDragMoveEvent(QDragMoveEvent *e); |
|
693 void viewportDragLeaveEvent(QDragLeaveEvent *e); |
|
694 void viewportDropEvent(QDropEvent *e); |
|
695 bool acceptDrop(const QPoint &pnt, QWidget *source); |
|
696 void setCurrentDropItem(const QPoint &pnt); |
|
697 #endif |
|
698 |
|
699 private slots: |
|
700 void rename(); |
|
701 void cancelRename(); |
|
702 void changeSortColumn2(int column); |
|
703 void doubleClickTimeout(); |
|
704 void changeDirDuringDrag(); |
|
705 void dragObjDestroyed(); |
|
706 void contentsMoved(int, int); |
|
707 |
|
708 private: |
|
709 Q3FileDialog *filedialog; |
|
710 QTimer* renameTimer; |
|
711 QPoint pressPos, oldDragPos; |
|
712 bool mousePressed; |
|
713 int urls; |
|
714 QString startDragDir; |
|
715 Q3ListViewItem *currDropItem, *dragItem; |
|
716 QTimer *changeDirTimer; |
|
717 bool firstMousePressEvent; |
|
718 bool ascending; |
|
719 int sortcolumn; |
|
720 Q3UrlOperator startDragUrl; |
|
721 |
|
722 }; |
|
723 |
|
724 /**************************************************************************** |
|
725 * |
|
726 * Classes for copy progress dialog |
|
727 * |
|
728 ****************************************************************************/ |
|
729 |
|
730 class QFDProgressAnimation : public QWidget |
|
731 { |
|
732 Q_OBJECT |
|
733 |
|
734 public: |
|
735 QFDProgressAnimation(QWidget *parent); |
|
736 void start(); |
|
737 |
|
738 private slots: |
|
739 void next(); |
|
740 |
|
741 protected: |
|
742 void paintEvent(QPaintEvent *e); |
|
743 |
|
744 private: |
|
745 int step; |
|
746 QTimer *timer; |
|
747 |
|
748 }; |
|
749 |
|
750 QFDProgressAnimation::QFDProgressAnimation(QWidget *parent) |
|
751 : QWidget(parent, "qt_progressanimation") |
|
752 { |
|
753 setFixedSize(300, 50); |
|
754 step = -1; |
|
755 next(); |
|
756 timer = new QTimer(this); |
|
757 connect(timer, SIGNAL(timeout()), |
|
758 this, SLOT(next())); |
|
759 } |
|
760 |
|
761 void QFDProgressAnimation::start() |
|
762 { |
|
763 timer->start(150, false); |
|
764 } |
|
765 |
|
766 void QFDProgressAnimation::next() |
|
767 { |
|
768 ++step; |
|
769 if (step > 10) |
|
770 step = 0; |
|
771 repaint(); |
|
772 } |
|
773 |
|
774 void QFDProgressAnimation::paintEvent(QPaintEvent *) |
|
775 { |
|
776 erase(); |
|
777 |
|
778 QPainter p; |
|
779 p.begin(this); |
|
780 if (step == 0) { |
|
781 p.drawPixmap(5, (height() - startCopyIcon->height()) / 2, |
|
782 *startCopyIcon); |
|
783 p.drawPixmap(width() - 5 - openFolderIcon->width(), |
|
784 (height() - openFolderIcon->height()) / 2 , *openFolderIcon); |
|
785 } else if (step == 10) { |
|
786 p.drawPixmap(5, (height() - openFolderIcon->height()) / 2, |
|
787 *openFolderIcon); |
|
788 p.drawPixmap(width() - 5 - endCopyIcon->width(), |
|
789 (height() - endCopyIcon->height()) / 2 , *endCopyIcon); |
|
790 } else { |
|
791 p.drawPixmap(5, (height() - openFolderIcon->height()) / 2, |
|
792 *openFolderIcon); |
|
793 p.drawPixmap(width() - 5 - openFolderIcon->width(), |
|
794 (height() - openFolderIcon->height()) / 2 , *openFolderIcon); |
|
795 int x = 10 + openFolderIcon->width(); |
|
796 int w = width() - 2 * x; |
|
797 int s = w / 9; |
|
798 p.drawPixmap(x + s * step, (height() - fileIcon->height()) / 2 - fileIcon->height(), |
|
799 *fileIcon); |
|
800 } |
|
801 } |
|
802 |
|
803 |
|
804 class QFDProgressDialog : public QDialog |
|
805 { |
|
806 Q_OBJECT |
|
807 |
|
808 public: |
|
809 QFDProgressDialog(QWidget *parent, const QString &fn, int steps); |
|
810 |
|
811 void setReadProgress(int p); |
|
812 void setWriteProgress(int p); |
|
813 void setWriteLabel(const QString &s); |
|
814 |
|
815 signals: |
|
816 void cancelled(); |
|
817 |
|
818 private: |
|
819 Q3ProgressBar *readBar; |
|
820 Q3ProgressBar *writeBar; |
|
821 QLabel *writeLabel; |
|
822 QFDProgressAnimation *animation; |
|
823 |
|
824 }; |
|
825 |
|
826 QFDProgressDialog::QFDProgressDialog(QWidget *parent, const QString &fn, int steps) |
|
827 : QDialog(parent, "", true) |
|
828 { |
|
829 setWindowTitle(Q3FileDialog::tr("Copy or Move a File")); |
|
830 QVBoxLayout *layout = new QVBoxLayout(this); |
|
831 layout->setSpacing(5); |
|
832 layout->setMargin(5); |
|
833 |
|
834 animation = new QFDProgressAnimation(this); |
|
835 layout->addWidget(animation); |
|
836 |
|
837 layout->addWidget(new QLabel(Q3FileDialog::tr("Read: %1").arg(fn), |
|
838 this, "qt_read_lbl")); |
|
839 readBar = new Q3ProgressBar(steps, this, "qt_readbar"); |
|
840 readBar->reset(); |
|
841 readBar->setProgress(0); |
|
842 layout->addWidget(readBar); |
|
843 writeLabel = new QLabel(Q3FileDialog::tr("Write: %1").arg(QString()), |
|
844 this, "qt_write_lbl"); |
|
845 layout->addWidget(writeLabel); |
|
846 writeBar = new Q3ProgressBar(steps, this, "qt_writebar"); |
|
847 writeBar->reset(); |
|
848 writeBar->setProgress(0); |
|
849 layout->addWidget(writeBar); |
|
850 |
|
851 QPushButton *b = new QPushButton(Q3FileDialog::tr("Cancel"), this, |
|
852 "qt_cancel_btn"); |
|
853 b->setFixedSize(b->sizeHint()); |
|
854 layout->addWidget(b); |
|
855 connect(b, SIGNAL(clicked()), |
|
856 this, SIGNAL(cancelled())); |
|
857 |
|
858 animation->start(); |
|
859 } |
|
860 |
|
861 void QFDProgressDialog::setReadProgress(int p) |
|
862 { |
|
863 readBar->setProgress(p); |
|
864 } |
|
865 |
|
866 void QFDProgressDialog::setWriteProgress(int p) |
|
867 { |
|
868 writeBar->setProgress(p); |
|
869 } |
|
870 |
|
871 void QFDProgressDialog::setWriteLabel(const QString &s) |
|
872 { |
|
873 writeLabel->setText(Q3FileDialog::tr("Write: %1").arg(s)); |
|
874 } |
|
875 |
|
876 /************************************************************************ |
|
877 * |
|
878 * Private Q3FileDialog members |
|
879 * |
|
880 ************************************************************************/ |
|
881 |
|
882 class Q3FileDialogPrivate { |
|
883 public: |
|
884 ~Q3FileDialogPrivate(); |
|
885 |
|
886 QStringList history; |
|
887 |
|
888 bool geometryDirty; |
|
889 Q3ComboBox * paths; |
|
890 QComboBox * types; |
|
891 QLabel * pathL; |
|
892 QLabel * fileL; |
|
893 QLabel * typeL; |
|
894 |
|
895 QVBoxLayout * topLevelLayout; |
|
896 QHBoxLayout *buttonLayout, *leftLayout, *rightLayout; |
|
897 Q3PtrList<QHBoxLayout> extraWidgetsLayouts; |
|
898 Q3PtrList<QLabel> extraLabels; |
|
899 Q3PtrList<QWidget> extraWidgets; |
|
900 Q3PtrList<QWidget> extraButtons; |
|
901 Q3PtrList<QAbstractButton> toolButtons; |
|
902 |
|
903 Q3WidgetStack * stack; |
|
904 |
|
905 QToolButton * cdToParent, *newFolder, * detailView, * mcView, |
|
906 *previewInfo, *previewContents, *goBack; |
|
907 Q3ButtonGroup * modeButtons; |
|
908 |
|
909 QString currentFileName; |
|
910 Q3ListViewItem *last; |
|
911 |
|
912 Q3ListBoxItem *lastEFSelected; |
|
913 |
|
914 struct File: public Q3ListViewItem { |
|
915 File(Q3FileDialogPrivate * dlgp, |
|
916 const QUrlInfo * fi, Q3ListViewItem * parent) |
|
917 : Q3ListViewItem(parent, dlgp->last), info(*fi), d(dlgp), i(0), hasMimePixmap(false) |
|
918 { setup(); dlgp->last = this; } |
|
919 File(Q3FileDialogPrivate * dlgp, |
|
920 const QUrlInfo * fi, Q3ListView * parent) |
|
921 : Q3ListViewItem(parent, dlgp->last), info(*fi), d(dlgp), i(0), hasMimePixmap(false) |
|
922 { setup(); dlgp->last = this; } |
|
923 File(Q3FileDialogPrivate * dlgp, |
|
924 const QUrlInfo * fi, Q3ListView * parent, Q3ListViewItem * after) |
|
925 : Q3ListViewItem(parent, after), info(*fi), d(dlgp), i(0), hasMimePixmap(false) |
|
926 { setup(); if (!nextSibling()) dlgp->last = this; } |
|
927 ~File(); |
|
928 |
|
929 QString text(int column) const; |
|
930 const QPixmap * pixmap(int) const; |
|
931 |
|
932 QUrlInfo info; |
|
933 Q3FileDialogPrivate * d; |
|
934 Q3ListBoxItem *i; |
|
935 bool hasMimePixmap; |
|
936 }; |
|
937 |
|
938 class MCItem: public Q3ListBoxItem { |
|
939 public: |
|
940 MCItem(Q3ListBox *, Q3ListViewItem * item); |
|
941 MCItem(Q3ListBox *, Q3ListViewItem * item, Q3ListBoxItem *after); |
|
942 QString text() const; |
|
943 const QPixmap *pixmap() const; |
|
944 int height(const Q3ListBox *) const; |
|
945 int width(const Q3ListBox *) const; |
|
946 void paint(QPainter *); |
|
947 Q3ListViewItem * i; |
|
948 }; |
|
949 |
|
950 class UrlInfoList : public Q3PtrList<QUrlInfo> { |
|
951 public: |
|
952 UrlInfoList() { setAutoDelete(true); } |
|
953 int compareItems(Q3PtrCollection::Item n1, Q3PtrCollection::Item n2) { |
|
954 if (!n1 || !n2) |
|
955 return 0; |
|
956 |
|
957 QUrlInfo *i1 = (QUrlInfo *)n1; |
|
958 QUrlInfo *i2 = (QUrlInfo *)n2; |
|
959 |
|
960 if (i1->isDir() && !i2->isDir()) |
|
961 return -1; |
|
962 if (!i1->isDir() && i2->isDir()) |
|
963 return 1; |
|
964 |
|
965 if (i1->name() == QLatin1String("..")) |
|
966 return -1; |
|
967 if (i2->name() == QLatin1String("..")) |
|
968 return 1; |
|
969 |
|
970 if (sortFilesBy == QDir::Name) { |
|
971 #if defined(Q_OS_WIN32) |
|
972 QString name1 = i1->name().lower(); |
|
973 QString name2 = i2->name().lower(); |
|
974 return name1.localeAwareCompare( name2 ); |
|
975 #else |
|
976 QString name1 = i1->name(); |
|
977 QString name2 = i2->name(); |
|
978 return name1.localeAwareCompare( name2 ); |
|
979 #endif |
|
980 } |
|
981 if (QUrlInfo::equal(*i1, *i2, sortFilesBy)) |
|
982 return 0; |
|
983 else if (QUrlInfo::greaterThan(*i1, *i2, sortFilesBy)) |
|
984 return 1; |
|
985 else if (QUrlInfo::lessThan(*i1, *i2, sortFilesBy)) |
|
986 return -1; |
|
987 // can't happen... |
|
988 return 0; |
|
989 } |
|
990 QUrlInfo *operator[](int i) { |
|
991 return at(i); |
|
992 } |
|
993 }; |
|
994 |
|
995 UrlInfoList sortedList; |
|
996 Q3PtrList<File> pendingItems; |
|
997 |
|
998 QFileListBox * moreFiles; |
|
999 |
|
1000 Q3FileDialog::Mode mode; |
|
1001 |
|
1002 QString rw; |
|
1003 QString ro; |
|
1004 QString wo; |
|
1005 QString inaccessible; |
|
1006 |
|
1007 QString symLinkToFile; |
|
1008 QString file; |
|
1009 QString symLinkToDir; |
|
1010 QString dir; |
|
1011 QString symLinkToSpecial; |
|
1012 QString special; |
|
1013 Q3WidgetStack *preview; |
|
1014 bool infoPreview, contentsPreview; |
|
1015 QSplitter *splitter; |
|
1016 Q3UrlOperator url, oldUrl; |
|
1017 QWidget *infoPreviewWidget, *contentsPreviewWidget; |
|
1018 Q3FilePreview *infoPreviewer, *contentsPreviewer; |
|
1019 bool hadDotDot; |
|
1020 |
|
1021 bool ignoreNextKeyPress; |
|
1022 // ignores the next refresh operation in case the user forced a selection |
|
1023 bool ignoreNextRefresh; |
|
1024 QFDProgressDialog *progressDia; |
|
1025 bool checkForFilter; |
|
1026 bool ignoreStop; |
|
1027 |
|
1028 QTimer *mimeTypeTimer; |
|
1029 const Q3NetworkOperation *currListChildren; |
|
1030 |
|
1031 // this is similar to QUrl::encode but does encode "*" and |
|
1032 // doesn't encode whitespaces |
|
1033 static QString encodeFileName(const QString& fName) { |
|
1034 |
|
1035 QString newStr; |
|
1036 Q3CString cName = fName.utf8(); |
|
1037 const Q3CString sChars( |
|
1038 #ifdef Q_WS_WIN |
|
1039 "#%" |
|
1040 #else |
|
1041 "<>#@\"&%$:,;?={}|^~[]\'`\\*" |
|
1042 #endif |
|
1043 ); |
|
1044 |
|
1045 int len = cName.length(); |
|
1046 if (!len) |
|
1047 return QString(); |
|
1048 for (int i = 0; i < len ;++i) { |
|
1049 uchar inCh = (uchar)cName[i]; |
|
1050 if (inCh >= 128 || sChars.contains(inCh)) |
|
1051 { |
|
1052 newStr += QLatin1Char('%'); |
|
1053 ushort c = inCh / 16; |
|
1054 c += c > 9 ? 'A' - 10 : '0'; |
|
1055 newStr += QLatin1Char((char)c); |
|
1056 c = inCh % 16; |
|
1057 c += c > 9 ? 'A' - 10 : '0'; |
|
1058 newStr += QLatin1Char((char)c); |
|
1059 } else { |
|
1060 newStr += QLatin1Char((char)inCh); |
|
1061 } |
|
1062 } |
|
1063 return newStr; |
|
1064 } |
|
1065 |
|
1066 static bool fileExists(const Q3UrlOperator &url, const QString& name) |
|
1067 { |
|
1068 Q3Url u(url, Q3FileDialogPrivate::encodeFileName(name)); |
|
1069 if (u.isLocalFile()) { |
|
1070 QFileInfo f(u.path()); |
|
1071 return f.exists(); |
|
1072 } else { |
|
1073 Q3NetworkProtocol *p = Q3NetworkProtocol::getNetworkProtocol(url.protocol()); |
|
1074 if (p && (p->supportedOperations()&Q3NetworkProtocol::OpListChildren)) { |
|
1075 QUrlInfo ui(url.info(name.isEmpty() ? QString::fromLatin1(".") : name)); |
|
1076 return ui.isValid(); |
|
1077 } |
|
1078 } |
|
1079 return true; |
|
1080 } |
|
1081 |
|
1082 #ifndef Q_NO_CURSOR |
|
1083 bool cursorOverride; // Remember if the cursor was overridden or not. |
|
1084 #endif |
|
1085 }; |
|
1086 |
|
1087 Q3FileDialogPrivate::~Q3FileDialogPrivate() |
|
1088 { |
|
1089 delete modeButtons; |
|
1090 } |
|
1091 |
|
1092 |
|
1093 |
|
1094 /************************************************************************ |
|
1095 * |
|
1096 * Internal class QRenameEdit |
|
1097 * |
|
1098 ************************************************************************/ |
|
1099 |
|
1100 void QRenameEdit::keyPressEvent(QKeyEvent *e) |
|
1101 { |
|
1102 if (e->key() == Qt::Key_Escape) |
|
1103 emit cancelRename(); |
|
1104 else |
|
1105 QLineEdit::keyPressEvent(e); |
|
1106 e->accept(); |
|
1107 } |
|
1108 |
|
1109 void QRenameEdit::focusOutEvent(QFocusEvent *) |
|
1110 { |
|
1111 if (!doRenameAlreadyEmitted) |
|
1112 emitDoRename(); |
|
1113 } |
|
1114 |
|
1115 void QRenameEdit::slotReturnPressed() |
|
1116 { |
|
1117 emitDoRename(); |
|
1118 } |
|
1119 |
|
1120 void QRenameEdit::emitDoRename() |
|
1121 { |
|
1122 doRenameAlreadyEmitted = true; |
|
1123 emit doRename(); |
|
1124 doRenameAlreadyEmitted = false; |
|
1125 } |
|
1126 |
|
1127 /************************************************************************ |
|
1128 * |
|
1129 * Internal class QFileListBox |
|
1130 * |
|
1131 ************************************************************************/ |
|
1132 |
|
1133 QFileListBox::QFileListBox(QWidget *parent, Q3FileDialog *dlg) |
|
1134 : Q3ListBox(parent, "filelistbox"), filedialog(dlg), |
|
1135 renaming(false), renameItem(0), mousePressed(false), |
|
1136 firstMousePressEvent(true) |
|
1137 { |
|
1138 changeDirTimer = new QTimer(this); |
|
1139 Q3VBox *box = new Q3VBox(viewport(), "qt_vbox"); |
|
1140 box->setFrameStyle(QFrame::Box | QFrame::Plain); |
|
1141 lined = new QRenameEdit(box); |
|
1142 lined->setFixedHeight(lined->sizeHint().height()); |
|
1143 box->hide(); |
|
1144 box->setBackgroundRole(QPalette::Base); |
|
1145 renameTimer = new QTimer(this); |
|
1146 connect(lined, SIGNAL(doRename()), |
|
1147 this, SLOT (rename())); |
|
1148 connect(lined, SIGNAL(cancelRename()), |
|
1149 this, SLOT(cancelRename())); |
|
1150 connect(renameTimer, SIGNAL(timeout()), |
|
1151 this, SLOT(doubleClickTimeout())); |
|
1152 connect(changeDirTimer, SIGNAL(timeout()), |
|
1153 this, SLOT(changeDirDuringDrag())); |
|
1154 connect(this, SIGNAL(contentsMoving(int,int)), |
|
1155 this, SLOT(contentsMoved(int,int))); |
|
1156 viewport()->setAcceptDrops(true); |
|
1157 dragItem = 0; |
|
1158 } |
|
1159 |
|
1160 void QFileListBox::show() |
|
1161 { |
|
1162 setBackgroundRole(QPalette::Base); |
|
1163 viewport()->setBackgroundRole(QPalette::Base); |
|
1164 Q3ListBox::show(); |
|
1165 } |
|
1166 |
|
1167 void QFileListBox::keyPressEvent(QKeyEvent *e) |
|
1168 { |
|
1169 if ((e->key() == Qt::Key_Enter || |
|
1170 e->key() == Qt::Key_Return) && |
|
1171 renaming) |
|
1172 return; |
|
1173 |
|
1174 QString keyPressed = ((QKeyEvent *)e)->text().toLower(); |
|
1175 QChar keyChar = keyPressed[0]; |
|
1176 if (keyChar.isLetterOrNumber()) { |
|
1177 Q3ListBoxItem * i = 0; |
|
1178 if (currentItem() != -1) |
|
1179 i = item(currentItem()); |
|
1180 else |
|
1181 i = firstItem(); |
|
1182 if (i->next()) |
|
1183 i = i->next(); |
|
1184 else |
|
1185 i = firstItem(); |
|
1186 while (i != item(currentItem())) { |
|
1187 QString it = text(index(i)); |
|
1188 if (it[0].toLower() == keyChar) { |
|
1189 clearSelection(); |
|
1190 setCurrentItem(i); |
|
1191 } else { |
|
1192 if (i->next()) |
|
1193 i = i->next(); |
|
1194 else { |
|
1195 if (!item(currentItem())) { |
|
1196 clearSelection(); |
|
1197 break; |
|
1198 } |
|
1199 i = firstItem(); |
|
1200 } |
|
1201 } |
|
1202 } |
|
1203 } |
|
1204 cancelRename(); |
|
1205 Q3ListBox::keyPressEvent(e); |
|
1206 } |
|
1207 |
|
1208 void QFileListBox::viewportMousePressEvent(QMouseEvent *e) |
|
1209 { |
|
1210 pressPos = e->pos(); |
|
1211 mousePressed = false; |
|
1212 |
|
1213 bool didRename = renaming; |
|
1214 |
|
1215 cancelRename(); |
|
1216 if (!hasFocus() && !viewport()->hasFocus()) |
|
1217 setFocus(); |
|
1218 |
|
1219 if (e->button() != Qt::LeftButton) { |
|
1220 Q3ListBox::viewportMousePressEvent(e); |
|
1221 firstMousePressEvent = false; |
|
1222 return; |
|
1223 } |
|
1224 |
|
1225 int i = currentItem(); |
|
1226 bool wasSelected = false; |
|
1227 if (i != -1) |
|
1228 wasSelected = item(i)->isSelected(); |
|
1229 Q3ListBox::mousePressEvent(e); |
|
1230 |
|
1231 Q3FileDialogPrivate::MCItem *i1 = (Q3FileDialogPrivate::MCItem*)item(currentItem()); |
|
1232 if (i1) |
|
1233 mousePressed = (!((Q3FileDialogPrivate::File*)i1->i)->info.isDir()) |
|
1234 || (filedialog->mode() == Q3FileDialog::Directory) || (filedialog->mode() == Q3FileDialog::DirectoryOnly); |
|
1235 |
|
1236 if (itemAt(e->pos()) != item(i)) { |
|
1237 firstMousePressEvent = false; |
|
1238 return; |
|
1239 } |
|
1240 |
|
1241 if (!firstMousePressEvent && !didRename && i == currentItem() && currentItem() != -1 && |
|
1242 wasSelected && QUrlInfo(filedialog->d->url.info(QString(QLatin1Char('.')))).isWritable() && item(currentItem())->text() != QLatin1String("..")) { |
|
1243 renameTimer->start(QApplication::doubleClickInterval(), true); |
|
1244 renameItem = item(i); |
|
1245 } |
|
1246 |
|
1247 firstMousePressEvent = false; |
|
1248 } |
|
1249 |
|
1250 void QFileListBox::viewportMouseReleaseEvent(QMouseEvent *e) |
|
1251 { |
|
1252 dragItem = 0; |
|
1253 Q3ListBox::viewportMouseReleaseEvent(e); |
|
1254 mousePressed = false; |
|
1255 } |
|
1256 |
|
1257 void QFileListBox::viewportMouseDoubleClickEvent(QMouseEvent *e) |
|
1258 { |
|
1259 renameTimer->stop(); |
|
1260 Q3ListBox::viewportMouseDoubleClickEvent(e); |
|
1261 } |
|
1262 |
|
1263 void QFileListBox::viewportMouseMoveEvent(QMouseEvent *e) |
|
1264 { |
|
1265 if (!dragItem) |
|
1266 dragItem = itemAt(e->pos()); |
|
1267 renameTimer->stop(); |
|
1268 #ifndef QT_NO_DRAGANDDROP |
|
1269 if ( (pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance() && mousePressed) { |
|
1270 Q3ListBoxItem *item = dragItem; |
|
1271 dragItem = 0; |
|
1272 if (item) { |
|
1273 if (!itemRect(item).contains(e->pos())) |
|
1274 return; |
|
1275 Q3UriDrag* drag = new Q3UriDrag(viewport()); |
|
1276 QStringList files; |
|
1277 if (filedialog->mode() == Q3FileDialog::ExistingFiles) |
|
1278 files = filedialog->selectedFiles(); |
|
1279 else |
|
1280 files = QStringList(filedialog->selectedFile()); |
|
1281 drag->setFileNames(files); |
|
1282 |
|
1283 if (lined->parentWidget()->isVisible()) |
|
1284 cancelRename(); |
|
1285 |
|
1286 connect(drag, SIGNAL(destroyed()), |
|
1287 this, SLOT(dragObjDestroyed())); |
|
1288 drag->drag(); |
|
1289 |
|
1290 mousePressed = false; |
|
1291 } |
|
1292 } else |
|
1293 #endif |
|
1294 { |
|
1295 Q3ListBox::viewportMouseMoveEvent(e); |
|
1296 } |
|
1297 |
|
1298 } |
|
1299 |
|
1300 void QFileListBox::dragObjDestroyed() |
|
1301 { |
|
1302 #ifndef QT_NO_DRAGANDDROP |
|
1303 //####### |
|
1304 //filedialog->rereadDir(); |
|
1305 #endif |
|
1306 } |
|
1307 |
|
1308 #ifndef QT_NO_DRAGANDDROP |
|
1309 void QFileListBox::viewportDragEnterEvent(QDragEnterEvent *e) |
|
1310 { |
|
1311 startDragUrl = filedialog->d->url; |
|
1312 startDragDir = filedialog->dirPath(); |
|
1313 currDropItem = 0; |
|
1314 |
|
1315 if (!Q3UriDrag::canDecode(e)) { |
|
1316 e->ignore(); |
|
1317 return; |
|
1318 } |
|
1319 |
|
1320 QStringList l; |
|
1321 Q3UriDrag::decodeLocalFiles(e, l); |
|
1322 urls = (int)l.count(); |
|
1323 |
|
1324 if (acceptDrop(e->pos(), e->source())) { |
|
1325 e->accept(); |
|
1326 setCurrentDropItem(e->pos()); |
|
1327 } else { |
|
1328 e->ignore(); |
|
1329 setCurrentDropItem(QPoint(-1, -1)); |
|
1330 } |
|
1331 |
|
1332 oldDragPos = e->pos(); |
|
1333 } |
|
1334 |
|
1335 void QFileListBox::viewportDragMoveEvent(QDragMoveEvent *e) |
|
1336 { |
|
1337 if (acceptDrop(e->pos(), e->source())) { |
|
1338 switch (e->action()) { |
|
1339 case QDropEvent::Copy: |
|
1340 e->acceptAction(); |
|
1341 break; |
|
1342 case QDropEvent::Move: |
|
1343 e->acceptAction(); |
|
1344 break; |
|
1345 case QDropEvent::Link: |
|
1346 break; |
|
1347 default: |
|
1348 break; |
|
1349 } |
|
1350 if (oldDragPos != e->pos()) |
|
1351 setCurrentDropItem(e->pos()); |
|
1352 } else { |
|
1353 changeDirTimer->stop(); |
|
1354 e->ignore(); |
|
1355 setCurrentDropItem(QPoint(-1, -1)); |
|
1356 } |
|
1357 |
|
1358 oldDragPos = e->pos(); |
|
1359 } |
|
1360 |
|
1361 void QFileListBox::viewportDragLeaveEvent(QDragLeaveEvent *) |
|
1362 { |
|
1363 changeDirTimer->stop(); |
|
1364 setCurrentDropItem(QPoint(-1, -1)); |
|
1365 //######## |
|
1366 // if (startDragDir != filedialog->d->url) |
|
1367 // filedialog->setUrl(startDragUrl); |
|
1368 } |
|
1369 |
|
1370 void QFileListBox::viewportDropEvent(QDropEvent *e) |
|
1371 { |
|
1372 changeDirTimer->stop(); |
|
1373 |
|
1374 if (!Q3UriDrag::canDecode(e)) { |
|
1375 e->ignore(); |
|
1376 return; |
|
1377 } |
|
1378 |
|
1379 Q3StrList l; |
|
1380 Q3UriDrag::decode(e, l); |
|
1381 |
|
1382 bool move = e->action() == QDropEvent::Move; |
|
1383 // bool supportAction = move || e->action() == QDropEvent::Copy; |
|
1384 |
|
1385 Q3UrlOperator dest; |
|
1386 if (currDropItem) |
|
1387 dest = Q3UrlOperator(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text())); |
|
1388 else |
|
1389 dest = filedialog->d->url; |
|
1390 QStringList lst; |
|
1391 for (uint i = 0; i < l.count(); ++i) { |
|
1392 lst << QLatin1String(l.at(i)); |
|
1393 } |
|
1394 |
|
1395 filedialog->d->url.copy(lst, dest, move); |
|
1396 |
|
1397 // ##### what is supportAction for? |
|
1398 e->acceptAction(); |
|
1399 currDropItem = 0; |
|
1400 } |
|
1401 |
|
1402 bool QFileListBox::acceptDrop(const QPoint &pnt, QWidget *source) |
|
1403 { |
|
1404 Q3ListBoxItem *item = itemAt(pnt); |
|
1405 if (!item || (item && !itemRect(item).contains(pnt))) { |
|
1406 if (source == viewport() && startDragDir == filedialog->dirPath()) |
|
1407 return false; |
|
1408 return true; |
|
1409 } |
|
1410 |
|
1411 QUrlInfo fi(filedialog->d->url.info(item->text().isEmpty() ? QString::fromLatin1(".") : item->text())); |
|
1412 |
|
1413 if (fi.isDir() && itemRect(item).contains(pnt)) |
|
1414 return true; |
|
1415 return false; |
|
1416 } |
|
1417 |
|
1418 void QFileListBox::setCurrentDropItem(const QPoint &pnt) |
|
1419 { |
|
1420 changeDirTimer->stop(); |
|
1421 |
|
1422 Q3ListBoxItem *item = 0; |
|
1423 if (pnt != QPoint(-1, -1)) |
|
1424 item = itemAt(pnt); |
|
1425 if (item && !QUrlInfo(filedialog->d->url.info(item->text().isEmpty() ? QString::fromLatin1(".") : item->text())).isDir()) |
|
1426 item = 0; |
|
1427 if (item && !itemRect(item).contains(pnt)) |
|
1428 item = 0; |
|
1429 |
|
1430 currDropItem = item; |
|
1431 if (currDropItem) |
|
1432 setCurrentItem(currDropItem); |
|
1433 changeDirTimer->start(750); |
|
1434 } |
|
1435 #endif // QT_NO_DRAGANDDROP |
|
1436 |
|
1437 void QFileListBox::changeDirDuringDrag() |
|
1438 { |
|
1439 #ifndef QT_NO_DRAGANDDROP |
|
1440 if (!currDropItem) |
|
1441 return; |
|
1442 changeDirTimer->stop(); |
|
1443 Q3Url u(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text())); |
|
1444 filedialog->setDir(u); |
|
1445 currDropItem = 0; |
|
1446 #endif |
|
1447 } |
|
1448 |
|
1449 void QFileListBox::doubleClickTimeout() |
|
1450 { |
|
1451 startRename(); |
|
1452 renameTimer->stop(); |
|
1453 } |
|
1454 |
|
1455 void QFileListBox::startRename(bool check) |
|
1456 { |
|
1457 if (check && (!renameItem || renameItem != item(currentItem()))) |
|
1458 return; |
|
1459 |
|
1460 int i = currentItem(); |
|
1461 setSelected(i, true); |
|
1462 QRect r = itemRect(item(i)); |
|
1463 int bdr = item(i)->pixmap() ? |
|
1464 item(i)->pixmap()->width() : 16; |
|
1465 int x = r.x() + bdr; |
|
1466 int y = r.y(); |
|
1467 int w = item(i)->width(this) - bdr; |
|
1468 int h = qMax(lined->height() + 2, r.height()); |
|
1469 y = y + r.height() / 2 - h / 2; |
|
1470 |
|
1471 lined->parentWidget()->setGeometry(x, y, w + 6, h); |
|
1472 lined->setFocus(); |
|
1473 lined->setText(item(i)->text()); |
|
1474 lined->selectAll(); |
|
1475 lined->setFrame(false); |
|
1476 lined->parentWidget()->show(); |
|
1477 viewport()->setFocusProxy(lined); |
|
1478 renaming = true; |
|
1479 } |
|
1480 |
|
1481 void QFileListBox::clear() |
|
1482 { |
|
1483 cancelRename(); |
|
1484 Q3ListBox::clear(); |
|
1485 } |
|
1486 |
|
1487 void QFileListBox::rename() |
|
1488 { |
|
1489 if (!lined->text().isEmpty()) { |
|
1490 QString file = currentText(); |
|
1491 |
|
1492 if (lined->text() != file) |
|
1493 filedialog->d->url.rename(file, lined->text()); |
|
1494 } |
|
1495 cancelRename(); |
|
1496 } |
|
1497 |
|
1498 void QFileListBox::cancelRename() |
|
1499 { |
|
1500 renameItem = 0; |
|
1501 lined->parentWidget()->hide(); |
|
1502 viewport()->setFocusProxy(this); |
|
1503 renaming = false; |
|
1504 updateItem(currentItem()); |
|
1505 if (lined->hasFocus()) |
|
1506 viewport()->setFocus(); |
|
1507 } |
|
1508 |
|
1509 void QFileListBox::contentsMoved(int, int) |
|
1510 { |
|
1511 changeDirTimer->stop(); |
|
1512 #ifndef QT_NO_DRAGANDDROP |
|
1513 setCurrentDropItem(QPoint(-1, -1)); |
|
1514 #endif |
|
1515 } |
|
1516 |
|
1517 /************************************************************************ |
|
1518 * |
|
1519 * Internal class QFileListView |
|
1520 * |
|
1521 ************************************************************************/ |
|
1522 |
|
1523 Q3FileDialogQFileListView::Q3FileDialogQFileListView(QWidget *parent, Q3FileDialog *dlg) |
|
1524 : Q3ListView(parent, "qt_filedlg_listview"), renaming(false), renameItem(0), |
|
1525 filedialog(dlg), mousePressed(false), |
|
1526 firstMousePressEvent(true) |
|
1527 { |
|
1528 changeDirTimer = new QTimer(this); |
|
1529 Q3VBox *box = new Q3VBox(viewport(), "qt_vbox"); |
|
1530 box->setFrameStyle(QFrame::Box | QFrame::Plain); |
|
1531 lined = new QRenameEdit(box); |
|
1532 lined->setFixedHeight(lined->sizeHint().height()); |
|
1533 box->hide(); |
|
1534 box->setBackgroundRole(QPalette::Base); |
|
1535 renameTimer = new QTimer(this); |
|
1536 connect(lined, SIGNAL(doRename()), |
|
1537 this, SLOT (rename())); |
|
1538 connect(lined, SIGNAL(cancelRename()), |
|
1539 this, SLOT(cancelRename())); |
|
1540 header()->setMovingEnabled(false); |
|
1541 connect(renameTimer, SIGNAL(timeout()), |
|
1542 this, SLOT(doubleClickTimeout())); |
|
1543 connect(changeDirTimer, SIGNAL(timeout()), |
|
1544 this, SLOT(changeDirDuringDrag())); |
|
1545 disconnect(header(), SIGNAL(sectionClicked(int)), |
|
1546 this, SLOT(changeSortColumn(int))); |
|
1547 connect(header(), SIGNAL(sectionClicked(int)), |
|
1548 this, SLOT(changeSortColumn2(int))); |
|
1549 connect(this, SIGNAL(contentsMoving(int,int)), |
|
1550 this, SLOT(contentsMoved(int,int))); |
|
1551 |
|
1552 viewport()->setAcceptDrops(true); |
|
1553 sortcolumn = 0; |
|
1554 ascending = true; |
|
1555 dragItem = 0; |
|
1556 } |
|
1557 |
|
1558 void Q3FileDialogQFileListView::setSorting(int column, bool increasing) |
|
1559 { |
|
1560 if (column == -1) { |
|
1561 Q3ListView::setSorting(column, increasing); |
|
1562 return; |
|
1563 } |
|
1564 |
|
1565 sortAscending = ascending = increasing; |
|
1566 sortcolumn = column; |
|
1567 switch (column) { |
|
1568 case 0: |
|
1569 sortFilesBy = QDir::Name; |
|
1570 break; |
|
1571 case 1: |
|
1572 sortFilesBy = QDir::Size; |
|
1573 break; |
|
1574 case 3: |
|
1575 sortFilesBy = QDir::Time; |
|
1576 break; |
|
1577 default: |
|
1578 sortFilesBy = QDir::Name; // #### ??? |
|
1579 break; |
|
1580 } |
|
1581 |
|
1582 filedialog->resortDir(); |
|
1583 } |
|
1584 |
|
1585 void Q3FileDialogQFileListView::changeSortColumn2(int column) |
|
1586 { |
|
1587 int lcol = header()->mapToLogical(column); |
|
1588 setSorting(lcol, sortcolumn == lcol ? !ascending : true); |
|
1589 } |
|
1590 |
|
1591 void Q3FileDialogQFileListView::keyPressEvent(QKeyEvent *e) |
|
1592 { |
|
1593 if ((e->key() == Qt::Key_Enter || |
|
1594 e->key() == Qt::Key_Return) && |
|
1595 renaming) |
|
1596 return; |
|
1597 |
|
1598 QString keyPressed = e->text().toLower(); |
|
1599 QChar keyChar = keyPressed[0]; |
|
1600 if (keyChar.isLetterOrNumber()) { |
|
1601 Q3ListViewItem * i = 0; |
|
1602 if (currentItem()) |
|
1603 i = currentItem(); |
|
1604 else |
|
1605 i = firstChild(); |
|
1606 if (i->nextSibling()) |
|
1607 i = i->nextSibling(); |
|
1608 else |
|
1609 i = firstChild(); |
|
1610 while (i != currentItem()) { |
|
1611 QString it = i->text(0); |
|
1612 if (it[0].toLower() == keyChar) { |
|
1613 clearSelection(); |
|
1614 ensureItemVisible(i); |
|
1615 setCurrentItem(i); |
|
1616 } else { |
|
1617 if (i->nextSibling()) |
|
1618 i = i->nextSibling(); |
|
1619 else |
|
1620 i = firstChild(); |
|
1621 } |
|
1622 } |
|
1623 return; |
|
1624 } |
|
1625 |
|
1626 cancelRename(); |
|
1627 Q3ListView::keyPressEvent(e); |
|
1628 } |
|
1629 |
|
1630 void Q3FileDialogQFileListView::viewportMousePressEvent(QMouseEvent *e) |
|
1631 { |
|
1632 pressPos = e->pos(); |
|
1633 mousePressed = false; |
|
1634 |
|
1635 bool didRename = renaming; |
|
1636 cancelRename(); |
|
1637 if (!hasFocus() && !viewport()->hasFocus()) |
|
1638 setFocus(); |
|
1639 |
|
1640 if (e->button() != Qt::LeftButton) { |
|
1641 Q3ListView::viewportMousePressEvent(e); |
|
1642 firstMousePressEvent = false; |
|
1643 return; |
|
1644 } |
|
1645 |
|
1646 Q3ListViewItem *i = currentItem(); |
|
1647 Q3ListView::viewportMousePressEvent(e); |
|
1648 |
|
1649 Q3FileDialogPrivate::File *i1 = (Q3FileDialogPrivate::File*)currentItem(); |
|
1650 if (i1) |
|
1651 mousePressed = !i1->info.isDir() || (filedialog->mode() == Q3FileDialog::Directory) || (filedialog->mode() == Q3FileDialog::DirectoryOnly); |
|
1652 |
|
1653 |
|
1654 if (itemAt(e->pos()) != i || |
|
1655 e->x() + contentsX() > columnWidth(0)) { |
|
1656 firstMousePressEvent = false; |
|
1657 return; |
|
1658 } |
|
1659 |
|
1660 if (!firstMousePressEvent && !didRename && i == currentItem() && currentItem() && |
|
1661 QUrlInfo(filedialog->d->url.info(QString(QLatin1Char('.')))).isWritable() && currentItem()->text(0) != QLatin1String("..")) { |
|
1662 renameTimer->start(QApplication::doubleClickInterval(), true); |
|
1663 renameItem = currentItem(); |
|
1664 } |
|
1665 |
|
1666 firstMousePressEvent = false; |
|
1667 } |
|
1668 |
|
1669 void Q3FileDialogQFileListView::viewportMouseDoubleClickEvent(QMouseEvent *e) |
|
1670 { |
|
1671 renameTimer->stop(); |
|
1672 Q3ListView::viewportMouseDoubleClickEvent(e); |
|
1673 } |
|
1674 |
|
1675 void Q3FileDialogQFileListView::viewportMouseReleaseEvent(QMouseEvent *e) |
|
1676 { |
|
1677 Q3ListView::viewportMouseReleaseEvent(e); |
|
1678 mousePressed = false; |
|
1679 dragItem = 0; |
|
1680 } |
|
1681 |
|
1682 void Q3FileDialogQFileListView::viewportMouseMoveEvent(QMouseEvent *e) |
|
1683 { |
|
1684 renameTimer->stop(); |
|
1685 if (!dragItem) |
|
1686 dragItem = itemAt(e->pos()); |
|
1687 #ifndef QT_NO_DRAGANDDROP |
|
1688 if ( (pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance() && mousePressed) { |
|
1689 Q3ListViewItem *item = dragItem; |
|
1690 dragItem = 0; |
|
1691 if (item) { |
|
1692 Q3UriDrag* drag = new Q3UriDrag(viewport()); |
|
1693 QStringList files; |
|
1694 if (filedialog->mode() == Q3FileDialog::ExistingFiles) |
|
1695 files = filedialog->selectedFiles(); |
|
1696 else |
|
1697 files = QStringList(filedialog->selectedFile()); |
|
1698 drag->setFileNames(files); |
|
1699 |
|
1700 if (lined->isVisible()) |
|
1701 cancelRename(); |
|
1702 |
|
1703 connect(drag, SIGNAL(destroyed()), |
|
1704 this, SLOT(dragObjDestroyed())); |
|
1705 drag->drag(); |
|
1706 |
|
1707 mousePressed = false; |
|
1708 } |
|
1709 } |
|
1710 #endif |
|
1711 } |
|
1712 |
|
1713 void Q3FileDialogQFileListView::dragObjDestroyed() |
|
1714 { |
|
1715 #ifndef QT_NO_DRAGANDDROP |
|
1716 //###### |
|
1717 //filedialog->rereadDir(); |
|
1718 #endif |
|
1719 } |
|
1720 |
|
1721 #ifndef QT_NO_DRAGANDDROP |
|
1722 void Q3FileDialogQFileListView::viewportDragEnterEvent(QDragEnterEvent *e) |
|
1723 { |
|
1724 startDragUrl = filedialog->d->url; |
|
1725 startDragDir = filedialog->dirPath(); |
|
1726 currDropItem = 0; |
|
1727 |
|
1728 if (!Q3UriDrag::canDecode(e)) { |
|
1729 e->ignore(); |
|
1730 return; |
|
1731 } |
|
1732 |
|
1733 QStringList l; |
|
1734 Q3UriDrag::decodeLocalFiles(e, l); |
|
1735 urls = (int)l.count(); |
|
1736 |
|
1737 if (acceptDrop(e->pos(), e->source())) { |
|
1738 e->accept(); |
|
1739 setCurrentDropItem(e->pos()); |
|
1740 } else { |
|
1741 e->ignore(); |
|
1742 setCurrentDropItem(QPoint(-1, -1)); |
|
1743 } |
|
1744 |
|
1745 oldDragPos = e->pos(); |
|
1746 } |
|
1747 |
|
1748 void Q3FileDialogQFileListView::viewportDragMoveEvent(QDragMoveEvent *e) |
|
1749 { |
|
1750 if (acceptDrop(e->pos(), e->source())) { |
|
1751 if (oldDragPos != e->pos()) |
|
1752 setCurrentDropItem(e->pos()); |
|
1753 switch (e->action()) { |
|
1754 case QDropEvent::Copy: |
|
1755 e->acceptAction(); |
|
1756 break; |
|
1757 case QDropEvent::Move: |
|
1758 e->acceptAction(); |
|
1759 break; |
|
1760 case QDropEvent::Link: |
|
1761 break; |
|
1762 default: |
|
1763 break; |
|
1764 } |
|
1765 } else { |
|
1766 changeDirTimer->stop(); |
|
1767 e->ignore(); |
|
1768 setCurrentDropItem(QPoint(-1, -1)); |
|
1769 } |
|
1770 |
|
1771 oldDragPos = e->pos(); |
|
1772 } |
|
1773 |
|
1774 void Q3FileDialogQFileListView::viewportDragLeaveEvent(QDragLeaveEvent *) |
|
1775 { |
|
1776 changeDirTimer->stop(); |
|
1777 setCurrentDropItem(QPoint(-1, -1)); |
|
1778 //######## |
|
1779 // if (startDragDir != filedialog->d->url) |
|
1780 // filedialog->setUrl(startDragUrl); |
|
1781 } |
|
1782 |
|
1783 void Q3FileDialogQFileListView::viewportDropEvent(QDropEvent *e) |
|
1784 { |
|
1785 changeDirTimer->stop(); |
|
1786 |
|
1787 if (!Q3UriDrag::canDecode(e)) { |
|
1788 e->ignore(); |
|
1789 return; |
|
1790 } |
|
1791 |
|
1792 QStringList l; |
|
1793 Q3UriDrag::decodeToUnicodeUris(e, l); |
|
1794 |
|
1795 bool move = e->action() == QDropEvent::Move; |
|
1796 // bool supportAction = move || e->action() == QDropEvent::Copy; |
|
1797 |
|
1798 Q3UrlOperator dest; |
|
1799 if (currDropItem) |
|
1800 dest = Q3UrlOperator(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text(0))); |
|
1801 else |
|
1802 dest = filedialog->d->url; |
|
1803 filedialog->d->url.copy(l, dest, move); |
|
1804 |
|
1805 // ##### what is supportAction for? |
|
1806 e->acceptAction(); |
|
1807 currDropItem = 0; |
|
1808 } |
|
1809 |
|
1810 bool Q3FileDialogQFileListView::acceptDrop(const QPoint &pnt, QWidget *source) |
|
1811 { |
|
1812 Q3ListViewItem *item = itemAt(pnt); |
|
1813 if (!item || (item && !itemRect(item).contains(pnt))) { |
|
1814 if (source == viewport() && startDragDir == filedialog->dirPath()) |
|
1815 return false; |
|
1816 return true; |
|
1817 } |
|
1818 |
|
1819 QUrlInfo fi(filedialog->d->url.info(item->text(0).isEmpty() ? QString::fromLatin1(".") : item->text(0))); |
|
1820 |
|
1821 if (fi.isDir() && itemRect(item).contains(pnt)) |
|
1822 return true; |
|
1823 return false; |
|
1824 } |
|
1825 |
|
1826 void Q3FileDialogQFileListView::setCurrentDropItem(const QPoint &pnt) |
|
1827 { |
|
1828 changeDirTimer->stop(); |
|
1829 |
|
1830 Q3ListViewItem *item = itemAt(pnt); |
|
1831 if (pnt == QPoint(-1, -1)) |
|
1832 item = 0; |
|
1833 if (item && !QUrlInfo(filedialog->d->url.info(item->text(0).isEmpty() ? QString::fromLatin1(".") : item->text(0))).isDir()) |
|
1834 item = 0; |
|
1835 |
|
1836 if (item && !itemRect(item).contains(pnt)) |
|
1837 item = 0; |
|
1838 |
|
1839 currDropItem = item; |
|
1840 |
|
1841 if (currDropItem) |
|
1842 setCurrentItem(currDropItem); |
|
1843 |
|
1844 changeDirTimer->start(750); |
|
1845 } |
|
1846 #endif // QT_NO_DRAGANDDROP |
|
1847 |
|
1848 void Q3FileDialogQFileListView::changeDirDuringDrag() |
|
1849 { |
|
1850 #ifndef QT_NO_DRAGANDDROP |
|
1851 if (!currDropItem) |
|
1852 return; |
|
1853 changeDirTimer->stop(); |
|
1854 Q3Url u(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text(0))); |
|
1855 filedialog->setDir(u); |
|
1856 currDropItem = 0; |
|
1857 #endif // QT_NO_DRAGANDDROP |
|
1858 } |
|
1859 |
|
1860 |
|
1861 void Q3FileDialogQFileListView::doubleClickTimeout() |
|
1862 { |
|
1863 startRename(); |
|
1864 renameTimer->stop(); |
|
1865 } |
|
1866 |
|
1867 void Q3FileDialogQFileListView::startRename(bool check) |
|
1868 { |
|
1869 if (check && (!renameItem || renameItem != currentItem())) |
|
1870 return; |
|
1871 |
|
1872 Q3ListViewItem *i = currentItem(); |
|
1873 setSelected(i, true); |
|
1874 |
|
1875 QRect r = itemRect(i); |
|
1876 int bdr = i->pixmap(0) ? |
|
1877 i->pixmap(0)->width() : 16; |
|
1878 int x = r.x() + bdr; |
|
1879 int y = r.y(); |
|
1880 int w = columnWidth(0) - bdr; |
|
1881 int h = qMax(lined->height() + 2, r.height()); |
|
1882 y = y + r.height() / 2 - h / 2; |
|
1883 |
|
1884 lined->parentWidget()->setGeometry(x, y, w + 6, h); |
|
1885 lined->setFocus(); |
|
1886 lined->setText(i->text(0)); |
|
1887 lined->selectAll(); |
|
1888 lined->setFrame(false); |
|
1889 lined->parentWidget()->show(); |
|
1890 viewport()->setFocusProxy(lined); |
|
1891 renaming = true; |
|
1892 } |
|
1893 |
|
1894 void Q3FileDialogQFileListView::clear() |
|
1895 { |
|
1896 cancelRename(); |
|
1897 Q3ListView::clear(); |
|
1898 } |
|
1899 |
|
1900 void Q3FileDialogQFileListView::rename() |
|
1901 { |
|
1902 if (!lined->text().isEmpty()) { |
|
1903 QString file = currentItem()->text(0); |
|
1904 |
|
1905 if (lined->text() != file) |
|
1906 filedialog->d->url.rename(file, lined->text()); |
|
1907 } |
|
1908 cancelRename(); |
|
1909 } |
|
1910 |
|
1911 void Q3FileDialogQFileListView::cancelRename() |
|
1912 { |
|
1913 renameItem = 0; |
|
1914 lined->parentWidget()->hide(); |
|
1915 viewport()->setFocusProxy(this); |
|
1916 renaming = false; |
|
1917 if (currentItem()) |
|
1918 currentItem()->repaint(); |
|
1919 if (lined->hasFocus()) |
|
1920 viewport()->setFocus(); |
|
1921 } |
|
1922 |
|
1923 void Q3FileDialogQFileListView::contentsMoved(int, int) |
|
1924 { |
|
1925 changeDirTimer->stop(); |
|
1926 #ifndef QT_NO_DRAGANDDROP |
|
1927 setCurrentDropItem(QPoint(-1, -1)); |
|
1928 #endif |
|
1929 } |
|
1930 |
|
1931 |
|
1932 Q3FileDialogPrivate::File::~File() |
|
1933 { |
|
1934 if (d->pendingItems.findRef(this)) |
|
1935 d->pendingItems.removeRef(this); |
|
1936 } |
|
1937 |
|
1938 QString Q3FileDialogPrivate::File::text(int column) const |
|
1939 { |
|
1940 makeVariables(); |
|
1941 |
|
1942 switch(column) { |
|
1943 case 0: |
|
1944 return info.name(); |
|
1945 case 1: |
|
1946 if (info.isFile()) { |
|
1947 QIODevice::Offset size = info.size(); |
|
1948 return QString::number(size); |
|
1949 } else { |
|
1950 return QString::fromLatin1(""); |
|
1951 } |
|
1952 case 2: |
|
1953 if (info.isFile() && info.isSymLink()) { |
|
1954 return d->symLinkToFile; |
|
1955 } else if (info.isFile()) { |
|
1956 return d->file; |
|
1957 } else if (info.isDir() && info.isSymLink()) { |
|
1958 return d->symLinkToDir; |
|
1959 } else if (info.isDir()) { |
|
1960 return d->dir; |
|
1961 } else if (info.isSymLink()) { |
|
1962 return d->symLinkToSpecial; |
|
1963 } else { |
|
1964 return d->special; |
|
1965 } |
|
1966 case 3: { |
|
1967 return info.lastModified().toString(Qt::LocalDate); |
|
1968 } |
|
1969 case 4: |
|
1970 if (info.isReadable()) |
|
1971 return info.isWritable() ? d->rw : d->ro; |
|
1972 else |
|
1973 return info.isWritable() ? d->wo : d->inaccessible; |
|
1974 } |
|
1975 |
|
1976 return QString::fromLatin1("<--->"); |
|
1977 } |
|
1978 |
|
1979 const QPixmap * Q3FileDialogPrivate::File::pixmap(int column) const |
|
1980 { |
|
1981 if (column) { |
|
1982 return 0; |
|
1983 } else if (Q3ListViewItem::pixmap(column)) { |
|
1984 return Q3ListViewItem::pixmap(column); |
|
1985 } else if (info.isSymLink()) { |
|
1986 if (info.isFile()) |
|
1987 return symLinkFileIcon; |
|
1988 else |
|
1989 return symLinkDirIcon; |
|
1990 } else if (info.isDir()) { |
|
1991 return closedFolderIcon; |
|
1992 } else if (info.isFile()) { |
|
1993 return fileIcon; |
|
1994 } else { |
|
1995 return fifteenTransparentPixels; |
|
1996 } |
|
1997 } |
|
1998 |
|
1999 Q3FileDialogPrivate::MCItem::MCItem(Q3ListBox * lb, Q3ListViewItem * item) |
|
2000 : Q3ListBoxItem() |
|
2001 { |
|
2002 i = item; |
|
2003 if (lb) |
|
2004 lb->insertItem(this); |
|
2005 } |
|
2006 |
|
2007 Q3FileDialogPrivate::MCItem::MCItem(Q3ListBox * lb, Q3ListViewItem * item, Q3ListBoxItem *after) |
|
2008 : Q3ListBoxItem() |
|
2009 { |
|
2010 i = item; |
|
2011 if (lb) |
|
2012 lb->insertItem(this, after); |
|
2013 } |
|
2014 |
|
2015 QString Q3FileDialogPrivate::MCItem::text() const |
|
2016 { |
|
2017 return i->text(0); |
|
2018 } |
|
2019 |
|
2020 |
|
2021 const QPixmap *Q3FileDialogPrivate::MCItem::pixmap() const |
|
2022 { |
|
2023 return i->pixmap(0); |
|
2024 } |
|
2025 |
|
2026 |
|
2027 int Q3FileDialogPrivate::MCItem::height(const Q3ListBox * lb) const |
|
2028 { |
|
2029 int hf = lb->fontMetrics().height(); |
|
2030 int hp = pixmap() ? pixmap()->height() : 0; |
|
2031 return qMax(hf, hp) + 2; |
|
2032 } |
|
2033 |
|
2034 |
|
2035 int Q3FileDialogPrivate::MCItem::width(const Q3ListBox * lb) const |
|
2036 { |
|
2037 QFontMetrics fm = lb->fontMetrics(); |
|
2038 int w = 2; |
|
2039 if (pixmap()) |
|
2040 w += pixmap()->width() + 4; |
|
2041 else |
|
2042 w += 18; |
|
2043 w += fm.width(text()); |
|
2044 w += -fm.minLeftBearing(); |
|
2045 w += -fm.minRightBearing(); |
|
2046 w += 6; |
|
2047 return w; |
|
2048 } |
|
2049 |
|
2050 |
|
2051 void Q3FileDialogPrivate::MCItem::paint(QPainter * ptr) |
|
2052 { |
|
2053 QFontMetrics fm = ptr->fontMetrics(); |
|
2054 |
|
2055 int h; |
|
2056 |
|
2057 if (pixmap()) |
|
2058 h = qMax(fm.height(), pixmap()->height()) + 2; |
|
2059 else |
|
2060 h = fm.height() + 2; |
|
2061 |
|
2062 const QPixmap * pm = pixmap(); |
|
2063 if (pm) |
|
2064 ptr->drawPixmap(2, 1, *pm); |
|
2065 |
|
2066 ptr->drawText(pm ? pm->width() + 4 : 22, h - fm.descent() - 2, |
|
2067 text()); |
|
2068 } |
|
2069 |
|
2070 static QStringList makeFiltersList(const QString &filter) |
|
2071 { |
|
2072 if (filter.isEmpty()) |
|
2073 return QStringList(); |
|
2074 |
|
2075 int i = filter.indexOf(QLatin1String(";;"), 0); |
|
2076 QString sep(QLatin1String(";;")); |
|
2077 if (i == -1) { |
|
2078 if (filter.contains(QLatin1Char('\n'))) { |
|
2079 sep = QLatin1Char('\n'); |
|
2080 i = filter.indexOf(sep); |
|
2081 } |
|
2082 } |
|
2083 |
|
2084 return QStringList::split(sep, filter); |
|
2085 } |
|
2086 |
|
2087 /*! |
|
2088 \class Q3FileDialog |
|
2089 \brief The Q3FileDialog class provides dialogs that allow users to select files or directories. |
|
2090 |
|
2091 \compat |
|
2092 |
|
2093 The Q3FileDialog class enables a user to traverse their file system in |
|
2094 order to select one or many files or a directory. |
|
2095 |
|
2096 The easiest way to create a Q3FileDialog is to use the static |
|
2097 functions. On Windows, these static functions will call the native |
|
2098 Windows file dialog and on Mac OS X, these static function will call |
|
2099 the native Mac OS X file dialog. |
|
2100 |
|
2101 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 0 |
|
2102 |
|
2103 In the above example, a modal Q3FileDialog is created using a static |
|
2104 function. The startup directory is set to "/home". The file filter |
|
2105 is set to "Images (*.png *.xpm *.jpg)". The parent of the file dialog |
|
2106 is set to \e this and it is given the identification name - "open file |
|
2107 dialog". The caption at the top of file dialog is set to "Choose a |
|
2108 file". If you want to use multiple filters, separate each one with |
|
2109 \e two semicolons, e.g. |
|
2110 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 1 |
|
2111 |
|
2112 You can create your own Q3FileDialog without using the static |
|
2113 functions. By calling setMode(), you can set what can be returned by |
|
2114 the Q3FileDialog. |
|
2115 |
|
2116 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 2 |
|
2117 |
|
2118 In the above example, the mode of the file dialog is set to \l |
|
2119 AnyFile, meaning that the user can select any file, or even specify a |
|
2120 file that doesn't exist. This mode is useful for creating a "File Save |
|
2121 As" file dialog. Use \l ExistingFile if the user must select an |
|
2122 existing file or \l Directory if only a directory may be selected. |
|
2123 (See the \l Q3FileDialog::Mode enum for the complete list of modes.) |
|
2124 |
|
2125 You can retrieve the dialog's mode with mode(). Use setFilter() to set |
|
2126 the dialog's file filter, e.g. |
|
2127 |
|
2128 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 3 |
|
2129 |
|
2130 In the above example, the filter is set to "Images (*.png *.xpm |
|
2131 *.jpg)", this means that only files with the extension \c png, \c xpm |
|
2132 or \c jpg will be shown in the Q3FileDialog. You can apply |
|
2133 several filters by using setFilters() and add additional filters with |
|
2134 addFilter(). Use setSelectedFilter() to select one of the filters |
|
2135 you've given as the file dialog's default filter. Whenever the user |
|
2136 changes the filter the filterSelected() signal is emitted. |
|
2137 |
|
2138 The file dialog has two view modes, Q3FileDialog::List which simply |
|
2139 lists file and directory names and Q3FileDialog::Detail which |
|
2140 displays additional information alongside each name, e.g. file size, |
|
2141 modification date, etc. Set the mode with setViewMode(). |
|
2142 |
|
2143 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 4 |
|
2144 |
|
2145 The last important function you will need to use when creating your |
|
2146 own file dialog is selectedFile(). |
|
2147 |
|
2148 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 5 |
|
2149 |
|
2150 In the above example, a modal file dialog is created and shown. If |
|
2151 the user clicked OK, then the file they selected is put in \c |
|
2152 fileName. |
|
2153 |
|
2154 If you are using the \l ExistingFiles mode then you will need to use |
|
2155 selectedFiles() which will return the selected files in a QStringList. |
|
2156 |
|
2157 The dialog's working directory can be set with setDir(). The display |
|
2158 of hidden files is controlled with setShowHiddenFiles(). The dialog |
|
2159 can be forced to re-read the directory with rereadDir() and re-sort |
|
2160 the directory with resortDir(). All the files in the current directory |
|
2161 can be selected with selectAll(). |
|
2162 |
|
2163 \section1 Creating and using preview widgets |
|
2164 |
|
2165 There are two kinds of preview widgets that can be used with |
|
2166 Q3FileDialogs: \e content preview widgets and \e information preview |
|
2167 widgets. They are created and used in the same way except that the |
|
2168 function names differ, e.g. setContentsPreview() and setInfoPreview(). |
|
2169 |
|
2170 A preview widget is a widget that is placed inside a Q3FileDialog so |
|
2171 that the user can see either the contents of the file, or information |
|
2172 about the file. |
|
2173 |
|
2174 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 6 |
|
2175 |
|
2176 In the above snippet, we create a preview widget which inherits from |
|
2177 QLabel and Q3FilePreview. File preview widgets \e must inherit from |
|
2178 Q3FilePreview. |
|
2179 |
|
2180 Inside the class we reimplement Q3FilePreview::previewUrl(), this is |
|
2181 where we determine what happens when a file is selected. In the |
|
2182 above example we only show a preview of the file if it is a valid |
|
2183 pixmap. Here's how to make a file dialog use a preview widget: |
|
2184 |
|
2185 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 7 |
|
2186 |
|
2187 The first line creates an instance of our preview widget. We then |
|
2188 create our file dialog and call setContentsPreviewEnabled(true), |
|
2189 this tell the file dialog to preview the contents of the currently |
|
2190 selected file. We then call setContentsPreview() -- note that we pass |
|
2191 the same preview widget twice. Finally, before showing the file |
|
2192 dialog, we call setPreviewMode() setting the mode to \e Contents which |
|
2193 will show the contents preview of the file that the user has selected. |
|
2194 |
|
2195 If you create another preview widget that is used for displaying |
|
2196 information about a file, create it in the same way as the contents |
|
2197 preview widget and call setInfoPreviewEnabled(), and |
|
2198 setInfoPreview(). Then the user will be able to switch between the |
|
2199 two preview modes. |
|
2200 |
|
2201 For more information about creating a Q3FilePreview widget see |
|
2202 \l{Q3FilePreview}. |
|
2203 */ |
|
2204 |
|
2205 |
|
2206 /*! \enum Q3FileDialog::Mode |
|
2207 |
|
2208 This enum is used to indicate what the user may select in the file |
|
2209 dialog, i.e. what the dialog will return if the user clicks OK. |
|
2210 |
|
2211 \value AnyFile The name of a file, whether it exists or not. |
|
2212 \value ExistingFile The name of a single existing file. |
|
2213 \value Directory The name of a directory. Both files and directories |
|
2214 are displayed. |
|
2215 \value DirectoryOnly The name of a directory. The file dialog will only display directories. |
|
2216 \value ExistingFiles The names of zero or more existing files. |
|
2217 |
|
2218 See setMode(). |
|
2219 */ |
|
2220 |
|
2221 /*! |
|
2222 \enum Q3FileDialog::ViewMode |
|
2223 |
|
2224 This enum describes the view mode of the file dialog, i.e. what |
|
2225 information about each file will be displayed. |
|
2226 |
|
2227 \value List Display file and directory names with icons. |
|
2228 \value Detail Display file and directory names with icons plus |
|
2229 additional information, such as file size and modification date. |
|
2230 |
|
2231 See setViewMode(). |
|
2232 */ |
|
2233 |
|
2234 /*! |
|
2235 \enum Q3FileDialog::PreviewMode |
|
2236 |
|
2237 This enum describes the preview mode of the file dialog. |
|
2238 |
|
2239 \value NoPreview No preview is shown at all. |
|
2240 \value Contents Show a preview of the contents of the current file |
|
2241 using the contents preview widget. |
|
2242 \value Info Show information about the current file using the |
|
2243 info preview widget. |
|
2244 |
|
2245 See setPreviewMode(), setContentsPreview() and setInfoPreview(). |
|
2246 */ |
|
2247 |
|
2248 /*! |
|
2249 \fn void Q3FileDialog::detailViewSelectionChanged() |
|
2250 \internal |
|
2251 */ |
|
2252 |
|
2253 /*! |
|
2254 \fn void Q3FileDialog::listBoxSelectionChanged() |
|
2255 \internal |
|
2256 */ |
|
2257 |
|
2258 extern const char qt3_file_dialog_filter_reg_exp[] = "([a-zA-Z0-9]*)\\(([a-zA-Z0-9_.*? +;#\\[\\]]*)\\)$"; |
|
2259 |
|
2260 /*! |
|
2261 Constructs a file dialog called \a name, with the parent, \a parent. |
|
2262 If \a modal is true then the file dialog is modal; otherwise it is |
|
2263 modeless. |
|
2264 */ |
|
2265 |
|
2266 Q3FileDialog::Q3FileDialog(QWidget *parent, const char *name, bool modal) |
|
2267 : QDialog(parent, name, modal, |
|
2268 (modal ? |
|
2269 (Qt::WStyle_Customize | Qt::WStyle_DialogBorder | Qt::WStyle_Title | Qt::WStyle_SysMenu) : Qt::WindowFlags(0))) |
|
2270 { |
|
2271 init(); |
|
2272 d->mode = ExistingFile; |
|
2273 d->types->insertItem(tr("All Files (*)")); |
|
2274 d->cursorOverride = false; |
|
2275 emit dirEntered(d->url.dirPath()); |
|
2276 rereadDir(); |
|
2277 } |
|
2278 |
|
2279 |
|
2280 /*! |
|
2281 Constructs a file dialog called \a name with the parent, \a parent. |
|
2282 If \a modal is true then the file dialog is modal; otherwise it is |
|
2283 modeless. |
|
2284 |
|
2285 If \a dirName is specified then it will be used as the dialog's |
|
2286 working directory, i.e. it will be the directory that is shown when |
|
2287 the dialog appears. If \a filter is specified it will be used as the |
|
2288 dialog's file filter. |
|
2289 |
|
2290 */ |
|
2291 |
|
2292 Q3FileDialog::Q3FileDialog(const QString& dirName, const QString & filter, |
|
2293 QWidget *parent, const char *name, bool modal) |
|
2294 : QDialog(parent, name, modal, |
|
2295 (modal ? (Qt::WStyle_Customize | Qt::WStyle_DialogBorder | Qt::WStyle_Title | Qt::WStyle_SysMenu) |
|
2296 : Qt::WindowFlags(0))) |
|
2297 { |
|
2298 init(); |
|
2299 d->mode = ExistingFile; |
|
2300 rereadDir(); |
|
2301 Q3UrlOperator u(dirName); |
|
2302 if (!dirName.isEmpty() && (!u.isLocalFile() || QDir(dirName).exists())) |
|
2303 setSelection(dirName); |
|
2304 else if (workingDirectory && !workingDirectory->isEmpty()) |
|
2305 setDir(*workingDirectory); |
|
2306 |
|
2307 if (!filter.isEmpty()) { |
|
2308 setFilters(filter); |
|
2309 if (!dirName.isEmpty()) { |
|
2310 int dotpos = dirName.indexOf(QLatin1Char('.'), 0, Qt::CaseInsensitive); |
|
2311 if (dotpos != -1) { |
|
2312 for (int b=0 ; b<d->types->count() ; b++) { |
|
2313 if (d->types->text(b).contains(dirName.right(dirName.length() - dotpos))) { |
|
2314 d->types->setCurrentItem(b); |
|
2315 setFilter(d->types->text(b)); |
|
2316 return; |
|
2317 } |
|
2318 } |
|
2319 } |
|
2320 } |
|
2321 } else { |
|
2322 d->types->insertItem(tr("All Files (*)")); |
|
2323 } |
|
2324 } |
|
2325 |
|
2326 |
|
2327 /*! |
|
2328 \internal |
|
2329 Initializes the file dialog. |
|
2330 */ |
|
2331 |
|
2332 void Q3FileDialog::init() |
|
2333 { |
|
2334 setSizeGripEnabled(true); |
|
2335 d = new Q3FileDialogPrivate(); |
|
2336 d->mode = AnyFile; |
|
2337 d->last = 0; |
|
2338 d->lastEFSelected = 0; |
|
2339 d->moreFiles = 0; |
|
2340 d->infoPreview = false; |
|
2341 d->contentsPreview = false; |
|
2342 d->hadDotDot = false; |
|
2343 d->ignoreNextKeyPress = false; |
|
2344 d->progressDia = 0; |
|
2345 d->checkForFilter = false; |
|
2346 d->ignoreNextRefresh = false; |
|
2347 d->ignoreStop = false; |
|
2348 d->mimeTypeTimer = new QTimer(this); |
|
2349 d->cursorOverride = false; |
|
2350 connect(d->mimeTypeTimer, SIGNAL(timeout()), |
|
2351 this, SLOT(doMimeTypeLookup())); |
|
2352 |
|
2353 d->url = Q3UrlOperator(toRootIfNotExists( QDir::currentDirPath() )); |
|
2354 d->oldUrl = d->url; |
|
2355 d->currListChildren = 0; |
|
2356 |
|
2357 connect(&d->url, SIGNAL(start(Q3NetworkOperation*)), |
|
2358 this, SLOT(urlStart(Q3NetworkOperation*))); |
|
2359 connect(&d->url, SIGNAL(finished(Q3NetworkOperation*)), |
|
2360 this, SLOT(urlFinished(Q3NetworkOperation*))); |
|
2361 connect(&d->url, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)), |
|
2362 this, SLOT(insertEntry(Q3ValueList<QUrlInfo>,Q3NetworkOperation*))); |
|
2363 connect(&d->url, SIGNAL(removed(Q3NetworkOperation*)), |
|
2364 this, SLOT(removeEntry(Q3NetworkOperation*))); |
|
2365 connect(&d->url, SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)), |
|
2366 this, SLOT(createdDirectory(QUrlInfo,Q3NetworkOperation*))); |
|
2367 connect(&d->url, SIGNAL(itemChanged(Q3NetworkOperation*)), |
|
2368 this, SLOT(itemChanged(Q3NetworkOperation*))); |
|
2369 connect(&d->url, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)), |
|
2370 this, SLOT(dataTransferProgress(int,int,Q3NetworkOperation*))); |
|
2371 |
|
2372 nameEdit = new QLineEdit(this, "name/filter editor"); |
|
2373 nameEdit->setMaxLength(255); //_POSIX_MAX_PATH |
|
2374 connect(nameEdit, SIGNAL(textChanged(QString)), |
|
2375 this, SLOT(fileNameEditDone())); |
|
2376 nameEdit->installEventFilter(this); |
|
2377 |
|
2378 d->splitter = new QSplitter(this, "qt_splitter"); |
|
2379 |
|
2380 d->stack = new Q3WidgetStack(d->splitter, "files and more files"); |
|
2381 |
|
2382 d->splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); |
|
2383 |
|
2384 files = new Q3FileDialogQFileListView(d->stack, this); |
|
2385 QFontMetrics fm = fontMetrics(); |
|
2386 files->addColumn(tr("Name")); |
|
2387 files->addColumn(tr("Size")); |
|
2388 files->setColumnAlignment(1, Qt::AlignRight); |
|
2389 files->addColumn(tr("Type")); |
|
2390 files->addColumn(tr("Date")); |
|
2391 files->addColumn(tr("Attributes")); |
|
2392 files->header()->setStretchEnabled(true, 0); |
|
2393 |
|
2394 files->setMinimumSize(50, 25 + 2*fm.lineSpacing()); |
|
2395 |
|
2396 connect(files, SIGNAL(selectionChanged()), |
|
2397 this, SLOT(detailViewSelectionChanged())); |
|
2398 connect(files, SIGNAL(currentChanged(Q3ListViewItem*)), |
|
2399 this, SLOT(updateFileNameEdit(Q3ListViewItem*))); |
|
2400 connect(files, SIGNAL(doubleClicked(Q3ListViewItem*)), |
|
2401 this, SLOT(selectDirectoryOrFile(Q3ListViewItem*))); |
|
2402 connect(files, SIGNAL(returnPressed(Q3ListViewItem*)), |
|
2403 this, SLOT(selectDirectoryOrFile(Q3ListViewItem*))); |
|
2404 connect(files, SIGNAL(contextMenuRequested(Q3ListViewItem*,QPoint,int)), |
|
2405 this, SLOT(popupContextMenu(Q3ListViewItem*,QPoint,int))); |
|
2406 |
|
2407 files->installEventFilter(this); |
|
2408 files->viewport()->installEventFilter(this); |
|
2409 |
|
2410 d->moreFiles = new QFileListBox(d->stack, this); |
|
2411 d->moreFiles->setRowMode(Q3ListBox::FitToHeight); |
|
2412 d->moreFiles->setVariableWidth(true); |
|
2413 |
|
2414 connect(d->moreFiles, SIGNAL(selected(Q3ListBoxItem*)), |
|
2415 this, SLOT(selectDirectoryOrFile(Q3ListBoxItem*))); |
|
2416 connect(d->moreFiles, SIGNAL(selectionChanged()), |
|
2417 this, SLOT(listBoxSelectionChanged())); |
|
2418 connect(d->moreFiles, SIGNAL(highlighted(Q3ListBoxItem*)), |
|
2419 this, SLOT(updateFileNameEdit(Q3ListBoxItem*))); |
|
2420 connect(d->moreFiles, SIGNAL(contextMenuRequested(Q3ListBoxItem*,QPoint)), |
|
2421 this, SLOT(popupContextMenu(Q3ListBoxItem*,QPoint))); |
|
2422 |
|
2423 d->moreFiles->installEventFilter(this); |
|
2424 d->moreFiles->viewport()->installEventFilter(this); |
|
2425 |
|
2426 okB = new QPushButton(tr("&OK"), this, "OK"); //### Or "Save (see other "OK") |
|
2427 okB->setDefault(true); |
|
2428 okB->setEnabled(false); |
|
2429 connect(okB, SIGNAL(clicked()), this, SLOT(okClicked())); |
|
2430 cancelB = new QPushButton(tr("Cancel") , this, "Cancel"); |
|
2431 connect(cancelB, SIGNAL(clicked()), this, SLOT(cancelClicked())); |
|
2432 |
|
2433 d->paths = new Q3ComboBox(true, this, "directory history/editor"); |
|
2434 d->paths->setDuplicatesEnabled(false); |
|
2435 d->paths->setInsertionPolicy(Q3ComboBox::NoInsertion); |
|
2436 makeVariables(); |
|
2437 |
|
2438 QFileInfoList rootDrives = QDir::drives(); |
|
2439 for (int i = 0; i < rootDrives.size(); ++i) { |
|
2440 QFileInfo fi = rootDrives.at(i); |
|
2441 d->paths->insertItem(*openFolderIcon, fi.absFilePath()); |
|
2442 } |
|
2443 |
|
2444 if (QDir::homeDirPath().size()) { |
|
2445 if (!d->paths->listBox()->findItem(QDir::homeDirPath())) |
|
2446 d->paths->insertItem(*openFolderIcon, QDir::homeDirPath()); |
|
2447 } |
|
2448 |
|
2449 connect(d->paths, SIGNAL(activated(QString)), |
|
2450 this, SLOT(setDir(QString))); |
|
2451 |
|
2452 d->paths->installEventFilter(this); |
|
2453 QObjectList ol = d->paths->queryList("QLineEdit"); |
|
2454 if (ol.size()) |
|
2455 ol.at(0)->installEventFilter(this); |
|
2456 |
|
2457 d->geometryDirty = true; |
|
2458 d->types = new QComboBox(true, this, "file types"); |
|
2459 d->types->setDuplicatesEnabled(false); |
|
2460 d->types->setEditable(false); |
|
2461 connect(d->types, SIGNAL(activated(QString)), |
|
2462 this, SLOT(setFilter(QString))); |
|
2463 connect(d->types, SIGNAL(activated(QString)), |
|
2464 this, SIGNAL(filterSelected(QString))); |
|
2465 |
|
2466 d->pathL = new QLabel(d->paths, tr("Look &in:"), this, "qt_looin_lbl"); |
|
2467 d->fileL = new QLabel(nameEdit, tr("File &name:"), this, "qt_filename_lbl"); |
|
2468 d->typeL = new QLabel(d->types, tr("File &type:"), this, "qt_filetype_lbl"); |
|
2469 |
|
2470 d->goBack = new QToolButton(this, "go back"); |
|
2471 d->goBack->setEnabled(false); |
|
2472 d->goBack->setFocusPolicy(Qt::TabFocus); |
|
2473 connect(d->goBack, SIGNAL(clicked()), this, SLOT(goBack())); |
|
2474 #ifndef QT_NO_TOOLTIP |
|
2475 QToolTip::add(d->goBack, tr("Back")); |
|
2476 #endif |
|
2477 d->goBack->setIconSet(*goBackIcon); |
|
2478 |
|
2479 d->cdToParent = new QToolButton(this, "cd to parent"); |
|
2480 d->cdToParent->setFocusPolicy(Qt::TabFocus); |
|
2481 #ifndef QT_NO_TOOLTIP |
|
2482 QToolTip::add(d->cdToParent, tr("One directory up")); |
|
2483 #endif |
|
2484 d->cdToParent->setIconSet(*cdToParentIcon); |
|
2485 connect(d->cdToParent, SIGNAL(clicked()), |
|
2486 this, SLOT(cdUpClicked())); |
|
2487 |
|
2488 d->newFolder = new QToolButton(this, "new folder"); |
|
2489 d->newFolder->setFocusPolicy(Qt::TabFocus); |
|
2490 #ifndef QT_NO_TOOLTIP |
|
2491 QToolTip::add(d->newFolder, tr("Create New Folder")); |
|
2492 #endif |
|
2493 d->newFolder->setIconSet(*newFolderIcon); |
|
2494 connect(d->newFolder, SIGNAL(clicked()), |
|
2495 this, SLOT(newFolderClicked())); |
|
2496 |
|
2497 d->modeButtons = new Q3ButtonGroup(0, "invisible group"); |
|
2498 connect(d->modeButtons, SIGNAL(destroyed()), |
|
2499 this, SLOT(modeButtonsDestroyed())); |
|
2500 d->modeButtons->setExclusive(true); |
|
2501 connect(d->modeButtons, SIGNAL(clicked(int)), |
|
2502 d->stack, SLOT(raiseWidget(int))); |
|
2503 connect(d->modeButtons, SIGNAL(clicked(int)), |
|
2504 this, SLOT(changeMode(int))); |
|
2505 |
|
2506 d->mcView = new QToolButton(this, "mclistbox view"); |
|
2507 d->mcView->setFocusPolicy(Qt::TabFocus); |
|
2508 #ifndef QT_NO_TOOLTIP |
|
2509 QToolTip::add(d->mcView, tr("List View")); |
|
2510 #endif |
|
2511 d->mcView->setIconSet(*multiColumnListViewIcon); |
|
2512 d->mcView->setToggleButton(true); |
|
2513 d->stack->addWidget(d->moreFiles, d->modeButtons->insert(d->mcView)); |
|
2514 d->detailView = new QToolButton(this, "list view"); |
|
2515 d->detailView->setFocusPolicy(Qt::TabFocus); |
|
2516 #ifndef QT_NO_TOOLTIP |
|
2517 QToolTip::add(d->detailView, tr("Detail View")); |
|
2518 #endif |
|
2519 d->detailView->setIconSet(*detailViewIcon); |
|
2520 d->detailView->setToggleButton(true); |
|
2521 d->stack->addWidget(files, d->modeButtons->insert(d->detailView)); |
|
2522 |
|
2523 d->previewInfo = new QToolButton(this, "preview info view"); |
|
2524 d->previewInfo->setFocusPolicy(Qt::TabFocus); |
|
2525 #ifndef QT_NO_TOOLTIP |
|
2526 QToolTip::add(d->previewInfo, tr("Preview File Info")); |
|
2527 #endif |
|
2528 d->previewInfo->setIconSet(*previewInfoViewIcon); |
|
2529 d->previewInfo->setToggleButton(true); |
|
2530 d->modeButtons->insert(d->previewInfo); |
|
2531 |
|
2532 d->previewContents = new QToolButton(this, "preview info view"); |
|
2533 if (!qstrcmp(style()->className(), "QWindowsStyle")) |
|
2534 { |
|
2535 d->goBack->setAutoRaise(true); |
|
2536 d->cdToParent->setAutoRaise(true); |
|
2537 d->newFolder->setAutoRaise(true); |
|
2538 d->mcView->setAutoRaise(true); |
|
2539 d->detailView->setAutoRaise(true); |
|
2540 d->previewInfo->setAutoRaise(true); |
|
2541 d->previewContents->setAutoRaise(true); |
|
2542 } |
|
2543 d->previewContents->setFocusPolicy(Qt::TabFocus); |
|
2544 #ifndef QT_NO_TOOLTIP |
|
2545 QToolTip::add(d->previewContents, tr("Preview File Contents")); |
|
2546 #endif |
|
2547 d->previewContents->setIconSet(*previewContentsViewIcon); |
|
2548 d->previewContents->setToggleButton(true); |
|
2549 d->modeButtons->insert(d->previewContents); |
|
2550 |
|
2551 connect(d->detailView, SIGNAL(clicked()), |
|
2552 d->moreFiles, SLOT(cancelRename())); |
|
2553 connect(d->detailView, SIGNAL(clicked()), |
|
2554 files, SLOT(cancelRename())); |
|
2555 connect(d->mcView, SIGNAL(clicked()), |
|
2556 d->moreFiles, SLOT(cancelRename())); |
|
2557 connect(d->mcView, SIGNAL(clicked()), |
|
2558 files, SLOT(cancelRename())); |
|
2559 |
|
2560 d->stack->raiseWidget(d->moreFiles); |
|
2561 d->mcView->setOn(true); |
|
2562 |
|
2563 QHBoxLayout *lay = new QHBoxLayout(this); |
|
2564 lay->setMargin(6); |
|
2565 d->leftLayout = new QHBoxLayout(lay, 5); |
|
2566 d->topLevelLayout = new QVBoxLayout((QWidget*)0, 5); |
|
2567 lay->addLayout(d->topLevelLayout, 1); |
|
2568 |
|
2569 QHBoxLayout * h; |
|
2570 |
|
2571 d->preview = new Q3WidgetStack(d->splitter, "qt_preview"); |
|
2572 |
|
2573 d->infoPreviewWidget = new QWidget(d->preview, "qt_preview_info"); |
|
2574 d->contentsPreviewWidget = new QWidget(d->preview, "qt_preview_contents"); |
|
2575 d->infoPreviewer = d->contentsPreviewer = 0; |
|
2576 |
|
2577 h = new QHBoxLayout(0); |
|
2578 d->buttonLayout = h; |
|
2579 d->topLevelLayout->addLayout(h); |
|
2580 h->addWidget(d->pathL); |
|
2581 h->addSpacing(8); |
|
2582 h->addWidget(d->paths); |
|
2583 h->addSpacing(8); |
|
2584 if (d->goBack) |
|
2585 h->addWidget(d->goBack); |
|
2586 h->addWidget(d->cdToParent); |
|
2587 h->addSpacing(2); |
|
2588 h->addWidget(d->newFolder); |
|
2589 h->addSpacing(4); |
|
2590 h->addWidget(d->mcView); |
|
2591 h->addWidget(d->detailView); |
|
2592 h->addWidget(d->previewInfo); |
|
2593 h->addWidget(d->previewContents); |
|
2594 |
|
2595 d->topLevelLayout->addWidget(d->splitter); |
|
2596 |
|
2597 h = new QHBoxLayout(); |
|
2598 d->topLevelLayout->addLayout(h); |
|
2599 h->addWidget(d->fileL); |
|
2600 h->addWidget(nameEdit); |
|
2601 h->addSpacing(15); |
|
2602 h->addWidget(okB); |
|
2603 |
|
2604 h = new QHBoxLayout(); |
|
2605 d->topLevelLayout->addLayout(h); |
|
2606 h->addWidget(d->typeL); |
|
2607 h->addWidget(d->types); |
|
2608 h->addSpacing(15); |
|
2609 h->addWidget(cancelB); |
|
2610 |
|
2611 d->rightLayout = new QHBoxLayout(lay, 5); |
|
2612 d->topLevelLayout->setStretchFactor(d->mcView, 1); |
|
2613 d->topLevelLayout->setStretchFactor(files, 1); |
|
2614 |
|
2615 updateGeometries(); |
|
2616 |
|
2617 if (d->goBack) { |
|
2618 setTabOrder(d->paths, d->goBack); |
|
2619 setTabOrder(d->goBack, d->cdToParent); |
|
2620 } else { |
|
2621 setTabOrder(d->paths, d->cdToParent); |
|
2622 } |
|
2623 setTabOrder(d->cdToParent, d->newFolder); |
|
2624 setTabOrder(d->newFolder, d->mcView); |
|
2625 setTabOrder(d->mcView, d->detailView); |
|
2626 setTabOrder(d->detailView, d->moreFiles); |
|
2627 setTabOrder(d->moreFiles, files); |
|
2628 setTabOrder(files, nameEdit); |
|
2629 setTabOrder(nameEdit, d->types); |
|
2630 setTabOrder(d->types, okB); |
|
2631 setTabOrder(okB, cancelB); |
|
2632 |
|
2633 d->rw = tr("Read-write"); |
|
2634 d->ro = tr("Read-only"); |
|
2635 d->wo = tr("Write-only"); |
|
2636 d->inaccessible = tr("Inaccessible"); |
|
2637 |
|
2638 d->symLinkToFile = tr("Symlink to File"); |
|
2639 d->symLinkToDir = tr("Symlink to Directory"); |
|
2640 d->symLinkToSpecial = tr("Symlink to Special"); |
|
2641 d->file = tr("File"); |
|
2642 d->dir = tr("Dir"); |
|
2643 d->special = tr("Special"); |
|
2644 |
|
2645 if (lastWidth == 0) { |
|
2646 QRect screen = QApplication::desktop()->screenGeometry(pos()); |
|
2647 if (screen.width() < 1024 || screen.height() < 768) { |
|
2648 resize(qMin(screen.width(), 420), qMin(screen.height(), 236)); |
|
2649 } else { |
|
2650 QSize s = files->sizeHint(); |
|
2651 s = QSize(s.width() + 300, s.height() + 82); |
|
2652 |
|
2653 if (s.width() * 3 > screen.width() * 2) |
|
2654 s.setWidth(screen.width() * 2 / 3); |
|
2655 |
|
2656 if (s.height() * 3 > screen.height() * 2) |
|
2657 s.setHeight(screen.height() * 2 / 3); |
|
2658 else if (s.height() * 3 < screen.height()) |
|
2659 s.setHeight(screen.height() / 3); |
|
2660 |
|
2661 resize(s); |
|
2662 } |
|
2663 updateLastSize(this); |
|
2664 } else { |
|
2665 resize(lastWidth, lastHeight); |
|
2666 } |
|
2667 |
|
2668 if (detailViewMode) { |
|
2669 d->stack->raiseWidget(files); |
|
2670 d->mcView->setOn(false); |
|
2671 d->detailView->setOn(true); |
|
2672 } |
|
2673 |
|
2674 d->preview->hide(); |
|
2675 nameEdit->setFocus(); |
|
2676 |
|
2677 connect(nameEdit, SIGNAL(returnPressed()), |
|
2678 this, SLOT(fileNameEditReturnPressed())); |
|
2679 } |
|
2680 |
|
2681 /*! |
|
2682 \internal |
|
2683 */ |
|
2684 |
|
2685 void Q3FileDialog::fileNameEditReturnPressed() |
|
2686 { |
|
2687 d->oldUrl = d->url; |
|
2688 if (!isDirectoryMode(d->mode)) { |
|
2689 okClicked(); |
|
2690 } else { |
|
2691 d->currentFileName.clear(); |
|
2692 if (nameEdit->text().isEmpty()) { |
|
2693 emit fileSelected(selectedFile()); |
|
2694 accept(); |
|
2695 } else { |
|
2696 QUrlInfo f; |
|
2697 Q3FileDialogPrivate::File * c |
|
2698 = (Q3FileDialogPrivate::File *)files->currentItem(); |
|
2699 if (c && files->isSelected(c)) |
|
2700 f = c->info; |
|
2701 else |
|
2702 f = QUrlInfo(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text())); |
|
2703 if (f.isDir()) { |
|
2704 setUrl(Q3UrlOperator(d->url, |
|
2705 Q3FileDialogPrivate::encodeFileName(nameEdit->text() + QLatin1Char('/')))); |
|
2706 d->checkForFilter = true; |
|
2707 trySetSelection(true, d->url, true); |
|
2708 d->checkForFilter = false; |
|
2709 } |
|
2710 } |
|
2711 nameEdit->setText(QString()); |
|
2712 } |
|
2713 } |
|
2714 |
|
2715 /*! |
|
2716 \internal |
|
2717 Update the info and content preview widgets to display \a u. |
|
2718 */ |
|
2719 |
|
2720 void Q3FileDialog::updatePreviews(const Q3Url &u) |
|
2721 { |
|
2722 if (d->infoPreviewer) |
|
2723 d->infoPreviewer->previewUrl(u); |
|
2724 if (d->contentsPreviewer) |
|
2725 d->contentsPreviewer->previewUrl(u); |
|
2726 } |
|
2727 |
|
2728 /*! |
|
2729 \internal |
|
2730 Changes the preview mode to the mode specified at \a id. |
|
2731 */ |
|
2732 |
|
2733 void Q3FileDialog::changeMode(int id) |
|
2734 { |
|
2735 if (!d->infoPreview && !d->contentsPreview) |
|
2736 return; |
|
2737 |
|
2738 QAbstractButton*btn = d->modeButtons->find(id); |
|
2739 if (!btn) |
|
2740 return; |
|
2741 |
|
2742 if (btn == d->previewContents && !d->contentsPreview) |
|
2743 return; |
|
2744 if (btn == d->previewInfo && !d->infoPreview) |
|
2745 return; |
|
2746 |
|
2747 if (btn != d->previewContents && btn != d->previewInfo) { |
|
2748 d->preview->hide(); |
|
2749 } else { |
|
2750 if (files->currentItem()) |
|
2751 updatePreviews(Q3Url(d->url, files->currentItem()->text(0))); |
|
2752 if (btn == d->previewInfo) |
|
2753 d->preview->raiseWidget(d->infoPreviewWidget); |
|
2754 else |
|
2755 d->preview->raiseWidget(d->contentsPreviewWidget); |
|
2756 d->preview->show(); |
|
2757 } |
|
2758 } |
|
2759 |
|
2760 /*! |
|
2761 Destroys the file dialog. |
|
2762 */ |
|
2763 |
|
2764 Q3FileDialog::~Q3FileDialog() |
|
2765 { |
|
2766 // since clear might call setContentsPos which would emit |
|
2767 // a signal and thus cause a recompute of sizes... |
|
2768 files->blockSignals(true); |
|
2769 d->moreFiles->blockSignals(true); |
|
2770 files->clear(); |
|
2771 d->moreFiles->clear(); |
|
2772 d->moreFiles->blockSignals(false); |
|
2773 files->blockSignals(false); |
|
2774 |
|
2775 #ifndef QT_NO_CURSOR |
|
2776 if (d->cursorOverride) |
|
2777 QApplication::restoreOverrideCursor(); |
|
2778 #endif |
|
2779 |
|
2780 delete d; |
|
2781 d = 0; |
|
2782 } |
|
2783 |
|
2784 |
|
2785 /*! |
|
2786 \property Q3FileDialog::selectedFile |
|
2787 |
|
2788 \brief the name of the selected file |
|
2789 |
|
2790 If a file was selected selectedFile contains the file's name including |
|
2791 its absolute path; otherwise selectedFile is empty. |
|
2792 |
|
2793 \sa QString::isEmpty(), selectedFiles, selectedFilter |
|
2794 */ |
|
2795 |
|
2796 QString Q3FileDialog::selectedFile() const |
|
2797 { |
|
2798 QString s = d->currentFileName; |
|
2799 // remove the protocol because we do not want to encode it... |
|
2800 QString prot = Q3Url(s).protocol(); |
|
2801 if (!prot.isEmpty()) { |
|
2802 prot += QLatin1Char(':'); |
|
2803 s.remove(0, prot.length()); |
|
2804 } |
|
2805 Q3Url u(prot + Q3FileDialogPrivate::encodeFileName(s)); |
|
2806 if (u.isLocalFile()) { |
|
2807 QString s = u.toString(); |
|
2808 if (s.left(5) == QLatin1String("file:")) |
|
2809 s.remove((uint)0, 5); |
|
2810 return s; |
|
2811 } |
|
2812 return d->currentFileName; |
|
2813 } |
|
2814 |
|
2815 /*! |
|
2816 \property Q3FileDialog::selectedFilter |
|
2817 |
|
2818 \brief the filter which the user has selected in the file dialog |
|
2819 |
|
2820 \sa filterSelected(), selectedFiles, selectedFile |
|
2821 */ |
|
2822 |
|
2823 QString Q3FileDialog::selectedFilter() const |
|
2824 { |
|
2825 return d->types->currentText(); |
|
2826 } |
|
2827 |
|
2828 /*! \overload |
|
2829 |
|
2830 Sets the current filter selected in the file dialog to the |
|
2831 \a{n}-th filter in the filter list. |
|
2832 |
|
2833 \sa filterSelected(), selectedFilter(), selectedFiles(), selectedFile() |
|
2834 */ |
|
2835 |
|
2836 void Q3FileDialog::setSelectedFilter(int n) |
|
2837 { |
|
2838 d->types->setCurrentItem(n); |
|
2839 QString f = d->types->currentText(); |
|
2840 QRegExp r(QString::fromLatin1(qt3_file_dialog_filter_reg_exp)); |
|
2841 int index = r.indexIn(f); |
|
2842 if (index >= 0) |
|
2843 f = r.cap(2); |
|
2844 d->url.setNameFilter(f); |
|
2845 rereadDir(); |
|
2846 } |
|
2847 |
|
2848 /*! |
|
2849 Sets the current filter selected in the file dialog to the first |
|
2850 one that contains the text \a mask. |
|
2851 */ |
|
2852 |
|
2853 void Q3FileDialog::setSelectedFilter(const QString& mask) |
|
2854 { |
|
2855 int n; |
|
2856 |
|
2857 for (n = 0; n < d->types->count(); n++) { |
|
2858 if (d->types->text(n).contains(mask, Qt::CaseInsensitive)) { |
|
2859 d->types->setCurrentItem(n); |
|
2860 QString f = mask; |
|
2861 QRegExp r(QString::fromLatin1(qt3_file_dialog_filter_reg_exp)); |
|
2862 int index = r.indexIn(f); |
|
2863 if (index >= 0) |
|
2864 f = r.cap(2); |
|
2865 d->url.setNameFilter(f); |
|
2866 rereadDir(); |
|
2867 return; |
|
2868 } |
|
2869 } |
|
2870 } |
|
2871 |
|
2872 /*! |
|
2873 \property Q3FileDialog::selectedFiles |
|
2874 |
|
2875 \brief the list of selected files |
|
2876 |
|
2877 If one or more files are selected, selectedFiles contains their |
|
2878 names including their absolute paths. If no files are selected or |
|
2879 the mode isn't ExistingFiles selectedFiles is an empty list. |
|
2880 |
|
2881 It is more convenient to use selectedFile() if the mode is |
|
2882 \l ExistingFile, \c Directory or \c DirectoryOnly. |
|
2883 |
|
2884 Note that if you want to iterate over the list, you should |
|
2885 iterate over a copy, e.g. |
|
2886 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 8 |
|
2887 |
|
2888 \sa selectedFile, selectedFilter, QList::isEmpty() |
|
2889 */ |
|
2890 |
|
2891 QStringList Q3FileDialog::selectedFiles() const |
|
2892 { |
|
2893 QStringList lst; |
|
2894 |
|
2895 if (mode() == ExistingFiles) { |
|
2896 QStringList selectedLst; |
|
2897 QString selectedFiles = nameEdit->text(); |
|
2898 if (selectedFiles.lastIndexOf(QLatin1Char('\"')) == -1) { |
|
2899 //probably because Enter was pressed on the nameEdit, so we have one file |
|
2900 //not in "" but raw |
|
2901 selectedLst.append(selectedFiles); |
|
2902 } else { |
|
2903 selectedFiles.truncate(selectedFiles.lastIndexOf(QLatin1Char('\"'))); |
|
2904 selectedLst = selectedLst.split(QLatin1String("\" "), selectedFiles); |
|
2905 } |
|
2906 for (QStringList::Iterator it = selectedLst.begin(); it != selectedLst.end(); ++it) { |
|
2907 Q3Url u; |
|
2908 if ((*it)[0] == QLatin1Char('\"')) { |
|
2909 u = Q3Url(d->url, Q3FileDialogPrivate::encodeFileName((*it).mid(1))); |
|
2910 } else { |
|
2911 u = Q3Url(d->url, Q3FileDialogPrivate::encodeFileName((*it))); |
|
2912 } |
|
2913 if (u.isLocalFile()) { |
|
2914 QString s = u.toString(); |
|
2915 if (s.left(5) == QLatin1String("file:")) |
|
2916 s.remove((uint)0, 5); |
|
2917 lst << s; |
|
2918 } else { |
|
2919 lst << u.toString(); |
|
2920 } |
|
2921 } |
|
2922 } |
|
2923 |
|
2924 return lst; |
|
2925 } |
|
2926 |
|
2927 /*! |
|
2928 Sets the default selection to \a filename. If \a filename is |
|
2929 absolute, setDir() is also called to set the file dialog's working |
|
2930 directory to the filename's directory. |
|
2931 |
|
2932 \omit |
|
2933 Only for external use. Not useful inside Q3FileDialog. |
|
2934 \endomit |
|
2935 */ |
|
2936 |
|
2937 void Q3FileDialog::setSelection(const QString & filename) |
|
2938 { |
|
2939 d->oldUrl = d->url; |
|
2940 QString nf = d->url.nameFilter(); |
|
2941 if (Q3Url::isRelativeUrl(filename)) |
|
2942 d->url = Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(filename)); |
|
2943 else |
|
2944 d->url = Q3UrlOperator(filename); |
|
2945 d->url.setNameFilter(nf); |
|
2946 d->checkForFilter = true; |
|
2947 bool isDirOk; |
|
2948 bool isDir = d->url.isDir(&isDirOk); |
|
2949 if (!isDirOk) |
|
2950 isDir = d->url.path().right(1) == QString(QLatin1Char('/')); |
|
2951 if (!isDir) { |
|
2952 Q3UrlOperator u(d->url); |
|
2953 d->url.setPath(d->url.dirPath()); |
|
2954 trySetSelection(false, u, true); |
|
2955 d->ignoreNextRefresh = true; |
|
2956 nameEdit->selectAll(); |
|
2957 rereadDir(); |
|
2958 emit dirEntered(d->url.dirPath()); |
|
2959 } else { |
|
2960 if (!d->url.path().isEmpty() && |
|
2961 d->url.path().right(1) != QString(QLatin1Char('/'))) { |
|
2962 QString p = d->url.path(); |
|
2963 p += QLatin1Char('/'); |
|
2964 d->url.setPath(p); |
|
2965 } |
|
2966 trySetSelection(true, d->url, false); |
|
2967 rereadDir(); |
|
2968 emit dirEntered(d->url.dirPath()); |
|
2969 nameEdit->setText(QString::fromLatin1("")); |
|
2970 } |
|
2971 d->checkForFilter = false; |
|
2972 } |
|
2973 |
|
2974 /*! |
|
2975 \property Q3FileDialog::dirPath |
|
2976 |
|
2977 \brief the file dialog's working directory |
|
2978 |
|
2979 \sa dir(), setDir() |
|
2980 */ |
|
2981 |
|
2982 QString Q3FileDialog::dirPath() const |
|
2983 { |
|
2984 return d->url.dirPath(); |
|
2985 } |
|
2986 |
|
2987 |
|
2988 /*! |
|
2989 |
|
2990 Sets the filter used in the file dialog to \a newFilter. |
|
2991 |
|
2992 If \a newFilter contains a pair of parentheses containing one or more |
|
2993 of "anything*something" separated by spaces or by |
|
2994 semicolons then only the text contained in the parentheses is used as |
|
2995 the filter. This means that these calls are all equivalent: |
|
2996 |
|
2997 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 9 |
|
2998 |
|
2999 \sa setFilters() |
|
3000 */ |
|
3001 |
|
3002 void Q3FileDialog::setFilter(const QString & newFilter) |
|
3003 { |
|
3004 if (newFilter.isEmpty()) |
|
3005 return; |
|
3006 QString f = newFilter; |
|
3007 QRegExp r(QString::fromLatin1(qt3_file_dialog_filter_reg_exp)); |
|
3008 int index = r.indexIn(f); |
|
3009 if (index >= 0) |
|
3010 f = r.cap(2); |
|
3011 d->url.setNameFilter(f); |
|
3012 if (d->types->count() == 1) { |
|
3013 d->types->clear(); |
|
3014 d->types->insertItem(newFilter); |
|
3015 } else { |
|
3016 for (int i = 0; i < d->types->count(); ++i) { |
|
3017 if (d->types->text(i).left(newFilter.length()) == newFilter || |
|
3018 d->types->text(i).left(f.length()) == f) { |
|
3019 d->types->setCurrentItem(i); |
|
3020 break; |
|
3021 } |
|
3022 } |
|
3023 } |
|
3024 rereadDir(); |
|
3025 } |
|
3026 |
|
3027 |
|
3028 /*! \overload |
|
3029 Sets the file dialog's working directory to \a pathstr. |
|
3030 |
|
3031 \sa dir() |
|
3032 */ |
|
3033 |
|
3034 void Q3FileDialog::setDir(const QString & pathstr) |
|
3035 { |
|
3036 QString dr = pathstr; |
|
3037 if (dr.isEmpty()) |
|
3038 return; |
|
3039 |
|
3040 #if defined(Q_OS_UNIX) |
|
3041 if (dr.length() && dr[0] == QLatin1Char('~')) { |
|
3042 int i = 0; |
|
3043 while(i < (int)dr.length() && dr[i] != QLatin1Char('/')) |
|
3044 i++; |
|
3045 Q3CString user; |
|
3046 if (i == 1) { |
|
3047 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
|
3048 |
|
3049 # ifndef _POSIX_LOGIN_NAME_MAX |
|
3050 # define _POSIX_LOGIN_NAME_MAX 9 |
|
3051 # endif |
|
3052 |
|
3053 char name[_POSIX_LOGIN_NAME_MAX]; |
|
3054 if (::getlogin_r(name, _POSIX_LOGIN_NAME_MAX) == 0) |
|
3055 user = name; |
|
3056 else |
|
3057 #else |
|
3058 user = ::getlogin(); |
|
3059 if (user.isEmpty()) |
|
3060 #endif |
|
3061 user = qgetenv("LOGNAME"); |
|
3062 } else |
|
3063 user = dr.mid(1, i-1).local8Bit(); |
|
3064 dr = dr.mid(i, dr.length()); |
|
3065 struct passwd *pw; |
|
3066 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_FREEBSD) && !defined(Q_OS_OPENBSD) |
|
3067 struct passwd mt_pw; |
|
3068 char buffer[2048]; |
|
3069 if (::getpwnam_r(user, &mt_pw, buffer, 2048, &pw) == 0 && pw == &mt_pw) |
|
3070 #else |
|
3071 pw = ::getpwnam(user); |
|
3072 if (pw) |
|
3073 #endif |
|
3074 dr.prepend(QString::fromLocal8Bit(pw->pw_dir)); |
|
3075 } |
|
3076 #endif |
|
3077 |
|
3078 setUrl(dr); |
|
3079 } |
|
3080 |
|
3081 /*! |
|
3082 Returns the current directory shown in the file dialog. |
|
3083 |
|
3084 The ownership of the QDir pointer is transferred to the caller, so |
|
3085 it must be deleted by the caller when no longer required. |
|
3086 |
|
3087 \sa setDir() |
|
3088 */ |
|
3089 |
|
3090 const QDir *Q3FileDialog::dir() const |
|
3091 { |
|
3092 if (d->url.isLocalFile()) |
|
3093 return new QDir(d->url.path()); |
|
3094 else |
|
3095 return 0; |
|
3096 } |
|
3097 |
|
3098 /*! |
|
3099 Sets the file dialog's working directory to \a dir. |
|
3100 \sa dir() |
|
3101 */ |
|
3102 |
|
3103 void Q3FileDialog::setDir(const QDir &dir) |
|
3104 { |
|
3105 d->oldUrl = d->url; |
|
3106 QString nf(d->url.nameFilter()); |
|
3107 d->url = dir.canonicalPath(); |
|
3108 d->url.setNameFilter(nf); |
|
3109 QUrlInfo i(d->url.info(nameEdit->text().isEmpty()? QString::fromLatin1(".") : nameEdit->text())); |
|
3110 d->checkForFilter = true; |
|
3111 trySetSelection(i.isDir(), Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(nameEdit->text())), false); |
|
3112 d->checkForFilter = false; |
|
3113 rereadDir(); |
|
3114 emit dirEntered(d->url.path()); |
|
3115 } |
|
3116 |
|
3117 /*! |
|
3118 Sets the file dialog's working directory to the directory specified at \a url. |
|
3119 |
|
3120 \sa url() |
|
3121 */ |
|
3122 |
|
3123 void Q3FileDialog::setUrl(const Q3UrlOperator &url) |
|
3124 { |
|
3125 d->oldUrl = d->url; |
|
3126 QString nf = d->url.nameFilter(); |
|
3127 |
|
3128 QString operatorPath = url.toString(false, false); |
|
3129 if (Q3Url::isRelativeUrl(operatorPath)) { |
|
3130 d->url = Q3Url(d->url, operatorPath); |
|
3131 } else { |
|
3132 d->url = url; |
|
3133 } |
|
3134 d->url.setNameFilter(nf); |
|
3135 |
|
3136 d->checkForFilter = true; |
|
3137 if (!d->url.isDir()) { |
|
3138 Q3UrlOperator u = d->url; |
|
3139 d->url.setPath(d->url.dirPath()); |
|
3140 trySetSelection(false, u, false); |
|
3141 rereadDir(); |
|
3142 emit dirEntered(d->url.dirPath()); |
|
3143 QString fn = u.fileName(); |
|
3144 nameEdit->setText(fn); |
|
3145 } else { |
|
3146 trySetSelection(true, d->url, false); |
|
3147 rereadDir(); |
|
3148 emit dirEntered(d->url.dirPath()); |
|
3149 } |
|
3150 d->checkForFilter = false; |
|
3151 } |
|
3152 |
|
3153 /*! |
|
3154 \property Q3FileDialog::showHiddenFiles |
|
3155 |
|
3156 \brief whether hidden files are shown in the file dialog |
|
3157 |
|
3158 The default is false, i.e. don't show hidden files. |
|
3159 */ |
|
3160 |
|
3161 void Q3FileDialog::setShowHiddenFiles(bool s) |
|
3162 { |
|
3163 if (s == bShowHiddenFiles) |
|
3164 return; |
|
3165 |
|
3166 bShowHiddenFiles = s; |
|
3167 rereadDir(); |
|
3168 } |
|
3169 |
|
3170 bool Q3FileDialog::showHiddenFiles() const |
|
3171 { |
|
3172 return bShowHiddenFiles; |
|
3173 } |
|
3174 |
|
3175 /*! |
|
3176 Rereads the current directory shown in the file dialog. |
|
3177 |
|
3178 The only time you will need to call this function is if the contents of |
|
3179 the directory change and you wish to refresh the file dialog to reflect |
|
3180 the change. |
|
3181 |
|
3182 \sa resortDir() |
|
3183 */ |
|
3184 |
|
3185 void Q3FileDialog::rereadDir() |
|
3186 { |
|
3187 #ifndef QT_NO_CURSOR |
|
3188 if (!d->cursorOverride) { |
|
3189 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
|
3190 d->cursorOverride = true; |
|
3191 } |
|
3192 #endif |
|
3193 d->pendingItems.clear(); |
|
3194 if (d->mimeTypeTimer->isActive()) |
|
3195 d->mimeTypeTimer->stop(); |
|
3196 d->currListChildren = d->url.listChildren(); |
|
3197 #ifndef QT_NO_CURSOR |
|
3198 if (d->cursorOverride) { |
|
3199 QApplication::restoreOverrideCursor(); |
|
3200 d->cursorOverride = false; |
|
3201 } |
|
3202 #endif |
|
3203 } |
|
3204 |
|
3205 |
|
3206 /*! |
|
3207 \fn void Q3FileDialog::fileHighlighted(const QString& file) |
|
3208 |
|
3209 This signal is emitted when the user highlights the given \a file, |
|
3210 i.e. makes it the current file. |
|
3211 |
|
3212 \sa fileSelected(), filesSelected() |
|
3213 */ |
|
3214 |
|
3215 /*! |
|
3216 \fn void Q3FileDialog::fileSelected(const QString& file) |
|
3217 |
|
3218 This signal is emitted when the user selects the given \a file. |
|
3219 |
|
3220 \sa filesSelected(), fileHighlighted(), selectedFile() |
|
3221 */ |
|
3222 |
|
3223 /*! |
|
3224 \fn void Q3FileDialog::filesSelected(const QStringList& files) |
|
3225 |
|
3226 This signal is emitted when the user selects the given \a files in \e |
|
3227 ExistingFiles mode. |
|
3228 |
|
3229 \sa fileSelected(), fileHighlighted(), selectedFiles() |
|
3230 */ |
|
3231 |
|
3232 /*! |
|
3233 \fn void Q3FileDialog::dirEntered(const QString& directory) |
|
3234 |
|
3235 This signal is emitted when the user enters the given \a directory. |
|
3236 |
|
3237 \sa dir() |
|
3238 */ |
|
3239 |
|
3240 /*! |
|
3241 \fn void Q3FileDialog::filterSelected(const QString& filter) |
|
3242 |
|
3243 This signal is emitted when the user selects the given \a filter. |
|
3244 |
|
3245 \sa selectedFilter() |
|
3246 */ |
|
3247 |
|
3248 extern bool qt_resolve_symlinks; // defined in q3url.cpp |
|
3249 extern Q_GUI_EXPORT bool qt_use_native_dialogs; //qtgui |
|
3250 |
|
3251 /*! |
|
3252 This is a convenience static function that returns an existing file |
|
3253 selected by the user. If the user pressed Cancel, it returns a null |
|
3254 string. |
|
3255 |
|
3256 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 10 |
|
3257 |
|
3258 The function creates a modal file dialog called \a name, with |
|
3259 parent, \a parent. If a parent is not 0, the dialog will be shown |
|
3260 centered over the parent. |
|
3261 |
|
3262 The file dialog's working directory will be set to \a startWith. If \a |
|
3263 startWith includes a file name, the file will be selected. The filter |
|
3264 is set to \a filter so that only those files which match the filter |
|
3265 are shown. The filter selected is set to \a selectedFilter. The parameters |
|
3266 \a startWith, \a selectedFilter and \a filter may be an empty string. |
|
3267 |
|
3268 The dialog's caption is set to \a caption. If \a caption is not |
|
3269 specified then a default caption will be used. |
|
3270 |
|
3271 Under Windows and Mac OS X, this static function will use the native |
|
3272 file dialog and not a Q3FileDialog, unless the style of the application |
|
3273 is set to something other than the native style (Note that on Windows the |
|
3274 dialog will spin a blocking modal event loop that will not dispatch any |
|
3275 QTimers and if parent is not 0 then it will position the dialog just under |
|
3276 the parent's title bar). |
|
3277 |
|
3278 Under Unix/X11, the normal behavior of the file dialog is to resolve |
|
3279 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, |
|
3280 the file dialog will change to /var/tmp after entering /usr/tmp. |
|
3281 If \a resolveSymlinks is false, the file dialog will treat |
|
3282 symlinks as regular directories. |
|
3283 |
|
3284 \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() |
|
3285 */ |
|
3286 |
|
3287 QString Q3FileDialog::getOpenFileName(const QString & startWith, |
|
3288 const QString& filter, |
|
3289 QWidget *parent, const char* name, |
|
3290 const QString& caption, |
|
3291 QString *selectedFilter, |
|
3292 bool resolveSymlinks) |
|
3293 { |
|
3294 bool save_qt_resolve_symlinks = qt_resolve_symlinks; |
|
3295 qt_resolve_symlinks = resolveSymlinks; |
|
3296 |
|
3297 QStringList filters; |
|
3298 if (!filter.isEmpty()) |
|
3299 filters = makeFiltersList(filter); |
|
3300 |
|
3301 makeVariables(); |
|
3302 QString initialSelection; |
|
3303 //### Problem with the logic here: If a startWith is given and a file |
|
3304 // with that name exists in D->URL, the box will be opened at D->URL instead of |
|
3305 // the last directory used ('workingDirectory'). |
|
3306 // |
|
3307 // hm... isn't that problem exactly the documented behaviour? the |
|
3308 // documented behaviour sounds meaningful. |
|
3309 if (!startWith.isEmpty()) { |
|
3310 Q3UrlOperator u(Q3FileDialogPrivate::encodeFileName(startWith)); |
|
3311 if (u.isLocalFile() && QFileInfo(u.path()).isDir()) { |
|
3312 *workingDirectory = startWith; |
|
3313 } else { |
|
3314 if (u.isLocalFile()) { |
|
3315 QFileInfo fi(u.dirPath()); |
|
3316 if (fi.exists()) { |
|
3317 *workingDirectory = u.dirPath(); |
|
3318 initialSelection = u.fileName(); |
|
3319 } |
|
3320 } else { |
|
3321 *workingDirectory = u.toString(); |
|
3322 initialSelection.clear(); |
|
3323 } |
|
3324 } |
|
3325 } |
|
3326 |
|
3327 if (workingDirectory->isNull()) |
|
3328 *workingDirectory = toRootIfNotExists( QDir::currentDirPath() ); |
|
3329 |
|
3330 #if defined(Q_WS_WIN) |
|
3331 if (qt_use_native_dialogs && qobject_cast<QWindowsStyle *>(qApp->style())) |
|
3332 return winGetOpenFileName(initialSelection, filter, workingDirectory, |
|
3333 parent, name, caption, selectedFilter); |
|
3334 #elif defined(Q_WS_MAC) |
|
3335 if(qt_use_native_dialogs && qobject_cast<QMacStyle *>(qApp->style())) { |
|
3336 QStringList files = macGetOpenFileNames(filter, startWith.isEmpty() ? 0 : workingDirectory, |
|
3337 parent, name, caption, selectedFilter, false); |
|
3338 return files.isEmpty() ? QString() : files.first().normalized(QString::NormalizationForm_C); |
|
3339 } |
|
3340 #endif |
|
3341 |
|
3342 Q3FileDialog *dlg = new Q3FileDialog(*workingDirectory, QString(), parent, name ? name : "qt_filedlg_gofn", true); |
|
3343 |
|
3344 if (!caption.isNull()) |
|
3345 dlg->setWindowTitle(caption); |
|
3346 else |
|
3347 dlg->setWindowTitle(Q3FileDialog::tr("Open")); |
|
3348 |
|
3349 dlg->setFilters(filters); |
|
3350 if (selectedFilter) |
|
3351 dlg->setFilter(*selectedFilter); |
|
3352 dlg->setMode(Q3FileDialog::ExistingFile); |
|
3353 QString result; |
|
3354 if (!initialSelection.isEmpty()) |
|
3355 dlg->setSelection(initialSelection); |
|
3356 if (dlg->exec() == QDialog::Accepted) { |
|
3357 result = dlg->selectedFile(); |
|
3358 *workingDirectory = dlg->d->url; |
|
3359 if (selectedFilter) |
|
3360 *selectedFilter = dlg->selectedFilter(); |
|
3361 } |
|
3362 delete dlg; |
|
3363 |
|
3364 qt_resolve_symlinks = save_qt_resolve_symlinks; |
|
3365 |
|
3366 return result; |
|
3367 } |
|
3368 |
|
3369 /*! |
|
3370 This is a convenience static function that will return a file name |
|
3371 selected by the user. The file does not have to exist. |
|
3372 |
|
3373 It creates a modal file dialog called \a name, with parent, \a parent. |
|
3374 If a parent is not 0, the dialog will be shown centered over the |
|
3375 parent. |
|
3376 |
|
3377 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 11 |
|
3378 |
|
3379 The file dialog's working directory will be set to \a startWith. If \a |
|
3380 startWith includes a file name, the file will be selected. The filter |
|
3381 is set to \a filter so that only those files which match the filter |
|
3382 are shown. The filter selected is set to \a selectedFilter. The parameters |
|
3383 \a startWith, \a selectedFilter and \a filter may be an empty string. |
|
3384 |
|
3385 The dialog's caption is set to \a caption. If \a caption is not |
|
3386 specified then a default caption will be used. |
|
3387 |
|
3388 Under Windows and Mac OS X, this static function will use the native |
|
3389 file dialog and not a Q3FileDialog, unless the style of the application |
|
3390 is set to something other than the native style. (Note that on Windows the |
|
3391 dialog will spin a blocking modal event loop that will not dispatch any |
|
3392 QTimers and if parent is not 0 then it will position the dialog just under |
|
3393 the parent's title bar. And on the Mac the filter argument is ignored). |
|
3394 |
|
3395 Under Unix/X11, the normal behavior of the file dialog is to resolve |
|
3396 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, |
|
3397 the file dialog will change to /var/tmp after entering /usr/tmp. |
|
3398 If \a resolveSymlinks is false, the file dialog will treat |
|
3399 symlinks as regular directories. |
|
3400 |
|
3401 \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() |
|
3402 */ |
|
3403 |
|
3404 QString Q3FileDialog::getSaveFileName(const QString & startWith, |
|
3405 const QString& filter, |
|
3406 QWidget *parent, const char* name, |
|
3407 const QString& caption, |
|
3408 QString *selectedFilter, |
|
3409 bool resolveSymlinks) |
|
3410 { |
|
3411 bool save_qt_resolve_symlinks = qt_resolve_symlinks; |
|
3412 qt_resolve_symlinks = resolveSymlinks; |
|
3413 |
|
3414 QStringList filters; |
|
3415 if (!filter.isEmpty()) |
|
3416 filters = makeFiltersList(filter); |
|
3417 |
|
3418 makeVariables(); |
|
3419 QString initialSelection; |
|
3420 if (!startWith.isEmpty()) { |
|
3421 Q3UrlOperator u(Q3FileDialogPrivate::encodeFileName(startWith)); |
|
3422 if (u.isLocalFile() && QFileInfo(u.path()).isDir()) { |
|
3423 *workingDirectory = startWith; |
|
3424 } else { |
|
3425 if (u.isLocalFile()) { |
|
3426 QFileInfo fi(u.dirPath()); |
|
3427 if (fi.exists()) { |
|
3428 *workingDirectory = u.dirPath(); |
|
3429 initialSelection = u.fileName(); |
|
3430 } |
|
3431 } else { |
|
3432 *workingDirectory = u.toString(); |
|
3433 initialSelection.clear(); |
|
3434 } |
|
3435 } |
|
3436 } |
|
3437 |
|
3438 if (workingDirectory->isNull()) |
|
3439 *workingDirectory = toRootIfNotExists( QDir::currentDirPath() ); |
|
3440 |
|
3441 #if defined(Q_WS_WIN) |
|
3442 if (qt_use_native_dialogs && qobject_cast<QWindowsStyle *>(qApp->style())) |
|
3443 return winGetSaveFileName(initialSelection, filter, workingDirectory, |
|
3444 parent, name, caption, selectedFilter); |
|
3445 #elif defined(Q_WS_MAC) |
|
3446 if(qt_use_native_dialogs && qobject_cast<QMacStyle *>(qApp->style())) |
|
3447 return macGetSaveFileName(initialSelection.isNull() ? startWith : initialSelection, |
|
3448 filter, startWith.isEmpty() ? 0 : workingDirectory, parent, name, |
|
3449 caption, selectedFilter).normalized(QString::NormalizationForm_C); |
|
3450 #endif |
|
3451 |
|
3452 Q3FileDialog *dlg = new Q3FileDialog(*workingDirectory, QString(), parent, name ? name : "qt_filedlg_gsfn", true); |
|
3453 |
|
3454 if (!caption.isNull()) |
|
3455 dlg->setWindowTitle(caption); |
|
3456 else |
|
3457 dlg->setWindowTitle(Q3FileDialog::tr("Save As")); |
|
3458 |
|
3459 QString result; |
|
3460 dlg->setFilters(filters); |
|
3461 if (selectedFilter) |
|
3462 dlg->setFilter(*selectedFilter); |
|
3463 dlg->setMode(Q3FileDialog::AnyFile); |
|
3464 if (!initialSelection.isEmpty()) |
|
3465 dlg->setSelection(initialSelection); |
|
3466 if (dlg->exec() == QDialog::Accepted) { |
|
3467 result = dlg->selectedFile(); |
|
3468 *workingDirectory = dlg->d->url; |
|
3469 if (selectedFilter) |
|
3470 *selectedFilter = dlg->selectedFilter(); |
|
3471 } |
|
3472 delete dlg; |
|
3473 |
|
3474 qt_resolve_symlinks = save_qt_resolve_symlinks; |
|
3475 |
|
3476 return result; |
|
3477 } |
|
3478 |
|
3479 /*! |
|
3480 \internal |
|
3481 Activated when the "OK" button is clicked. |
|
3482 */ |
|
3483 |
|
3484 void Q3FileDialog::okClicked() |
|
3485 { |
|
3486 QString fn(nameEdit->text()); |
|
3487 |
|
3488 #if defined(Q_WS_WIN) |
|
3489 QFileInfo fi(d->url.path() + fn); |
|
3490 if (fi.isSymLink()) { |
|
3491 nameEdit->setText(fi.symLinkTarget()); |
|
3492 } |
|
3493 #endif |
|
3494 |
|
3495 if (fn.contains(QLatin1Char('*'))) { |
|
3496 addFilter(fn); |
|
3497 nameEdit->blockSignals(true); |
|
3498 nameEdit->setText(QString::fromLatin1("")); |
|
3499 nameEdit->blockSignals(false); |
|
3500 return; |
|
3501 } |
|
3502 |
|
3503 *workingDirectory = d->url; |
|
3504 detailViewMode = files->isVisible(); |
|
3505 updateLastSize(this); |
|
3506 |
|
3507 if (isDirectoryMode(d->mode)) { |
|
3508 QUrlInfo f(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text())); |
|
3509 if (f.isDir()) { |
|
3510 d->currentFileName = d->url; |
|
3511 if (d->currentFileName.right(1) != QString(QLatin1Char('/'))) |
|
3512 d->currentFileName += QLatin1Char('/'); |
|
3513 if (f.name() != QString(QLatin1Char('.'))) |
|
3514 d->currentFileName += f.name(); |
|
3515 accept(); |
|
3516 return; |
|
3517 } |
|
3518 // Since it's not a directory and we clicked ok, we |
|
3519 // don't really want to do anything else |
|
3520 return; |
|
3521 } |
|
3522 |
|
3523 // if we're in multi-selection mode and something is selected, |
|
3524 // accept it and be done. |
|
3525 if (mode() == ExistingFiles) { |
|
3526 if (! nameEdit->text().isEmpty()) { |
|
3527 QStringList sf = selectedFiles(); |
|
3528 bool isdir = false; |
|
3529 if (sf.count() == 1) { |
|
3530 Q3UrlOperator u(d->url, sf[0]); |
|
3531 bool ok; |
|
3532 isdir = u.isDir(&ok) && ok; |
|
3533 } |
|
3534 if (!isdir) { |
|
3535 emit filesSelected(sf); |
|
3536 accept(); |
|
3537 return; |
|
3538 } |
|
3539 } |
|
3540 } |
|
3541 |
|
3542 if (mode() == AnyFile) { |
|
3543 Q3UrlOperator u(d->url, Q3FileDialogPrivate::encodeFileName(nameEdit->text())); |
|
3544 if (!u.isDir()) { |
|
3545 d->currentFileName = u; |
|
3546 emit fileSelected(selectedFile()); |
|
3547 accept(); |
|
3548 return; |
|
3549 } |
|
3550 } |
|
3551 |
|
3552 if (mode() == ExistingFile) { |
|
3553 if (!Q3FileDialogPrivate::fileExists(d->url, nameEdit->text())) |
|
3554 return; |
|
3555 } |
|
3556 |
|
3557 // If selection is valid, return it, else try |
|
3558 // using selection as a directory to change to. |
|
3559 if (!d->currentFileName.isNull() && !d->currentFileName.contains(QLatin1Char('*'))) { |
|
3560 emit fileSelected(selectedFile()); |
|
3561 accept(); |
|
3562 } else { |
|
3563 QUrlInfo f; |
|
3564 Q3FileDialogPrivate::File * c |
|
3565 = (Q3FileDialogPrivate::File *)files->currentItem(); |
|
3566 Q3FileDialogPrivate::MCItem * m |
|
3567 = (Q3FileDialogPrivate::MCItem *)d->moreFiles->item(d->moreFiles->currentItem()); |
|
3568 if ((c && files->isVisible() && files->hasFocus()) |
|
3569 || (m && d->moreFiles->isVisible())) { |
|
3570 if (c && files->isVisible()) |
|
3571 f = c->info; |
|
3572 else |
|
3573 f = ((Q3FileDialogPrivate::File*)m->i)->info; |
|
3574 } else { |
|
3575 f = QUrlInfo(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text())); |
|
3576 } |
|
3577 if (f.isDir()) { |
|
3578 #if defined(Q_WS_WIN) |
|
3579 if (f.isSymLink()) |
|
3580 setUrl(Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(fn + QLatin1Char('/')))); |
|
3581 else |
|
3582 #else |
|
3583 setUrl(Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(f.name() + QLatin1Char('/')))); |
|
3584 #endif |
|
3585 d->checkForFilter = true; |
|
3586 trySetSelection(true, d->url, true); |
|
3587 d->checkForFilter = false; |
|
3588 } else { |
|
3589 if (!nameEdit->text().contains(QLatin1Char('/')) && |
|
3590 !nameEdit->text().contains(QLatin1String("\\")) |
|
3591 #if defined(Q_OS_WIN32) |
|
3592 && nameEdit->text()[1] != QLatin1Char(':') |
|
3593 #endif |
|
3594 ) |
|
3595 addFilter(nameEdit->text()); |
|
3596 else if (nameEdit->text()[0] == QLatin1Char('/') || |
|
3597 nameEdit->text()[0] == QLatin1Char('\\') |
|
3598 #if defined(Q_OS_WIN32) |
|
3599 || nameEdit->text()[1] == QLatin1Char(':') |
|
3600 #endif |
|
3601 ) |
|
3602 setDir(nameEdit->text()); |
|
3603 else if (nameEdit->text().left(3) == QLatin1String("../") || nameEdit->text().left(3) == QLatin1String("..\\")) |
|
3604 setDir(Q3Url(d->url.toString(), Q3FileDialogPrivate::encodeFileName(nameEdit->text())).toString()); |
|
3605 } |
|
3606 nameEdit->setText(QLatin1String("")); |
|
3607 } |
|
3608 } |
|
3609 |
|
3610 /*! |
|
3611 \internal |
|
3612 Activated when the "Filter" button is clicked. |
|
3613 */ |
|
3614 |
|
3615 void Q3FileDialog::filterClicked() |
|
3616 { |
|
3617 // unused |
|
3618 } |
|
3619 |
|
3620 /*! |
|
3621 \internal |
|
3622 Activated when the "Cancel" button is clicked. |
|
3623 */ |
|
3624 |
|
3625 void Q3FileDialog::cancelClicked() |
|
3626 { |
|
3627 *workingDirectory = d->url; |
|
3628 detailViewMode = files->isVisible(); |
|
3629 updateLastSize(this); |
|
3630 reject(); |
|
3631 } |
|
3632 |
|
3633 |
|
3634 /*!\reimp |
|
3635 */ |
|
3636 |
|
3637 void Q3FileDialog::resizeEvent(QResizeEvent * e) |
|
3638 { |
|
3639 QDialog::resizeEvent(e); |
|
3640 updateGeometries(); |
|
3641 } |
|
3642 |
|
3643 /* |
|
3644 \internal |
|
3645 The only correct way to try to set currentFileName |
|
3646 */ |
|
3647 bool Q3FileDialog::trySetSelection(bool isDir, const Q3UrlOperator &u, bool updatelined) |
|
3648 { |
|
3649 if (!isDir && !u.path().isEmpty() && u.path().right(1) == QString(QLatin1Char('/'))) |
|
3650 isDir = true; |
|
3651 if (u.fileName().contains(QLatin1Char('*')) && d->checkForFilter) { |
|
3652 QString fn(u.fileName()); |
|
3653 if (fn.contains(QLatin1Char('*'))) { |
|
3654 addFilter(fn); |
|
3655 d->currentFileName.clear(); |
|
3656 d->url.setFileName(QString()); |
|
3657 nameEdit->setText(QString::fromLatin1("")); |
|
3658 return false; |
|
3659 } |
|
3660 } |
|
3661 |
|
3662 if (isDir && d->preview && d->preview->isVisible()) |
|
3663 updatePreviews(u); |
|
3664 |
|
3665 QString old = d->currentFileName; |
|
3666 |
|
3667 if (isDirectoryMode(mode())) { |
|
3668 if (isDir) |
|
3669 d->currentFileName = u; |
|
3670 else |
|
3671 d->currentFileName.clear(); |
|
3672 } else if (!isDir && mode() == ExistingFiles) { |
|
3673 d->currentFileName = u; |
|
3674 } else if (!isDir || (mode() == AnyFile && !isDir)) { |
|
3675 d->currentFileName = u; |
|
3676 } else { |
|
3677 d->currentFileName.clear(); |
|
3678 } |
|
3679 if (updatelined && !d->currentFileName.isEmpty()) { |
|
3680 // If the selection is valid, or if its a directory, allow OK. |
|
3681 if (!d->currentFileName.isNull() || isDir) { |
|
3682 if (u.fileName() != QLatin1String("..")) { |
|
3683 QString fn = u.fileName(); |
|
3684 nameEdit->setText(fn); |
|
3685 } else { |
|
3686 nameEdit->setText(QLatin1String("")); |
|
3687 } |
|
3688 } else |
|
3689 nameEdit->setText(QString::fromLatin1("")); |
|
3690 } |
|
3691 |
|
3692 if (!d->currentFileName.isNull() || isDir) { |
|
3693 okB->setEnabled(true); |
|
3694 } else if (!isDirectoryMode(d->mode)) { |
|
3695 okB->setEnabled(false); |
|
3696 } |
|
3697 |
|
3698 if (d->currentFileName.length() && old != d->currentFileName) |
|
3699 emit fileHighlighted(selectedFile()); |
|
3700 |
|
3701 return !d->currentFileName.isNull(); |
|
3702 } |
|
3703 |
|
3704 |
|
3705 /*! Make sure the minimum and maximum sizes of everything are sane. |
|
3706 */ |
|
3707 |
|
3708 void Q3FileDialog::updateGeometries() |
|
3709 { |
|
3710 if (!d || !d->geometryDirty) |
|
3711 return; |
|
3712 |
|
3713 d->geometryDirty = false; |
|
3714 |
|
3715 QSize r, t; |
|
3716 |
|
3717 // we really should use QSize::expandedTo() |
|
3718 #define RM r.setWidth(qMax(r.width(),t.width())); \ |
|
3719 r.setHeight(qMax(r.height(),t.height())) |
|
3720 |
|
3721 // labels first |
|
3722 r = d->pathL->sizeHint(); |
|
3723 t = d->fileL->sizeHint(); |
|
3724 RM; |
|
3725 t = d->typeL->sizeHint(); |
|
3726 RM; |
|
3727 d->pathL->setFixedSize(d->pathL->sizeHint()); |
|
3728 d->fileL->setFixedSize(r); |
|
3729 d->typeL->setFixedSize(r); |
|
3730 |
|
3731 // single-line input areas |
|
3732 r = d->paths->sizeHint(); |
|
3733 t = nameEdit->sizeHint(); |
|
3734 RM; |
|
3735 t = d->types->sizeHint(); |
|
3736 RM; |
|
3737 r.setWidth(t.width() * 2 / 3); |
|
3738 t.setWidth(QWIDGETSIZE_MAX); |
|
3739 t.setHeight(r.height()); |
|
3740 d->paths->setMinimumSize(r); |
|
3741 d->paths->setMaximumSize(t); |
|
3742 nameEdit->setMinimumSize(r); |
|
3743 nameEdit->setMaximumSize(t); |
|
3744 d->types->setMinimumSize(r); |
|
3745 d->types->setMaximumSize(t); |
|
3746 |
|
3747 // buttons on top row |
|
3748 r = QSize(0, d->paths->minimumSize().height()); |
|
3749 t = QSize(21, 20); |
|
3750 RM; |
|
3751 if (r.height()+1 > r.width()) |
|
3752 r.setWidth(r.height()+1); |
|
3753 if (d->goBack) |
|
3754 d->goBack->setFixedSize(r); |
|
3755 d->cdToParent->setFixedSize(r); |
|
3756 d->newFolder->setFixedSize(r); |
|
3757 d->mcView->setFixedSize(r); |
|
3758 d->detailView->setFixedSize(r); |
|
3759 |
|
3760 QAbstractButton *b = 0; |
|
3761 if (!d->toolButtons.isEmpty()) { |
|
3762 for (b = d->toolButtons.first(); b; b = d->toolButtons.next()) |
|
3763 b->setFixedSize(b->sizeHint().width(), r.height()); |
|
3764 } |
|
3765 |
|
3766 if (d->infoPreview) { |
|
3767 d->previewInfo->show(); |
|
3768 d->previewInfo->setFixedSize(r); |
|
3769 } else { |
|
3770 d->previewInfo->hide(); |
|
3771 d->previewInfo->setFixedSize(QSize(0, 0)); |
|
3772 } |
|
3773 |
|
3774 if (d->contentsPreview) { |
|
3775 d->previewContents->show(); |
|
3776 d->previewContents->setFixedSize(r); |
|
3777 } else { |
|
3778 d->previewContents->hide(); |
|
3779 d->previewContents->setFixedSize(QSize(0, 0)); |
|
3780 } |
|
3781 |
|
3782 // open/save, cancel |
|
3783 r = QSize(75, 20); |
|
3784 t = okB->sizeHint(); |
|
3785 RM; |
|
3786 t = cancelB->sizeHint(); |
|
3787 RM; |
|
3788 |
|
3789 okB->setFixedSize(r); |
|
3790 cancelB->setFixedSize(r); |
|
3791 |
|
3792 d->topLevelLayout->activate(); |
|
3793 |
|
3794 #undef RM |
|
3795 } |
|
3796 |
|
3797 |
|
3798 /*! Updates the file name edit box to \a newItem in the file dialog |
|
3799 when the cursor moves in the listview. |
|
3800 */ |
|
3801 |
|
3802 void Q3FileDialog::updateFileNameEdit(Q3ListViewItem * newItem) |
|
3803 { |
|
3804 if (!newItem) |
|
3805 return; |
|
3806 |
|
3807 if (mode() == ExistingFiles) { |
|
3808 detailViewSelectionChanged(); |
|
3809 Q3Url u(d->url, Q3FileDialogPrivate::encodeFileName(((Q3FileDialogPrivate::File*)files->currentItem())->info.name())); |
|
3810 QFileInfo fi(u.toString(false, false)); |
|
3811 if (!fi.isDir()) |
|
3812 emit fileHighlighted(u.toString(false, false)); |
|
3813 } else if (files->isSelected(newItem)) { |
|
3814 Q3FileDialogPrivate::File * i = (Q3FileDialogPrivate::File *)newItem; |
|
3815 if (i && i->i && !i->i->isSelected()) { |
|
3816 d->moreFiles->blockSignals(true); |
|
3817 d->moreFiles->setSelected(i->i, true); |
|
3818 d->moreFiles->blockSignals(false); |
|
3819 } |
|
3820 // Encode the filename in case it had any special characters in it |
|
3821 QString encFile = Q3FileDialogPrivate::encodeFileName(newItem->text(0)); |
|
3822 trySetSelection(i->info.isDir(), Q3UrlOperator(d->url, encFile), true); |
|
3823 } |
|
3824 } |
|
3825 |
|
3826 void Q3FileDialog::detailViewSelectionChanged() |
|
3827 { |
|
3828 if (d->mode != ExistingFiles) |
|
3829 return; |
|
3830 |
|
3831 nameEdit->clear(); |
|
3832 QString str; |
|
3833 Q3ListViewItem * i = files->firstChild(); |
|
3834 d->moreFiles->blockSignals(true); |
|
3835 while(i) { |
|
3836 if (d->moreFiles && isVisible()) { |
|
3837 Q3FileDialogPrivate::File *f = (Q3FileDialogPrivate::File *)i; |
|
3838 if (f->i && f->i->isSelected() != i->isSelected()) |
|
3839 d->moreFiles->setSelected(f->i, i->isSelected()); |
|
3840 } |
|
3841 if (i->isSelected() && !((Q3FileDialogPrivate::File *)i)->info.isDir()) |
|
3842 str += QString::fromLatin1("\"%1\" ").arg(i->text(0)); |
|
3843 i = i->nextSibling(); |
|
3844 } |
|
3845 d->moreFiles->blockSignals(false); |
|
3846 nameEdit->setText(str); |
|
3847 nameEdit->setCursorPosition(str.length()); |
|
3848 okB->setEnabled(true); |
|
3849 if (d->preview && d->preview->isVisible() && files->currentItem()) { |
|
3850 Q3Url u = Q3Url(d->url, Q3FileDialogPrivate::encodeFileName(((Q3FileDialogPrivate::File*)files->currentItem())->info.name())); |
|
3851 updatePreviews(u); |
|
3852 } |
|
3853 } |
|
3854 |
|
3855 void Q3FileDialog::listBoxSelectionChanged() |
|
3856 { |
|
3857 if (d->mode != ExistingFiles) |
|
3858 return; |
|
3859 |
|
3860 if (d->ignoreNextRefresh) { |
|
3861 d->ignoreNextRefresh = false; |
|
3862 return; |
|
3863 } |
|
3864 |
|
3865 nameEdit->clear(); |
|
3866 QString str; |
|
3867 Q3ListBoxItem * i = d->moreFiles->item(0); |
|
3868 Q3ListBoxItem * j = 0; |
|
3869 int index = 0; |
|
3870 files->blockSignals(true); |
|
3871 while(i) { |
|
3872 Q3FileDialogPrivate::MCItem *mcitem = (Q3FileDialogPrivate::MCItem *)i; |
|
3873 if (files && isVisible()) { |
|
3874 if (mcitem->i->isSelected() != mcitem->isSelected()) { |
|
3875 files->setSelected(mcitem->i, mcitem->isSelected()); |
|
3876 |
|
3877 // What happens here is that we want to emit signal highlighted for |
|
3878 // newly added items. But Q3ListBox apparently emits selectionChanged even |
|
3879 // when a user clicks on the same item twice. So, basically emulate the behaivor |
|
3880 // we have in the "Details" view which only emits highlighted the first time we |
|
3881 // click on the item. Perhaps at some point we should have a call to |
|
3882 // updateFileNameEdit(Q3ListViewItem) which also emits fileHighlighted() for |
|
3883 // ExistingFiles. For better or for worse, this clones the behaivor of the |
|
3884 // "Details" view quite well. |
|
3885 if (mcitem->isSelected() && i != d->lastEFSelected) { |
|
3886 Q3Url u(d->url, Q3FileDialogPrivate::encodeFileName(((Q3FileDialogPrivate::File*)(mcitem)->i)->info.name())); |
|
3887 d->lastEFSelected = i; |
|
3888 emit fileHighlighted(u.toString(false, false)); |
|
3889 } |
|
3890 } |
|
3891 } |
|
3892 if (d->moreFiles->isSelected(i) |
|
3893 && !((Q3FileDialogPrivate::File*)(mcitem)->i)->info.isDir()) { |
|
3894 str += QString::fromLatin1("\"%1\" ").arg(i->text()); |
|
3895 if (j == 0) |
|
3896 j = i; |
|
3897 } |
|
3898 i = d->moreFiles->item(++index); |
|
3899 } |
|
3900 |
|
3901 files->blockSignals(false); |
|
3902 nameEdit->setText(str); |
|
3903 nameEdit->setCursorPosition(str.length()); |
|
3904 okB->setEnabled(true); |
|
3905 if (d->preview && d->preview->isVisible() && j) { |
|
3906 Q3Url u = Q3Url(d->url, |
|
3907 Q3FileDialogPrivate::encodeFileName(((Q3FileDialogPrivate::File*)((Q3FileDialogPrivate::MCItem*)j)->i)->info.name())); |
|
3908 updatePreviews(u); |
|
3909 } |
|
3910 } |
|
3911 |
|
3912 /*! \overload */ |
|
3913 |
|
3914 void Q3FileDialog::updateFileNameEdit(Q3ListBoxItem * newItem) |
|
3915 { |
|
3916 if (!newItem) |
|
3917 return; |
|
3918 Q3FileDialogPrivate::MCItem * i = (Q3FileDialogPrivate::MCItem *)newItem; |
|
3919 if (i->i) { |
|
3920 i->i->listView()->setSelected(i->i, i->isSelected()); |
|
3921 updateFileNameEdit(i->i); |
|
3922 } |
|
3923 } |
|
3924 |
|
3925 |
|
3926 /*! Updates the dialog when the file name edit changes. */ |
|
3927 |
|
3928 void Q3FileDialog::fileNameEditDone() |
|
3929 { |
|
3930 QUrlInfo f(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text())); |
|
3931 if (mode() != Q3FileDialog::ExistingFiles) { |
|
3932 Q3UrlOperator u(d->url, Q3FileDialogPrivate::encodeFileName(nameEdit->text())); |
|
3933 trySetSelection(f.isDir(), u, false); |
|
3934 if (d->preview && d->preview->isVisible()) |
|
3935 updatePreviews(u); |
|
3936 } |
|
3937 } |
|
3938 |
|
3939 |
|
3940 |
|
3941 /*! This private slot reacts to double-clicks in the list view. The item that |
|
3942 was double-clicked is specified in \a newItem */ |
|
3943 |
|
3944 void Q3FileDialog::selectDirectoryOrFile(Q3ListViewItem * newItem) |
|
3945 { |
|
3946 |
|
3947 *workingDirectory = d->url; |
|
3948 detailViewMode = files->isVisible(); |
|
3949 updateLastSize(this); |
|
3950 |
|
3951 if (!newItem) |
|
3952 return; |
|
3953 |
|
3954 if (d->url.isLocalFile()) { |
|
3955 QFileInfo fi(d->url.path() + newItem->text(0)); |
|
3956 #if defined(Q_WS_WIN) |
|
3957 if (fi.isSymLink()) { |
|
3958 nameEdit->setText(fi.symLinkTarget()); |
|
3959 okClicked(); |
|
3960 return; |
|
3961 } |
|
3962 #endif |
|
3963 } |
|
3964 |
|
3965 Q3FileDialogPrivate::File * i = (Q3FileDialogPrivate::File *)newItem; |
|
3966 |
|
3967 QString oldName = nameEdit->text(); |
|
3968 if (i->info.isDir()) { |
|
3969 setUrl(Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(i->info.name()) + QLatin1Char('/'))); |
|
3970 if (isDirectoryMode(mode())) { |
|
3971 QUrlInfo f (d->url.info(QString::fromLatin1("."))); |
|
3972 trySetSelection(f.isDir(), d->url, true); |
|
3973 } |
|
3974 } else if (newItem->isSelectable() && |
|
3975 trySetSelection(i->info.isDir(), Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(i->info.name())), true)) { |
|
3976 if (!isDirectoryMode(mode())) { |
|
3977 if (mode() == ExistingFile) { |
|
3978 if (Q3FileDialogPrivate::fileExists(d->url, nameEdit->text())) { |
|
3979 emit fileSelected(selectedFile()); |
|
3980 accept(); |
|
3981 } |
|
3982 } else { |
|
3983 emit fileSelected(selectedFile()); |
|
3984 accept(); |
|
3985 } |
|
3986 } |
|
3987 } else if (isDirectoryMode(d->mode)) { |
|
3988 d->currentFileName = d->url; |
|
3989 accept(); |
|
3990 } |
|
3991 if (!oldName.isEmpty() && !isDirectoryMode(mode())) |
|
3992 nameEdit->setText(oldName); |
|
3993 } |
|
3994 |
|
3995 |
|
3996 void Q3FileDialog::selectDirectoryOrFile(Q3ListBoxItem * newItem) |
|
3997 { |
|
3998 if (!newItem) |
|
3999 return; |
|
4000 |
|
4001 Q3FileDialogPrivate::MCItem * i = (Q3FileDialogPrivate::MCItem *)newItem; |
|
4002 if (i->i) { |
|
4003 i->i->listView()->setSelected(i->i, i->isSelected()); |
|
4004 selectDirectoryOrFile(i->i); |
|
4005 } |
|
4006 } |
|
4007 |
|
4008 |
|
4009 void Q3FileDialog::popupContextMenu(Q3ListViewItem *item, const QPoint &p, |
|
4010 int) |
|
4011 { |
|
4012 if (item) { |
|
4013 files->setCurrentItem(item); |
|
4014 files->setSelected(item, true); |
|
4015 } |
|
4016 |
|
4017 PopupAction action; |
|
4018 popupContextMenu(item ? item->text(0) : QString(), true, action, p); |
|
4019 |
|
4020 if (action == PA_Open) |
|
4021 selectDirectoryOrFile(item); |
|
4022 else if (action == PA_Rename) |
|
4023 files->startRename(false); |
|
4024 else if (action == PA_Delete) |
|
4025 deleteFile(item ? item->text(0) : QString()); |
|
4026 else if (action == PA_Reload) |
|
4027 rereadDir(); |
|
4028 else if (action == PA_Hidden) { |
|
4029 bShowHiddenFiles = !bShowHiddenFiles; |
|
4030 rereadDir(); |
|
4031 } else if (action == PA_SortName) { |
|
4032 sortFilesBy = (int)QDir::Name; |
|
4033 sortAscending = true; |
|
4034 resortDir(); |
|
4035 } else if (action == PA_SortSize) { |
|
4036 sortFilesBy = (int)QDir::Size; |
|
4037 sortAscending = true; |
|
4038 resortDir(); |
|
4039 } else if (action == PA_SortDate) { |
|
4040 sortFilesBy = (int)QDir::Time; |
|
4041 sortAscending = true; |
|
4042 resortDir(); |
|
4043 } else if (action == PA_SortUnsorted) { |
|
4044 sortFilesBy = (int)QDir::Unsorted; |
|
4045 sortAscending = true; |
|
4046 resortDir(); |
|
4047 } |
|
4048 |
|
4049 } |
|
4050 |
|
4051 void Q3FileDialog::popupContextMenu(Q3ListBoxItem *item, const QPoint & p) |
|
4052 { |
|
4053 PopupAction action; |
|
4054 popupContextMenu(item ? item->text() : QString(), false, action, p); |
|
4055 |
|
4056 if (action == PA_Open) |
|
4057 selectDirectoryOrFile(item); |
|
4058 else if (action == PA_Rename) |
|
4059 d->moreFiles->startRename(false); |
|
4060 else if (action == PA_Delete) |
|
4061 deleteFile(item->text()); |
|
4062 else if (action == PA_Reload) |
|
4063 rereadDir(); |
|
4064 else if (action == PA_Hidden) { |
|
4065 bShowHiddenFiles = !bShowHiddenFiles; |
|
4066 rereadDir(); |
|
4067 } else if (action == PA_SortName) { |
|
4068 sortFilesBy = (int)QDir::Name; |
|
4069 sortAscending = true; |
|
4070 resortDir(); |
|
4071 } else if (action == PA_SortSize) { |
|
4072 sortFilesBy = (int)QDir::Size; |
|
4073 sortAscending = true; |
|
4074 resortDir(); |
|
4075 } else if (action == PA_SortDate) { |
|
4076 sortFilesBy = (int)QDir::Time; |
|
4077 sortAscending = true; |
|
4078 resortDir(); |
|
4079 } else if (action == PA_SortUnsorted) { |
|
4080 sortFilesBy = (int)QDir::Unsorted; |
|
4081 sortAscending = true; |
|
4082 resortDir(); |
|
4083 } |
|
4084 } |
|
4085 |
|
4086 void Q3FileDialog::popupContextMenu(const QString &filename, bool, |
|
4087 PopupAction &action, const QPoint &p) |
|
4088 { |
|
4089 action = PA_Cancel; |
|
4090 |
|
4091 bool glob = filename.isEmpty(); |
|
4092 |
|
4093 Q3PopupMenu m(0, "file dialog context menu"); |
|
4094 m.setCheckable(true); |
|
4095 |
|
4096 if (!glob) { |
|
4097 QString okt; |
|
4098 if (QUrlInfo(d->url.info(filename.isEmpty() ? QString::fromLatin1(".") : fileName)).isDir()) { |
|
4099 okt = tr("&Open"); |
|
4100 } else { |
|
4101 if (mode() == AnyFile) |
|
4102 okt = tr("&Save"); |
|
4103 else |
|
4104 okt = tr("&Open"); |
|
4105 } |
|
4106 int ok = m.insertItem(okt); |
|
4107 |
|
4108 m.insertSeparator(); |
|
4109 int rename = m.insertItem(tr("&Rename")); |
|
4110 int del = m.insertItem(tr("&Delete")); |
|
4111 |
|
4112 if (filename.isEmpty() || !QUrlInfo(d->url.info(filename)).isWritable() || |
|
4113 filename == QLatin1String("..")) { |
|
4114 if (filename.isEmpty() || !QUrlInfo(d->url.info(filename)).isReadable()) |
|
4115 m.setItemEnabled(ok, false); |
|
4116 m.setItemEnabled(rename, false); |
|
4117 m.setItemEnabled(del, false); |
|
4118 } |
|
4119 |
|
4120 m.move(p); |
|
4121 int res = m.exec(QCursor::pos(), -1); |
|
4122 |
|
4123 if (res == ok) |
|
4124 action = PA_Open; |
|
4125 else if (res == rename) |
|
4126 action = PA_Rename; |
|
4127 else if (res == del) |
|
4128 action = PA_Delete; |
|
4129 } else { |
|
4130 int reload = m.insertItem(tr("R&eload")); |
|
4131 |
|
4132 Q3PopupMenu m2(0, "sort menu"); |
|
4133 |
|
4134 int sname = m2.insertItem(tr("Sort by &Name")); |
|
4135 //int stype = m2.insertItem(tr("Sort by &Type")); |
|
4136 int ssize = m2.insertItem(tr("Sort by &Size")); |
|
4137 int sdate = m2.insertItem(tr("Sort by &Date")); |
|
4138 m2.insertSeparator(); |
|
4139 int sunsorted = m2.insertItem(tr("&Unsorted")); |
|
4140 |
|
4141 //m2.setItemEnabled(stype, false); |
|
4142 |
|
4143 if (sortFilesBy == (int)QDir::Name) |
|
4144 m2.setItemChecked(sname, true); |
|
4145 else if (sortFilesBy == (int)QDir::Size) |
|
4146 m2.setItemChecked(ssize, true); |
|
4147 // else if (sortFilesBy == 0x16) |
|
4148 // m2.setItemChecked(stype, true); |
|
4149 else if (sortFilesBy == (int)QDir::Time) |
|
4150 m2.setItemChecked(sdate, true); |
|
4151 else if (sortFilesBy == (int)QDir::Unsorted) |
|
4152 m2.setItemChecked(sunsorted, true); |
|
4153 |
|
4154 m.insertItem(tr("Sort"), &m2); |
|
4155 |
|
4156 m.insertSeparator(); |
|
4157 |
|
4158 int hidden = m.insertItem(tr("Show &hidden files")); |
|
4159 m.setItemChecked(hidden, bShowHiddenFiles); |
|
4160 |
|
4161 m.move(p); |
|
4162 int res = m.exec(QCursor::pos(), -1); |
|
4163 |
|
4164 if (res == reload) |
|
4165 action = PA_Reload; |
|
4166 else if (res == hidden) |
|
4167 action = PA_Hidden; |
|
4168 else if (res == sname) |
|
4169 action = PA_SortName; |
|
4170 // else if (res == stype) |
|
4171 // action = PA_SortType; |
|
4172 else if (res == sdate) |
|
4173 action = PA_SortDate; |
|
4174 else if (res == ssize) |
|
4175 action = PA_SortSize; |
|
4176 else if (res == sunsorted) |
|
4177 action = PA_SortUnsorted; |
|
4178 } |
|
4179 |
|
4180 } |
|
4181 |
|
4182 void Q3FileDialog::deleteFile(const QString &filename) |
|
4183 { |
|
4184 if (filename.isEmpty()) |
|
4185 return; |
|
4186 |
|
4187 QString encoded = Q3FileDialogPrivate::encodeFileName(filename); |
|
4188 QUrlInfo fi(d->url.info(encoded.isEmpty() ? QString::fromLatin1(".") : encoded)); |
|
4189 QString t = tr("the file"); |
|
4190 if (fi.isDir()) |
|
4191 t = tr("the directory"); |
|
4192 if (fi.isSymLink()) |
|
4193 t = tr("the symlink"); |
|
4194 |
|
4195 if (QMessageBox::warning(this, |
|
4196 tr("Delete %1").arg(t), |
|
4197 tr("<qt>Are you sure you wish to delete %1 \"%2\"?</qt>") |
|
4198 .arg(t).arg(filename), |
|
4199 tr("&Yes"), tr("&No"), QString(), 1) == 0) |
|
4200 d->url.remove(Q3FileDialogPrivate::encodeFileName(filename)); |
|
4201 |
|
4202 } |
|
4203 |
|
4204 void Q3FileDialog::fileSelected(int ) |
|
4205 { |
|
4206 // unused |
|
4207 } |
|
4208 |
|
4209 void Q3FileDialog::fileHighlighted(int) |
|
4210 { |
|
4211 // unused |
|
4212 } |
|
4213 |
|
4214 void Q3FileDialog::dirSelected(int) |
|
4215 { |
|
4216 // unused |
|
4217 } |
|
4218 |
|
4219 void Q3FileDialog::pathSelected(int) |
|
4220 { |
|
4221 // unused |
|
4222 } |
|
4223 |
|
4224 |
|
4225 void Q3FileDialog::cdUpClicked() |
|
4226 { |
|
4227 QString oldName = nameEdit->text(); |
|
4228 setUrl(Q3UrlOperator(d->url, QLatin1String(".."))); |
|
4229 if (!oldName.isEmpty()) |
|
4230 nameEdit->setText(oldName); |
|
4231 } |
|
4232 |
|
4233 void Q3FileDialog::newFolderClicked() |
|
4234 { |
|
4235 QString foldername(tr("New Folder 1")); |
|
4236 int i = 0; |
|
4237 QStringList lst; |
|
4238 Q3ListViewItemIterator it(files); |
|
4239 for (; it.current(); ++it) |
|
4240 if (it.current()->text(0).contains(tr("New Folder"))) |
|
4241 lst.append(it.current()->text(0)); |
|
4242 |
|
4243 if (!lst.count() == 0) |
|
4244 while (lst.contains(foldername)) |
|
4245 foldername = tr("New Folder %1").arg(++i); |
|
4246 |
|
4247 d->url.mkdir(foldername); |
|
4248 } |
|
4249 |
|
4250 void Q3FileDialog::createdDirectory(const QUrlInfo &info, Q3NetworkOperation *) |
|
4251 { |
|
4252 resortDir(); |
|
4253 if (d->moreFiles->isVisible()) { |
|
4254 for (uint i = 0; i < d->moreFiles->count(); ++i) { |
|
4255 if (d->moreFiles->text(i) == info.name()) { |
|
4256 d->moreFiles->setCurrentItem(i); |
|
4257 d->moreFiles->startRename(false); |
|
4258 break; |
|
4259 } |
|
4260 } |
|
4261 } else { |
|
4262 Q3ListViewItem *item = files->firstChild(); |
|
4263 while (item) { |
|
4264 if (item->text(0) == info.name()) { |
|
4265 files->setSelected(item, true); |
|
4266 files->setCurrentItem(item); |
|
4267 files->startRename(false); |
|
4268 break; |
|
4269 } |
|
4270 item = item->nextSibling(); |
|
4271 } |
|
4272 } |
|
4273 } |
|
4274 |
|
4275 |
|
4276 /*! |
|
4277 This is a convenience static function that will return an existing directory |
|
4278 selected by the user. |
|
4279 |
|
4280 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 12 |
|
4281 |
|
4282 This function creates a modal file dialog called \a name, with |
|
4283 parent, \a parent. If parent is not 0, the dialog will be shown |
|
4284 centered over the parent. |
|
4285 |
|
4286 The dialog's working directory is set to \a dir, and the caption is |
|
4287 set to \a caption. Either of these may be an empty string in which case |
|
4288 the current directory and a default caption will be used respectively. |
|
4289 |
|
4290 If \a dirOnly is true, then only directories will be shown in |
|
4291 the file dialog; otherwise both directories and files will be shown. |
|
4292 |
|
4293 Under Unix/X11, the normal behavior of the file dialog is to resolve |
|
4294 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, |
|
4295 the file dialog will change to /var/tmp after entering /usr/tmp. |
|
4296 If \a resolveSymlinks is false, the file dialog will treat |
|
4297 symlinks as regular directories. |
|
4298 |
|
4299 Note that on Windows the dialog will spin a blocking modal event loop |
|
4300 that will not dispatch any QTimers and if parent is not 0 then it will |
|
4301 position the dialog just under the parent's title bar. |
|
4302 |
|
4303 \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() |
|
4304 */ |
|
4305 |
|
4306 QString Q3FileDialog::getExistingDirectory(const QString & dir, |
|
4307 QWidget *parent, |
|
4308 const char* name, |
|
4309 const QString& caption, |
|
4310 bool dirOnly, |
|
4311 bool resolveSymlinks) |
|
4312 { |
|
4313 bool save_qt_resolve_symlinks = qt_resolve_symlinks; |
|
4314 qt_resolve_symlinks = resolveSymlinks; |
|
4315 |
|
4316 makeVariables(); |
|
4317 QString wd; |
|
4318 if (workingDirectory) |
|
4319 wd = *workingDirectory; |
|
4320 |
|
4321 #if defined(Q_WS_WIN) |
|
4322 QString initialDir; |
|
4323 if (!dir.isEmpty()) { |
|
4324 Q3UrlOperator u(dir); |
|
4325 if (QFileInfo(u.path()).isDir()) |
|
4326 initialDir = dir; |
|
4327 } else |
|
4328 initialDir.clear(); |
|
4329 if (qt_use_native_dialogs && qobject_cast<QWindowsStyle *>(qApp->style()) && dirOnly) |
|
4330 return winGetExistingDirectory(initialDir, parent, name, caption); |
|
4331 #endif |
|
4332 #if defined(Q_WS_MAC) |
|
4333 if(qt_use_native_dialogs && qobject_cast<QMacStyle *>(qApp->style())) |
|
4334 return macGetOpenFileNames(QLatin1String(""), 0, parent, name, caption, |
|
4335 0, false, true).first().normalized(QString::NormalizationForm_C); |
|
4336 #endif |
|
4337 |
|
4338 Q3FileDialog *dlg = new Q3FileDialog(parent, name ? name : "qt_filedlg_ged", true); |
|
4339 |
|
4340 if (!caption.isNull()) |
|
4341 dlg->setWindowTitle(caption); |
|
4342 else |
|
4343 dlg->setWindowTitle(Q3FileDialog::tr("Find Directory")); |
|
4344 |
|
4345 dlg->setMode(dirOnly ? DirectoryOnly : Directory); |
|
4346 |
|
4347 dlg->d->types->clear(); |
|
4348 dlg->d->types->insertItem(Q3FileDialog::tr("Directories")); |
|
4349 dlg->d->types->setEnabled(false); |
|
4350 |
|
4351 QString dir_(dir); |
|
4352 dir_ = dir_.simplified(); |
|
4353 if (dir_.isEmpty() && !wd.isEmpty()) |
|
4354 dir_ = wd; |
|
4355 Q3UrlOperator u(dir_); |
|
4356 if (u.isLocalFile()) { |
|
4357 if (!dir_.isEmpty()) { |
|
4358 QFileInfo f(u.path()); |
|
4359 if (f.exists()) |
|
4360 if (f.isDir()) { |
|
4361 dlg->setDir(dir_); |
|
4362 wd = dir_; |
|
4363 } |
|
4364 } else if (!wd.isEmpty()) { |
|
4365 Q3Url tempUrl(wd); |
|
4366 QFileInfo f(tempUrl.path()); |
|
4367 if (f.isDir()) { |
|
4368 dlg->setDir(wd); |
|
4369 } |
|
4370 } else { |
|
4371 QString theDir = dir_; |
|
4372 if (theDir.isEmpty()) { |
|
4373 theDir = toRootIfNotExists( QDir::currentDirPath() ); |
|
4374 } if (!theDir.isEmpty()) { |
|
4375 Q3Url tempUrl(theDir); |
|
4376 QFileInfo f(tempUrl.path()); |
|
4377 if (f.isDir()) { |
|
4378 wd = theDir; |
|
4379 dlg->setDir(theDir); |
|
4380 } |
|
4381 } |
|
4382 } |
|
4383 } else { |
|
4384 dlg->setUrl(dir_); |
|
4385 } |
|
4386 |
|
4387 QString result; |
|
4388 dlg->setSelection(dlg->d->url.toString()); |
|
4389 |
|
4390 if (dlg->exec() == QDialog::Accepted) { |
|
4391 result = dlg->selectedFile(); |
|
4392 wd = result; |
|
4393 } |
|
4394 delete dlg; |
|
4395 |
|
4396 if (!result.isEmpty() && result.right(1) != QString(QLatin1Char('/'))) |
|
4397 result += QLatin1Char('/'); |
|
4398 |
|
4399 qt_resolve_symlinks = save_qt_resolve_symlinks; |
|
4400 |
|
4401 return result; |
|
4402 } |
|
4403 |
|
4404 |
|
4405 /*! |
|
4406 \property Q3FileDialog::mode |
|
4407 \brief the file dialog's mode |
|
4408 |
|
4409 The default mode is \l ExistingFile. |
|
4410 */ |
|
4411 |
|
4412 void Q3FileDialog::setMode(Mode newMode) |
|
4413 { |
|
4414 if (d->mode != newMode) { |
|
4415 d->mode = newMode; |
|
4416 QString sel = d->currentFileName; |
|
4417 int maxnamelen = 255; // _POSIX_MAX_PATH |
|
4418 if (isDirectoryMode(newMode)) { |
|
4419 files->setSelectionMode(Q3ListView::Single); |
|
4420 d->moreFiles->setSelectionMode(Q3ListBox::Single); |
|
4421 if (sel.isNull()) |
|
4422 sel = QString::fromLatin1("."); |
|
4423 d->types->setEnabled(false); |
|
4424 } else if (newMode == ExistingFiles) { |
|
4425 maxnamelen = INT_MAX; |
|
4426 files->setSelectionMode(Q3ListView::Extended); |
|
4427 d->moreFiles->setSelectionMode(Q3ListBox::Extended); |
|
4428 d->types->setEnabled(true); |
|
4429 } else { |
|
4430 files->setSelectionMode(Q3ListView::Single); |
|
4431 d->moreFiles->setSelectionMode(Q3ListBox::Single); |
|
4432 d->types->setEnabled(true); |
|
4433 } |
|
4434 nameEdit->setMaxLength(maxnamelen); |
|
4435 rereadDir(); |
|
4436 QUrlInfo f(d->url.info(QString(QLatin1Char('.')))); |
|
4437 trySetSelection(f.isDir(), d->url, false); |
|
4438 } |
|
4439 |
|
4440 QString okt; |
|
4441 bool changeFilters = false; |
|
4442 if (mode() == AnyFile) { |
|
4443 okt = tr("&Save"); |
|
4444 d->fileL->setText(tr("File &name:")); |
|
4445 if (d->types->count() == 1) { |
|
4446 d->types->setCurrentItem(0); |
|
4447 if (d->types->currentText() == QLatin1String("Directories")) { |
|
4448 changeFilters = true; |
|
4449 } |
|
4450 } |
|
4451 } |
|
4452 else if (mode() == Directory || mode() == DirectoryOnly) { |
|
4453 okt = tr("&OK"); |
|
4454 d->fileL->setText(tr("Directory:")); |
|
4455 d->types->clear(); |
|
4456 d->types->insertItem(tr("Directories")); |
|
4457 } |
|
4458 else { |
|
4459 okt = tr("&Open"); |
|
4460 d->fileL->setText(tr("File &name:")); |
|
4461 if (d->types->count() == 1) { |
|
4462 d->types->setCurrentItem(0); |
|
4463 if (d->types->currentText() == QLatin1String("Directories")) { |
|
4464 changeFilters = true; |
|
4465 } |
|
4466 } |
|
4467 } |
|
4468 |
|
4469 if (changeFilters) { |
|
4470 d->types->clear(); |
|
4471 d->types->insertItem(tr("All Files (*)")); |
|
4472 } |
|
4473 |
|
4474 okB->setText(okt); |
|
4475 } |
|
4476 |
|
4477 Q3FileDialog::Mode Q3FileDialog::mode() const |
|
4478 { |
|
4479 return d->mode; |
|
4480 } |
|
4481 |
|
4482 /*! \reimp |
|
4483 */ |
|
4484 |
|
4485 void Q3FileDialog::done(int i) |
|
4486 { |
|
4487 if (i == QDialog::Accepted && (d->mode == ExistingFile || d->mode == ExistingFiles)) { |
|
4488 QStringList selection = selectedFiles(); |
|
4489 for (int f = 0; f < selection.count(); f++) { |
|
4490 QString file = selection[f]; |
|
4491 if (file.isNull()) |
|
4492 continue; |
|
4493 if (d->url.isLocalFile() && !QFile::exists(file)) { |
|
4494 QMessageBox::information(this, tr("Error"), |
|
4495 tr("%1\nFile not found.\nCheck path and filename.").arg(file)); |
|
4496 return; |
|
4497 } |
|
4498 } |
|
4499 } |
|
4500 QDialog::done(i); |
|
4501 } |
|
4502 |
|
4503 /*! |
|
4504 \property Q3FileDialog::viewMode |
|
4505 |
|
4506 \brief the file dialog's view mode |
|
4507 |
|
4508 If you set the view mode to be \e Detail (the default), then you |
|
4509 will see the file's details, such as the size of the file and the |
|
4510 date the file was last modified in addition to the file's name. |
|
4511 |
|
4512 If you set the view mode to be \e List, then you will just |
|
4513 see a list of the files and folders. |
|
4514 |
|
4515 See \l Q3FileDialog::ViewMode |
|
4516 */ |
|
4517 |
|
4518 |
|
4519 Q3FileDialog::ViewMode Q3FileDialog::viewMode() const |
|
4520 { |
|
4521 if (detailViewMode) |
|
4522 return Detail; |
|
4523 else |
|
4524 return List; |
|
4525 } |
|
4526 |
|
4527 void Q3FileDialog::setViewMode(ViewMode m) |
|
4528 { |
|
4529 if (m == Detail) { |
|
4530 detailViewMode = true; |
|
4531 d->stack->raiseWidget(files); |
|
4532 d->detailView->setOn(true); |
|
4533 d->mcView->setOn(false); |
|
4534 } else if (m == List) { |
|
4535 detailViewMode = false; |
|
4536 d->stack->raiseWidget(d->moreFiles); |
|
4537 d->detailView->setOn(false); |
|
4538 d->mcView->setOn(true); |
|
4539 } |
|
4540 } |
|
4541 |
|
4542 |
|
4543 /*! |
|
4544 \property Q3FileDialog::previewMode |
|
4545 |
|
4546 \brief the preview mode for the file dialog |
|
4547 |
|
4548 If you set the mode to be a mode other than \e NoPreview, you must |
|
4549 use setInfoPreview() or setContentsPreview() to set the dialog's |
|
4550 preview widget to your preview widget and enable the preview |
|
4551 widget(s) with setInfoPreviewEnabled() or |
|
4552 setContentsPreviewEnabled(). |
|
4553 |
|
4554 \sa infoPreview, contentsPreview, viewMode |
|
4555 */ |
|
4556 |
|
4557 void Q3FileDialog::setPreviewMode(PreviewMode m) |
|
4558 { |
|
4559 if (m == NoPreview) { |
|
4560 d->previewInfo->setOn(false); |
|
4561 d->previewContents->setOn(false); |
|
4562 } else if (m == Info && d->infoPreview) { |
|
4563 d->previewInfo->setOn(true); |
|
4564 d->previewContents->setOn(false); |
|
4565 changeMode(d->modeButtons->id(d->previewInfo)); |
|
4566 } else if (m == Contents && d->contentsPreview) { |
|
4567 d->previewInfo->setOn(false); |
|
4568 d->previewContents->setOn(true); |
|
4569 changeMode(d->modeButtons->id(d->previewContents)); |
|
4570 } |
|
4571 } |
|
4572 Q3FileDialog::PreviewMode Q3FileDialog::previewMode() const |
|
4573 { |
|
4574 if (d->infoPreview && d->infoPreviewWidget->isVisibleTo(const_cast<Q3FileDialog *>(this))) |
|
4575 return Info; |
|
4576 else if (d->contentsPreview |
|
4577 && d->contentsPreviewWidget->isVisibleTo(const_cast<Q3FileDialog *>(this))) |
|
4578 return Contents; |
|
4579 return NoPreview; |
|
4580 } |
|
4581 |
|
4582 |
|
4583 /*! |
|
4584 Adds the specified widgets to the bottom of the file dialog. The |
|
4585 label \a l is placed underneath the "file name" and the "file types" |
|
4586 labels. The widget \a w is placed underneath the file types combobox. |
|
4587 The button \a b is placed underneath the Cancel push button. |
|
4588 |
|
4589 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 13 |
|
4590 |
|
4591 If you don't want to have one of the widgets added, pass 0 in that |
|
4592 widget's position. |
|
4593 |
|
4594 Every time you call this function, a new row of widgets will be added |
|
4595 to the bottom of the file dialog. |
|
4596 |
|
4597 \sa addToolButton(), addLeftWidget(), addRightWidget() |
|
4598 */ |
|
4599 |
|
4600 void Q3FileDialog::addWidgets(QLabel * l, QWidget * w, QPushButton * b) |
|
4601 { |
|
4602 if (!l && !w && !b) |
|
4603 return; |
|
4604 |
|
4605 d->geometryDirty = true; |
|
4606 |
|
4607 QHBoxLayout *lay = new QHBoxLayout(); |
|
4608 d->extraWidgetsLayouts.append(lay); |
|
4609 d->topLevelLayout->addLayout(lay); |
|
4610 |
|
4611 if (!l) |
|
4612 l = new QLabel(this, "qt_intern_lbl"); |
|
4613 d->extraLabels.append(l); |
|
4614 lay->addWidget(l); |
|
4615 |
|
4616 if (!w) |
|
4617 w = new QWidget(this, "qt_intern_widget"); |
|
4618 d->extraWidgets.append(w); |
|
4619 lay->addWidget(w); |
|
4620 lay->addSpacing(15); |
|
4621 |
|
4622 if (b) { |
|
4623 d->extraButtons.append(b); |
|
4624 lay->addWidget(b); |
|
4625 } else { |
|
4626 QWidget *wid = new QWidget(this, "qt_extrabuttons_widget"); |
|
4627 d->extraButtons.append(wid); |
|
4628 lay->addWidget(wid); |
|
4629 } |
|
4630 |
|
4631 updateGeometries(); |
|
4632 } |
|
4633 |
|
4634 /*! |
|
4635 Adds the tool button \a b to the row of tool buttons at the top of the |
|
4636 file dialog. The button is appended to the right of |
|
4637 this row. If \a separator is true, a small space is inserted between the |
|
4638 last button of the row and the new button \a b. |
|
4639 |
|
4640 \sa addWidgets(), addLeftWidget(), addRightWidget() |
|
4641 */ |
|
4642 |
|
4643 void Q3FileDialog::addToolButton(QAbstractButton *b, bool separator) |
|
4644 { |
|
4645 if (!b || !d->buttonLayout) |
|
4646 return; |
|
4647 |
|
4648 d->geometryDirty = true; |
|
4649 |
|
4650 d->toolButtons.append(b); |
|
4651 if (separator) |
|
4652 d->buttonLayout->addSpacing(8); |
|
4653 d->buttonLayout->addWidget(b); |
|
4654 |
|
4655 updateGeometries(); |
|
4656 } |
|
4657 |
|
4658 /*! |
|
4659 Adds the widget \a w to the left-hand side of the file dialog. |
|
4660 |
|
4661 \sa addRightWidget(), addWidgets(), addToolButton() |
|
4662 */ |
|
4663 |
|
4664 void Q3FileDialog::addLeftWidget(QWidget *w) |
|
4665 { |
|
4666 if (!w) |
|
4667 return; |
|
4668 d->geometryDirty = true; |
|
4669 |
|
4670 d->leftLayout->addWidget(w); |
|
4671 d->leftLayout->addSpacing(5); |
|
4672 |
|
4673 updateGeometries(); |
|
4674 } |
|
4675 |
|
4676 /*! |
|
4677 Adds the widget \a w to the right-hand side of the file dialog. |
|
4678 |
|
4679 \sa addLeftWidget(), addWidgets(), addToolButton() |
|
4680 */ |
|
4681 |
|
4682 void Q3FileDialog::addRightWidget(QWidget *w) |
|
4683 { |
|
4684 if (!w) |
|
4685 return; |
|
4686 d->geometryDirty = true; |
|
4687 |
|
4688 d->rightLayout->addSpacing(5); |
|
4689 d->rightLayout->addWidget(w); |
|
4690 |
|
4691 updateGeometries(); |
|
4692 } |
|
4693 |
|
4694 /*! \reimp */ |
|
4695 |
|
4696 void Q3FileDialog::keyPressEvent(QKeyEvent * ke) |
|
4697 { |
|
4698 if (!d->ignoreNextKeyPress && |
|
4699 ke && (ke->key() == Qt::Key_Enter || |
|
4700 ke->key() == Qt::Key_Return)) { |
|
4701 ke->ignore(); |
|
4702 if (d->paths->hasFocus()) { |
|
4703 ke->accept(); |
|
4704 if (d->url == Q3Url(d->paths->currentText())) |
|
4705 nameEdit->setFocus(); |
|
4706 } else if (d->types->hasFocus()) { |
|
4707 ke->accept(); |
|
4708 // ### is there a suitable condition for this? only valid |
|
4709 // wildcards? |
|
4710 nameEdit->setFocus(); |
|
4711 } else if (nameEdit->hasFocus()) { |
|
4712 if (d->currentFileName.isNull()) { |
|
4713 // maybe change directory |
|
4714 QUrlInfo i(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") :nameEdit->text())); |
|
4715 if (i.isDir()) { |
|
4716 nameEdit->setText(QString::fromLatin1("")); |
|
4717 setDir(Q3UrlOperator(d->url, Q3FileDialogPrivate::encodeFileName(i.name()))); |
|
4718 } |
|
4719 ke->accept(); |
|
4720 } else if (mode() == ExistingFiles) { |
|
4721 QUrlInfo i(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text())); |
|
4722 if (i.isFile()) { |
|
4723 Q3ListViewItem * i = files->firstChild(); |
|
4724 while (i && nameEdit->text() != i->text(0)) |
|
4725 i = i->nextSibling(); |
|
4726 if (i) |
|
4727 files->setSelected(i, true); |
|
4728 else |
|
4729 ke->accept(); // strangely, means to ignore that event |
|
4730 } |
|
4731 } |
|
4732 } else if (files->hasFocus() || d->moreFiles->hasFocus()) { |
|
4733 ke->accept(); |
|
4734 } |
|
4735 } else if (ke->key() == Qt::Key_Escape) { |
|
4736 ke->ignore(); |
|
4737 } |
|
4738 |
|
4739 d->ignoreNextKeyPress = false; |
|
4740 |
|
4741 if (!ke->isAccepted()) { |
|
4742 QDialog::keyPressEvent(ke); |
|
4743 } |
|
4744 } |
|
4745 |
|
4746 |
|
4747 /*! \class Q3FileIconProvider |
|
4748 |
|
4749 \brief The Q3FileIconProvider class provides icons for Q3FileDialog to |
|
4750 use. |
|
4751 |
|
4752 \compat |
|
4753 |
|
4754 By default Q3FileIconProvider is not used, but any application or |
|
4755 library can subclass it, reimplement pixmap() to return a suitable |
|
4756 icon, and make all Q3FileDialog objects use it by calling the static |
|
4757 function Q3FileDialog::setIconProvider(). |
|
4758 |
|
4759 It is advisable to make all the icons that Q3FileIconProvider returns be |
|
4760 the same size or at least the same width. This makes the list view |
|
4761 look much better. |
|
4762 |
|
4763 \sa Q3FileDialog |
|
4764 */ |
|
4765 |
|
4766 |
|
4767 /*! Constructs an empty file icon provider called \a name, with the |
|
4768 parent \a parent. |
|
4769 */ |
|
4770 |
|
4771 Q3FileIconProvider::Q3FileIconProvider(QObject * parent, const char* name) |
|
4772 : QObject(parent, name) |
|
4773 { |
|
4774 // nothing necessary |
|
4775 } |
|
4776 |
|
4777 |
|
4778 /*! |
|
4779 Returns a pointer to a pixmap that should be used to |
|
4780 signify the file with the information \a info. |
|
4781 |
|
4782 If pixmap() returns 0, Q3FileDialog draws the default pixmap. |
|
4783 |
|
4784 The default implementation returns particular icons for files, directories, |
|
4785 link-files and link-directories. It returns a blank "icon" for other types. |
|
4786 |
|
4787 If you return a pixmap here, it should measure 16x16 pixels. |
|
4788 */ |
|
4789 |
|
4790 const QPixmap * Q3FileIconProvider::pixmap(const QFileInfo & info) |
|
4791 { |
|
4792 if (info.isSymLink()) { |
|
4793 if (info.isFile()) |
|
4794 return symLinkFileIcon; |
|
4795 else |
|
4796 return symLinkDirIcon; |
|
4797 } else if (info.isDir()) { |
|
4798 return closedFolderIcon; |
|
4799 } else if (info.isFile()) { |
|
4800 return fileIcon; |
|
4801 } else { |
|
4802 return fifteenTransparentPixels; |
|
4803 } |
|
4804 } |
|
4805 |
|
4806 /*! |
|
4807 Sets the Q3FileIconProvider used by the file dialog to \a provider. |
|
4808 |
|
4809 The default is that there is no Q3FileIconProvider and Q3FileDialog |
|
4810 just draws a folder icon next to each directory and nothing next |
|
4811 to files. |
|
4812 |
|
4813 \sa Q3FileIconProvider, iconProvider() |
|
4814 */ |
|
4815 |
|
4816 void Q3FileDialog::setIconProvider(Q3FileIconProvider * provider) |
|
4817 { |
|
4818 fileIconProvider = provider; |
|
4819 } |
|
4820 |
|
4821 |
|
4822 /*! |
|
4823 Returns a pointer to the icon provider currently set on the file dialog. |
|
4824 By default there is no icon provider, and this function returns 0. |
|
4825 |
|
4826 \sa setIconProvider(), Q3FileIconProvider |
|
4827 */ |
|
4828 |
|
4829 Q3FileIconProvider * Q3FileDialog::iconProvider() |
|
4830 { |
|
4831 return fileIconProvider; |
|
4832 } |
|
4833 |
|
4834 |
|
4835 #if defined(Q_WS_WIN) |
|
4836 |
|
4837 // ### FIXME: this code is duplicated in qdns.cpp |
|
4838 static QString getWindowsRegString(HKEY key, const QString &subKey) |
|
4839 { |
|
4840 QString s; |
|
4841 |
|
4842 wchar_t buf[1024]; |
|
4843 DWORD bsz = sizeof(buf) / sizeof(wchar_t); |
|
4844 int r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)buf, &bsz); |
|
4845 if (r == ERROR_SUCCESS) { |
|
4846 s = QString::fromWCharArray(buf); |
|
4847 } else if (r == ERROR_MORE_DATA) { |
|
4848 char *ptr = new char[bsz+1]; |
|
4849 r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)ptr, &bsz); |
|
4850 if (r == ERROR_SUCCESS) |
|
4851 s = QLatin1String(ptr); |
|
4852 delete [] ptr; |
|
4853 } |
|
4854 |
|
4855 return s; |
|
4856 } |
|
4857 |
|
4858 QPixmap fromHICON(HICON hIcon) |
|
4859 { |
|
4860 ICONINFO icoInfo; |
|
4861 if (GetIconInfo(hIcon, &icoInfo) && icoInfo.hbmColor) { |
|
4862 return QPixmap::fromWinHBITMAP(icoInfo.hbmColor); |
|
4863 } |
|
4864 return QPixmap(); |
|
4865 } |
|
4866 |
|
4867 QWindowsIconProvider::QWindowsIconProvider(QObject *parent, const char *name) |
|
4868 : Q3FileIconProvider(parent, name) |
|
4869 { |
|
4870 pixw = GetSystemMetrics(SM_CXSMICON); |
|
4871 pixh = GetSystemMetrics(SM_CYSMICON); |
|
4872 |
|
4873 HKEY k; |
|
4874 HICON si; |
|
4875 QString s; |
|
4876 UINT res = 0; |
|
4877 |
|
4878 // ---------- get default folder pixmap |
|
4879 const wchar_t iconFolder[] = L"folder\\DefaultIcon"; // workaround for Borland |
|
4880 int r = RegOpenKeyEx(HKEY_CLASSES_ROOT, iconFolder, 0, KEY_READ, &k); |
|
4881 |
|
4882 if (r == ERROR_SUCCESS) { |
|
4883 s = getWindowsRegString(k, QString()); |
|
4884 RegCloseKey(k); |
|
4885 |
|
4886 QStringList lst = QStringList::split(QLatin1String(","), s); |
|
4887 |
|
4888 if (lst.count() >= 2) { // don't just assume that lst has two entries |
|
4889 res = ExtractIconEx((wchar_t*)lst[0].simplifyWhiteSpace().utf16(), lst[1].simplifyWhiteSpace().toInt(), 0, &si, 1); |
|
4890 } |
|
4891 |
|
4892 if (res) { |
|
4893 defaultFolder = fromHICON(si); |
|
4894 defaultFolder.setMask(defaultFolder.createHeuristicMask()); |
|
4895 *closedFolderIcon = defaultFolder; |
|
4896 DestroyIcon(si); |
|
4897 } else { |
|
4898 defaultFolder = *closedFolderIcon; |
|
4899 } |
|
4900 } else { |
|
4901 RegCloseKey(k); |
|
4902 } |
|
4903 |
|
4904 //------------------------------- get default file pixmap |
|
4905 res = ExtractIconEx(L"shell32.dll", 0, 0, &si, 1); |
|
4906 |
|
4907 if (res) { |
|
4908 defaultFile = fromHICON(si); |
|
4909 defaultFile.setMask(defaultFile.createHeuristicMask()); |
|
4910 *fileIcon = defaultFile; |
|
4911 DestroyIcon(si); |
|
4912 } else { |
|
4913 defaultFile = *fileIcon; |
|
4914 } |
|
4915 |
|
4916 //------------------------------- get default exe pixmap |
|
4917 #ifndef Q_OS_WINCE |
|
4918 res = ExtractIconEx(L"shell32.dll", 2, 0, &si, 1); |
|
4919 #else |
|
4920 res = ExtractIconEx(L"ceshell.dll", 10, 0, &si, 1); |
|
4921 #endif |
|
4922 |
|
4923 if (res) { |
|
4924 defaultExe = fromHICON(si); |
|
4925 defaultExe.setMask(defaultExe.createHeuristicMask()); |
|
4926 DestroyIcon(si); |
|
4927 } else { |
|
4928 defaultExe = *fileIcon; |
|
4929 } |
|
4930 } |
|
4931 |
|
4932 QWindowsIconProvider::~QWindowsIconProvider() |
|
4933 { |
|
4934 if (this == fileIconProvider) |
|
4935 fileIconProvider = 0; |
|
4936 } |
|
4937 |
|
4938 const QPixmap * QWindowsIconProvider::pixmap(const QFileInfo &fi) |
|
4939 { |
|
4940 if (fi.isSymLink()) { |
|
4941 QString real = fi.symLinkTarget(); |
|
4942 if (!real.isEmpty()) |
|
4943 return pixmap(QFileInfo(real)); |
|
4944 } |
|
4945 |
|
4946 QString ext = fi.extension(false).upper(); |
|
4947 QString key = ext; |
|
4948 ext.prepend(QLatin1String(".")); |
|
4949 QMap< QString, QPixmap >::Iterator it; |
|
4950 |
|
4951 if (fi.isDir()) { |
|
4952 return &defaultFolder; |
|
4953 } else if (ext.toLower() != QLatin1String(".exe")) { |
|
4954 it = cache.find(key); |
|
4955 if (it != cache.end()) |
|
4956 return &(*it); |
|
4957 |
|
4958 HKEY k, k2; |
|
4959 int r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (wchar_t*)ext.utf16(), 0, KEY_READ, &k); |
|
4960 QString s; |
|
4961 if (r == ERROR_SUCCESS) { |
|
4962 s = getWindowsRegString(k, QString()); |
|
4963 } else { |
|
4964 cache[key] = defaultFile; |
|
4965 RegCloseKey(k); |
|
4966 return &defaultFile; |
|
4967 } |
|
4968 RegCloseKey(k); |
|
4969 |
|
4970 r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (wchar_t*)QString(s + QLatin1String("\\DefaultIcon")).utf16(), |
|
4971 0, KEY_READ, &k2); |
|
4972 if (r == ERROR_SUCCESS) { |
|
4973 s = getWindowsRegString(k2, QString()); |
|
4974 } else { |
|
4975 cache[key] = defaultFile; |
|
4976 RegCloseKey(k2); |
|
4977 return &defaultFile; |
|
4978 } |
|
4979 RegCloseKey(k2); |
|
4980 |
|
4981 if (s.isEmpty()) |
|
4982 return &defaultFile; |
|
4983 |
|
4984 QStringList lst = QStringList::split(QLatin1String(","), s); |
|
4985 |
|
4986 HICON si; |
|
4987 UINT res = 0; |
|
4988 if (lst.count() >= 2) { // don't just assume that lst has two entries |
|
4989 QString filepath = lst[0].stripWhiteSpace(); |
|
4990 if (!filepath.isEmpty()) { |
|
4991 if (filepath.find(QLatin1String("%1")) != -1) { |
|
4992 filepath = filepath.arg(fi.filePath()); |
|
4993 if (ext.toLower() == QLatin1String(".dll")) { |
|
4994 pix = defaultFile; |
|
4995 return &pix; |
|
4996 } |
|
4997 } |
|
4998 if (filepath[0] == QLatin1Char('"') && filepath[(int)filepath.length()-1] == QLatin1Char('"')) |
|
4999 filepath = filepath.mid(1, filepath.length()-2); |
|
5000 |
|
5001 res = ExtractIconEx((wchar_t*)filepath.utf16(), lst[1].stripWhiteSpace().toInt(), 0, &si, 1); |
|
5002 } |
|
5003 } |
|
5004 if (res) { |
|
5005 pix = fromHICON(si); |
|
5006 pix.setMask(pix.createHeuristicMask()); |
|
5007 DestroyIcon(si); |
|
5008 } else { |
|
5009 pix = defaultFile; |
|
5010 } |
|
5011 |
|
5012 cache[key] = pix; |
|
5013 return &pix; |
|
5014 } else { |
|
5015 HICON si; |
|
5016 UINT res = 0; |
|
5017 if (!fi.absFilePath().isEmpty()) { |
|
5018 res = ExtractIconEx((wchar_t*)fi.absFilePath().utf16(), -1, 0, 0, 1); |
|
5019 if (res) |
|
5020 res = ExtractIconEx((wchar_t*)fi.absFilePath().utf16(), res - 1, 0, &si, 1); |
|
5021 } |
|
5022 |
|
5023 if (res) { |
|
5024 pix = fromHICON(si); |
|
5025 pix.setMask(pix.createHeuristicMask()); |
|
5026 DestroyIcon(si); |
|
5027 } else { |
|
5028 pix = defaultExe; |
|
5029 } |
|
5030 |
|
5031 return &pix; |
|
5032 } |
|
5033 |
|
5034 // can't happen! |
|
5035 return 0; |
|
5036 } |
|
5037 #endif |
|
5038 |
|
5039 |
|
5040 |
|
5041 /*! |
|
5042 \reimp |
|
5043 */ |
|
5044 bool Q3FileDialog::eventFilter(QObject * o, QEvent * e) |
|
5045 { |
|
5046 if (e->type() == QEvent::KeyPress && ((QKeyEvent*)e)->key() == Qt::Key_F5) { |
|
5047 rereadDir(); |
|
5048 ((QKeyEvent *)e)->accept(); |
|
5049 return true; |
|
5050 } else if (e->type() == QEvent::KeyPress && ((QKeyEvent*)e)->key() == Qt::Key_F2 && |
|
5051 (o == files || o == files->viewport())) { |
|
5052 if (files->isVisible() && files->currentItem()) { |
|
5053 if (QUrlInfo(d->url.info(QString(QLatin1Char('.')))).isWritable() && files->currentItem()->text(0) != QLatin1String("..")) { |
|
5054 files->renameItem = files->currentItem(); |
|
5055 files->startRename(true); |
|
5056 } |
|
5057 } |
|
5058 ((QKeyEvent *)e)->accept(); |
|
5059 return true; |
|
5060 } else if (e->type() == QEvent::KeyPress && ((QKeyEvent*)e)->key() == Qt::Key_F2 && |
|
5061 (o == d->moreFiles || o == d->moreFiles->viewport())) { |
|
5062 if (d->moreFiles->isVisible() && d->moreFiles->currentItem() != -1) { |
|
5063 if (QUrlInfo(d->url.info(QString(QLatin1Char('.')))).isWritable() && |
|
5064 d->moreFiles->item(d->moreFiles->currentItem())->text() != QLatin1String("..")) { |
|
5065 d->moreFiles->renameItem = d->moreFiles->item(d->moreFiles->currentItem()); |
|
5066 d->moreFiles->startRename(true); |
|
5067 } |
|
5068 } |
|
5069 ((QKeyEvent *)e)->accept(); |
|
5070 return true; |
|
5071 } else if (e->type() == QEvent::KeyPress && d->moreFiles->renaming) { |
|
5072 d->moreFiles->lined->setFocus(); |
|
5073 QApplication::sendEvent(d->moreFiles->lined, e); |
|
5074 ((QKeyEvent *)e)->accept(); |
|
5075 return true; |
|
5076 } else if (e->type() == QEvent::KeyPress && files->renaming) { |
|
5077 files->lined->setFocus(); |
|
5078 QApplication::sendEvent(files->lined, e); |
|
5079 ((QKeyEvent *)e)->accept(); |
|
5080 return true; |
|
5081 } else if (e->type() == QEvent::KeyPress && |
|
5082 ((QKeyEvent *)e)->key() == Qt::Key_Backspace && |
|
5083 (o == files || |
|
5084 o == d->moreFiles || |
|
5085 o == files->viewport() || |
|
5086 o == d->moreFiles->viewport())) { |
|
5087 cdUpClicked(); |
|
5088 ((QKeyEvent *)e)->accept(); |
|
5089 return true; |
|
5090 } else if (e->type() == QEvent::KeyPress && |
|
5091 ((QKeyEvent *)e)->key() == Qt::Key_Delete && |
|
5092 (o == files || |
|
5093 o == files->viewport())) { |
|
5094 if (files->currentItem()) |
|
5095 deleteFile(files->currentItem()->text(0)); |
|
5096 ((QKeyEvent *)e)->accept(); |
|
5097 return true; |
|
5098 } else if (e->type() == QEvent::KeyPress && |
|
5099 ((QKeyEvent *)e)->key() == Qt::Key_Delete && |
|
5100 (o == d->moreFiles || |
|
5101 o == d->moreFiles->viewport())) { |
|
5102 int c = d->moreFiles->currentItem(); |
|
5103 if (c >= 0) |
|
5104 deleteFile(d->moreFiles->item(c)->text()); |
|
5105 ((QKeyEvent *)e)->accept(); |
|
5106 return true; |
|
5107 } else if (o == files && e->type() == QEvent::FocusOut && files->currentItem()) { |
|
5108 } else if (o == files && e->type() == QEvent::KeyPress) { |
|
5109 QTimer::singleShot(0, this, SLOT(fixupNameEdit())); |
|
5110 } else if (o == nameEdit && e->type() == QEvent::KeyPress && d->mode != AnyFile) { |
|
5111 if ((nameEdit->cursorPosition() == (int)nameEdit->text().length() || nameEdit->hasSelectedText()) && |
|
5112 isprint(((QKeyEvent *)e)->ascii())) { |
|
5113 #if defined(Q_WS_WIN) |
|
5114 QString nt(nameEdit->text().toLower()); |
|
5115 #else |
|
5116 QString nt(nameEdit->text()); |
|
5117 #endif |
|
5118 nt.truncate(nameEdit->cursorPosition()); |
|
5119 nt += QLatin1Char((char)(((QKeyEvent *)e)->ascii())); |
|
5120 Q3ListViewItem * i = files->firstChild(); |
|
5121 #if defined(Q_WS_WIN) |
|
5122 while(i && i->text(0).left(nt.length()).toLower() != nt) |
|
5123 #else |
|
5124 while(i && i->text(0).left(nt.length()) != nt) |
|
5125 #endif |
|
5126 i = i->nextSibling(); |
|
5127 if (i) { |
|
5128 nt = i->text(0); |
|
5129 int cp = nameEdit->cursorPosition()+1; |
|
5130 nameEdit->validateAndSet(nt, cp, cp, nt.length()); |
|
5131 return true; |
|
5132 } |
|
5133 } |
|
5134 } else if (o == nameEdit && e->type() == QEvent::FocusIn) { |
|
5135 fileNameEditDone(); |
|
5136 } else if (d->moreFiles->renaming && o != d->moreFiles->lined && e->type() == QEvent::FocusIn) { |
|
5137 d->moreFiles->lined->setFocus(); |
|
5138 return true; |
|
5139 } else if (files->renaming && o != files->lined && e->type() == QEvent::FocusIn) { |
|
5140 files->lined->setFocus(); |
|
5141 return true; |
|
5142 } else if ((o == d->moreFiles || o == d->moreFiles->viewport()) && |
|
5143 e->type() == QEvent::FocusIn) { |
|
5144 if ((o == d->moreFiles->viewport() && !d->moreFiles->viewport()->hasFocus()) |
|
5145 || (o == d->moreFiles && !d->moreFiles->hasFocus())) |
|
5146 ((QWidget*)o)->setFocus(); |
|
5147 return false; |
|
5148 } |
|
5149 |
|
5150 return QDialog::eventFilter(o, e); |
|
5151 } |
|
5152 |
|
5153 /*! |
|
5154 Sets the filters used in the file dialog to \a filters. Each group |
|
5155 of filters must be separated by \c{;;} (\e two semicolons). |
|
5156 |
|
5157 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 14 |
|
5158 |
|
5159 */ |
|
5160 |
|
5161 void Q3FileDialog::setFilters(const QString &filters) |
|
5162 { |
|
5163 QStringList lst = makeFiltersList(filters); |
|
5164 setFilters(lst); |
|
5165 } |
|
5166 |
|
5167 /*! |
|
5168 \overload |
|
5169 |
|
5170 \a types must be a null-terminated list of strings. |
|
5171 |
|
5172 */ |
|
5173 |
|
5174 void Q3FileDialog::setFilters(const char ** types) |
|
5175 { |
|
5176 if (!types || !*types) |
|
5177 return; |
|
5178 |
|
5179 d->types->clear(); |
|
5180 while(types && *types) { |
|
5181 d->types->insertItem(QString::fromLatin1(*types)); |
|
5182 types++; |
|
5183 } |
|
5184 d->types->setCurrentItem(0); |
|
5185 setFilter(d->types->text(0)); |
|
5186 } |
|
5187 |
|
5188 |
|
5189 /*! |
|
5190 \overload |
|
5191 |
|
5192 \a types is a list of filter strings. |
|
5193 */ |
|
5194 |
|
5195 void Q3FileDialog::setFilters(const QStringList & types) |
|
5196 { |
|
5197 if (types.count() < 1) |
|
5198 return; |
|
5199 |
|
5200 d->types->clear(); |
|
5201 for (QStringList::ConstIterator it = types.begin(); it != types.end(); ++it) |
|
5202 d->types->insertItem(*it); |
|
5203 d->types->setCurrentItem(0); |
|
5204 setFilter(d->types->text(0)); |
|
5205 } |
|
5206 |
|
5207 /*! |
|
5208 Adds the filter \a filter to the list of filters and makes it the |
|
5209 current filter. |
|
5210 |
|
5211 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 15 |
|
5212 |
|
5213 In the above example, a file dialog is created, and the file filter "Images |
|
5214 (*.png *.jpg *.xpm)" is added and is set as the current filter. The original |
|
5215 filter, "All Files (*)", is still available. |
|
5216 |
|
5217 \sa setFilter(), setFilters() |
|
5218 */ |
|
5219 |
|
5220 void Q3FileDialog::addFilter(const QString &filter) |
|
5221 { |
|
5222 if (filter.isEmpty()) |
|
5223 return; |
|
5224 QString f = filter; |
|
5225 QRegExp r(QString::fromLatin1(qt3_file_dialog_filter_reg_exp)); |
|
5226 int index = r.indexIn(f); |
|
5227 if (index >= 0) |
|
5228 f = r.cap(2); |
|
5229 for (int i = 0; i < d->types->count(); ++i) { |
|
5230 QString f2(d->types->text(i)); |
|
5231 int index = r.indexIn(f2); |
|
5232 if (index >= 0) |
|
5233 f2 = r.cap(1); |
|
5234 if (f2 == f) { |
|
5235 d->types->setCurrentItem(i); |
|
5236 setFilter(f2); |
|
5237 return; |
|
5238 } |
|
5239 } |
|
5240 |
|
5241 d->types->insertItem(filter); |
|
5242 d->types->setCurrentItem(d->types->count() - 1); |
|
5243 setFilter(d->types->text(d->types->count() - 1)); |
|
5244 } |
|
5245 |
|
5246 /*! |
|
5247 Since modeButtons is a top-level widget, it may be destroyed by the |
|
5248 kernel at application exit. Notice if this happens to |
|
5249 avoid double deletion. |
|
5250 */ |
|
5251 |
|
5252 void Q3FileDialog::modeButtonsDestroyed() |
|
5253 { |
|
5254 if (d) |
|
5255 d->modeButtons = 0; |
|
5256 } |
|
5257 |
|
5258 |
|
5259 /*! |
|
5260 This is a convenience static function that will return one or more |
|
5261 existing files selected by the user. |
|
5262 |
|
5263 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 16 |
|
5264 |
|
5265 This function creates a modal file dialog called \a name, with |
|
5266 parent \a parent. If \a parent is not 0, the dialog will be shown |
|
5267 centered over the parent. |
|
5268 |
|
5269 The file dialog's working directory will be set to \a dir. If \a |
|
5270 dir includes a file name, the file will be selected. The filter |
|
5271 is set to \a filter so that only those files which match the filter |
|
5272 are shown. The filter selected is set to \a selectedFilter. The parameters |
|
5273 \a dir, \a selectedFilter and \a filter may be empty strings. |
|
5274 |
|
5275 The dialog's caption is set to \a caption. If \a caption is not |
|
5276 specified then a default caption will be used. |
|
5277 |
|
5278 Under Windows and Mac OS X, this static function will use the native |
|
5279 file dialog and not a Q3FileDialog, unless the style of the application |
|
5280 is set to something other than the native style. (Note that on Windows the |
|
5281 dialog will spin a blocking modal event loop that will not dispatch any |
|
5282 QTimers and if parent is not 0 then it will position the dialog just under |
|
5283 the parent's title bar). |
|
5284 |
|
5285 Under Unix/X11, the normal behavior of the file dialog is to resolve |
|
5286 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp, |
|
5287 the file dialog will change to /var/tmp after entering /usr/tmp. |
|
5288 If \a resolveSymlinks is false, the file dialog will treat |
|
5289 symlinks as regular directories. |
|
5290 |
|
5291 Note that if you want to iterate over the list of files, you should |
|
5292 iterate over a copy, e.g. |
|
5293 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 17 |
|
5294 |
|
5295 \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() |
|
5296 */ |
|
5297 |
|
5298 QStringList Q3FileDialog::getOpenFileNames(const QString & filter, |
|
5299 const QString& dir, |
|
5300 QWidget *parent, |
|
5301 const char* name, |
|
5302 const QString& caption, |
|
5303 QString *selectedFilter, |
|
5304 bool resolveSymlinks) |
|
5305 { |
|
5306 bool save_qt_resolve_symlinks = qt_resolve_symlinks; |
|
5307 qt_resolve_symlinks = resolveSymlinks; |
|
5308 |
|
5309 QStringList filters; |
|
5310 if (!filter.isEmpty()) |
|
5311 filters = makeFiltersList(filter); |
|
5312 |
|
5313 makeVariables(); |
|
5314 |
|
5315 if (workingDirectory->isNull()) |
|
5316 *workingDirectory = toRootIfNotExists( QDir::currentDirPath() ); |
|
5317 |
|
5318 if (!dir.isEmpty()) { |
|
5319 // #### works only correct for local files |
|
5320 Q3UrlOperator u(Q3FileDialogPrivate::encodeFileName(dir)); |
|
5321 if (u.isLocalFile() && QFileInfo(u.path()).isDir()) { |
|
5322 *workingDirectory = dir; |
|
5323 } else { |
|
5324 *workingDirectory = u.toString(); |
|
5325 } |
|
5326 } |
|
5327 |
|
5328 #if defined(Q_WS_WIN) |
|
5329 if (qt_use_native_dialogs && qobject_cast<QWindowsStyle *>(qApp->style())) |
|
5330 return winGetOpenFileNames(filter, workingDirectory, parent, name, caption, selectedFilter); |
|
5331 #elif defined(Q_WS_MAC) |
|
5332 if (qt_use_native_dialogs && qobject_cast<QMacStyle *>(qApp->style())) { |
|
5333 QStringList sl = macGetOpenFileNames(filter, dir.isEmpty() ? 0 : workingDirectory, |
|
5334 parent, name, caption, selectedFilter); |
|
5335 for (int i = 0; i < sl.count(); ++i) |
|
5336 sl.replace(i, sl.at(i).normalized(QString::NormalizationForm_C)); |
|
5337 return sl; |
|
5338 } |
|
5339 #endif |
|
5340 |
|
5341 Q3FileDialog *dlg = new Q3FileDialog(*workingDirectory, QString(), parent, name ? name : "qt_filedlg_gofns", true); |
|
5342 |
|
5343 if (!caption.isNull()) |
|
5344 dlg->setWindowTitle(caption); |
|
5345 else |
|
5346 dlg->setWindowTitle(Q3FileDialog::tr("Open")); |
|
5347 |
|
5348 dlg->setFilters(filters); |
|
5349 if (selectedFilter) |
|
5350 dlg->setFilter(*selectedFilter); |
|
5351 dlg->setMode(Q3FileDialog::ExistingFiles); |
|
5352 QString result; |
|
5353 QStringList lst; |
|
5354 if (dlg->exec() == QDialog::Accepted) { |
|
5355 lst = dlg->selectedFiles(); |
|
5356 *workingDirectory = dlg->d->url; |
|
5357 if (selectedFilter) |
|
5358 *selectedFilter = dlg->selectedFilter(); |
|
5359 } |
|
5360 delete dlg; |
|
5361 |
|
5362 qt_resolve_symlinks = save_qt_resolve_symlinks; |
|
5363 |
|
5364 return lst; |
|
5365 } |
|
5366 |
|
5367 /*! Updates the line edit to match the speed-key usage in Q3ListView. */ |
|
5368 |
|
5369 void Q3FileDialog::fixupNameEdit() |
|
5370 { |
|
5371 if (files->currentItem()) { |
|
5372 if (((Q3FileDialogPrivate::File*)files->currentItem())->info.isFile()) |
|
5373 nameEdit->setText(files->currentItem()->text(0)); |
|
5374 } |
|
5375 } |
|
5376 |
|
5377 /*! |
|
5378 Returns the URL of the current working directory in the file dialog. |
|
5379 |
|
5380 \sa setUrl() |
|
5381 */ |
|
5382 |
|
5383 Q3Url Q3FileDialog::url() const |
|
5384 { |
|
5385 return d->url; |
|
5386 } |
|
5387 |
|
5388 static bool isRoot(const Q3Url &u) |
|
5389 { |
|
5390 #if defined(Q_OS_UNIX) |
|
5391 if (u.path() == QString(QLatin1Char('/'))) |
|
5392 return true; |
|
5393 #elif defined(Q_OS_WIN32) |
|
5394 QString p = u.path(); |
|
5395 if (p.length() == 3 && |
|
5396 p.right(2) == QLatin1String(":/")) |
|
5397 return true; |
|
5398 if (p[0] == QLatin1Char('/') && p[1] == QLatin1Char('/')) { |
|
5399 int slashes = p.count(QLatin1Char('/')); |
|
5400 if (slashes <= 3) |
|
5401 return true; |
|
5402 if (slashes == 4 && p[(int)p.length() - 1] == QLatin1Char('/')) |
|
5403 return true; |
|
5404 } |
|
5405 #else |
|
5406 #if defined(Q_CC_GNU) |
|
5407 #warning "case not covered.." |
|
5408 #endif |
|
5409 #endif |
|
5410 |
|
5411 if (!u.isLocalFile() && u.path() == QString(QLatin1Char('/'))) |
|
5412 return true; |
|
5413 |
|
5414 return false; |
|
5415 } |
|
5416 |
|
5417 #if defined(Q_WS_WIN) |
|
5418 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; |
|
5419 #endif |
|
5420 |
|
5421 void Q3FileDialog::urlStart(Q3NetworkOperation *op) |
|
5422 { |
|
5423 if (!op) |
|
5424 return; |
|
5425 |
|
5426 #if defined(Q_WS_WIN) |
|
5427 old_qt_ntfs_permission_lookup = qt_ntfs_permission_lookup; |
|
5428 qt_ntfs_permission_lookup = 0; |
|
5429 #endif |
|
5430 if (op->operation() == Q3NetworkProtocol::OpListChildren) { |
|
5431 #ifndef QT_NO_CURSOR |
|
5432 if (!d->cursorOverride) { |
|
5433 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
|
5434 d->cursorOverride = true; |
|
5435 } |
|
5436 #endif |
|
5437 if (isRoot(d->url)) |
|
5438 d->cdToParent->setEnabled(false); |
|
5439 else |
|
5440 d->cdToParent->setEnabled(true); |
|
5441 d->mimeTypeTimer->stop(); |
|
5442 d->sortedList.clear(); |
|
5443 d->pendingItems.clear(); |
|
5444 d->moreFiles->clearSelection(); |
|
5445 files->clearSelection(); |
|
5446 d->moreFiles->clear(); |
|
5447 files->clear(); |
|
5448 files->setSorting(-1); |
|
5449 |
|
5450 QString s = d->url.toString(false, false); |
|
5451 bool found = false; |
|
5452 for (int i = 0; i < d->paths->count(); ++i) { |
|
5453 #if defined(Q_WS_WIN) |
|
5454 if (d->paths->text(i).toLower() == s.toLower()) { |
|
5455 #else |
|
5456 if (d->paths->text(i) == s) { |
|
5457 #endif |
|
5458 found = true; |
|
5459 d->paths->setCurrentItem(i); |
|
5460 break; |
|
5461 } |
|
5462 } |
|
5463 if (!found) { |
|
5464 d->paths->insertItem(*openFolderIcon, s, -1); |
|
5465 d->paths->setCurrentItem(d->paths->count() - 1); |
|
5466 } |
|
5467 d->last = 0; |
|
5468 d->hadDotDot = false; |
|
5469 |
|
5470 if (d->goBack && (d->history.isEmpty() || d->history.last() != d->url.toString())) { |
|
5471 d->history.append(d->url.toString()); |
|
5472 if (d->history.count() > 1) |
|
5473 d->goBack->setEnabled(true); |
|
5474 } |
|
5475 } |
|
5476 } |
|
5477 |
|
5478 void Q3FileDialog::urlFinished(Q3NetworkOperation *op) |
|
5479 { |
|
5480 if (!op) |
|
5481 return; |
|
5482 |
|
5483 #ifndef QT_NO_CURSOR |
|
5484 if (op->operation() == Q3NetworkProtocol::OpListChildren && |
|
5485 d->cursorOverride) { |
|
5486 QApplication::restoreOverrideCursor(); |
|
5487 d->cursorOverride = false; |
|
5488 } |
|
5489 #endif |
|
5490 |
|
5491 if (op->state() == Q3NetworkProtocol::StFailed) { |
|
5492 if (d->paths->hasFocus()) |
|
5493 d->ignoreNextKeyPress = true; |
|
5494 |
|
5495 if (d->progressDia) { |
|
5496 d->ignoreStop = true; |
|
5497 d->progressDia->close(); |
|
5498 delete d->progressDia; |
|
5499 d->progressDia = 0; |
|
5500 } |
|
5501 |
|
5502 int ecode = op->errorCode(); |
|
5503 QMessageBox::critical(this, tr("Error"), op->protocolDetail()); |
|
5504 |
|
5505 if (ecode == Q3NetworkProtocol::ErrListChildren || ecode == Q3NetworkProtocol::ErrParse || |
|
5506 ecode == Q3NetworkProtocol::ErrUnknownProtocol || ecode == Q3NetworkProtocol::ErrLoginIncorrect || |
|
5507 ecode == Q3NetworkProtocol::ErrValid || ecode == Q3NetworkProtocol::ErrHostNotFound || |
|
5508 ecode == Q3NetworkProtocol::ErrFileNotExisting) { |
|
5509 d->url = d->oldUrl; |
|
5510 rereadDir(); |
|
5511 } else { |
|
5512 // another error happened, no need to go back to last dir |
|
5513 } |
|
5514 } else if (op->operation() == Q3NetworkProtocol::OpListChildren && |
|
5515 op == d->currListChildren) { |
|
5516 if (!d->hadDotDot && !isRoot(d->url)) { |
|
5517 bool ok = true; |
|
5518 #if defined(Q_WS_WIN) |
|
5519 if (d->url.path().left(2) == QLatin1String("//")) |
|
5520 ok = false; |
|
5521 #endif |
|
5522 if (ok) { |
|
5523 QUrlInfo ui(d->url.info(QLatin1String(".."))); |
|
5524 ui.setName(QLatin1String("..")); |
|
5525 ui.setDir(true); |
|
5526 ui.setFile(false); |
|
5527 ui.setSymLink(false); |
|
5528 ui.setSize(0); |
|
5529 Q3ValueList<QUrlInfo> lst; |
|
5530 lst << ui; |
|
5531 insertEntry(lst, 0); |
|
5532 } |
|
5533 } |
|
5534 resortDir(); |
|
5535 } else if (op->operation() == Q3NetworkProtocol::OpGet) { |
|
5536 } else if (op->operation() == Q3NetworkProtocol::OpPut) { |
|
5537 rereadDir(); |
|
5538 if (d->progressDia) { |
|
5539 d->ignoreStop = true; |
|
5540 d->progressDia->close(); |
|
5541 } |
|
5542 delete d->progressDia; |
|
5543 d->progressDia = 0; |
|
5544 } |
|
5545 |
|
5546 #if defined(Q_WS_WIN) |
|
5547 qt_ntfs_permission_lookup = old_qt_ntfs_permission_lookup; |
|
5548 #endif |
|
5549 } |
|
5550 |
|
5551 void Q3FileDialog::dataTransferProgress(int bytesDone, int bytesTotal, Q3NetworkOperation *op) |
|
5552 { |
|
5553 if (!op) |
|
5554 return; |
|
5555 |
|
5556 QString label; |
|
5557 Q3Url u(op->arg(0)); |
|
5558 if (u.isLocalFile()) { |
|
5559 label = u.path(); |
|
5560 } else { |
|
5561 label = QLatin1String("%1 (on %2)"); |
|
5562 label = label.arg(u.path()).arg(u.host()); |
|
5563 } |
|
5564 |
|
5565 if (!d->progressDia) { |
|
5566 if (bytesDone < bytesTotal) { |
|
5567 d->ignoreStop = false; |
|
5568 d->progressDia = new QFDProgressDialog(this, label, bytesTotal); |
|
5569 connect(d->progressDia, SIGNAL(cancelled()), |
|
5570 this, SLOT(stopCopy())); |
|
5571 d->progressDia->show(); |
|
5572 } else |
|
5573 return; |
|
5574 } |
|
5575 |
|
5576 if (d->progressDia) { |
|
5577 if (op->operation() == Q3NetworkProtocol::OpGet) { |
|
5578 if (d->progressDia) { |
|
5579 d->progressDia->setReadProgress(bytesDone); |
|
5580 } |
|
5581 } else if (op->operation() == Q3NetworkProtocol::OpPut) { |
|
5582 if (d->progressDia) { |
|
5583 d->progressDia->setWriteLabel(label); |
|
5584 d->progressDia->setWriteProgress(bytesDone); |
|
5585 } |
|
5586 } else { |
|
5587 return; |
|
5588 } |
|
5589 } |
|
5590 } |
|
5591 |
|
5592 void Q3FileDialog::insertEntry(const Q3ValueList<QUrlInfo> &lst, Q3NetworkOperation *op) |
|
5593 { |
|
5594 if (op && op->operation() == Q3NetworkProtocol::OpListChildren && |
|
5595 op != d->currListChildren) |
|
5596 return; |
|
5597 Q3ValueList<QUrlInfo>::ConstIterator it = lst.begin(); |
|
5598 for (; it != lst.end(); ++it) { |
|
5599 const QUrlInfo &inf = *it; |
|
5600 if (d->mode == DirectoryOnly && !inf.isDir()) |
|
5601 continue; |
|
5602 if (inf.name() == QLatin1String("..")) { |
|
5603 d->hadDotDot = true; |
|
5604 if (isRoot(d->url)) |
|
5605 continue; |
|
5606 #if defined(Q_WS_WIN) |
|
5607 if (d->url.path().left(2) == QLatin1String("//")) |
|
5608 continue; |
|
5609 #endif |
|
5610 } else if (inf.name() == QString(QLatin1Char('.'))) |
|
5611 continue; |
|
5612 |
|
5613 #if defined(Q_WS_WIN) |
|
5614 // Workaround a Windows bug, '..' is apparantly hidden in directories |
|
5615 // that are one level away from root |
|
5616 if (!bShowHiddenFiles && inf.name() != QLatin1String("..")) { |
|
5617 if (d->url.isLocalFile()) { |
|
5618 QString file = d->url.path(); |
|
5619 if (!file.endsWith(QLatin1Char('/'))) |
|
5620 file.append(QLatin1Char('/')); |
|
5621 file += inf.name(); |
|
5622 if (GetFileAttributes((wchar_t*)file.utf16()) & FILE_ATTRIBUTE_HIDDEN) |
|
5623 continue; |
|
5624 } else { |
|
5625 if (inf.name() != QLatin1String("..") && inf.name()[0] == QLatin1Char('.')) |
|
5626 continue; |
|
5627 } |
|
5628 } |
|
5629 #else |
|
5630 if (!bShowHiddenFiles && inf.name() != QLatin1String("..")) { |
|
5631 if (inf.name()[0] == QLatin1Char('.')) |
|
5632 continue; |
|
5633 } |
|
5634 #endif |
|
5635 if (!d->url.isLocalFile()) { |
|
5636 Q3FileDialogPrivate::File * i = 0; |
|
5637 Q3FileDialogPrivate::MCItem *i2 = 0; |
|
5638 i = new Q3FileDialogPrivate::File(d, &inf, files); |
|
5639 i2 = new Q3FileDialogPrivate::MCItem(d->moreFiles, i); |
|
5640 |
|
5641 if ((d->mode == ExistingFiles && inf.isDir()) |
|
5642 || (isDirectoryMode(d->mode) && inf.isFile())) { |
|
5643 i->setSelectable(false); |
|
5644 i2->setSelectable(false); |
|
5645 } |
|
5646 |
|
5647 i->i = i2; |
|
5648 } |
|
5649 |
|
5650 d->sortedList.append(new QUrlInfo(inf)); |
|
5651 } |
|
5652 } |
|
5653 |
|
5654 void Q3FileDialog::removeEntry(Q3NetworkOperation *op) |
|
5655 { |
|
5656 if (!op) |
|
5657 return; |
|
5658 |
|
5659 QUrlInfo *i = 0; |
|
5660 Q3ListViewItemIterator it(files); |
|
5661 bool ok1 = false, ok2 = false; |
|
5662 for (i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next()) { |
|
5663 QString encName = Q3FileDialogPrivate::encodeFileName( |
|
5664 ((Q3FileDialogPrivate::File*)it.current())->info.name()); |
|
5665 if (encName == op->arg(0)) { |
|
5666 d->pendingItems.removeRef((Q3FileDialogPrivate::File*)it.current()); |
|
5667 delete ((Q3FileDialogPrivate::File*)it.current())->i; |
|
5668 delete it.current(); |
|
5669 ok1 = true; |
|
5670 } |
|
5671 if (i && i->name() == op->arg(0)) { |
|
5672 d->sortedList.removeRef(i); |
|
5673 i = d->sortedList.prev(); |
|
5674 ok2 = true; |
|
5675 } |
|
5676 if (ok1 && ok2) |
|
5677 break; |
|
5678 } |
|
5679 } |
|
5680 |
|
5681 void Q3FileDialog::itemChanged(Q3NetworkOperation *op) |
|
5682 { |
|
5683 if (!op) |
|
5684 return; |
|
5685 |
|
5686 QUrlInfo *i = 0; |
|
5687 Q3ListViewItemIterator it1(files); |
|
5688 bool ok1 = false, ok2 = false; |
|
5689 // first check whether the new file replaces an existing file. |
|
5690 for (i = d->sortedList.first(); it1.current(); ++it1, i = d->sortedList.next()) { |
|
5691 if (((Q3FileDialogPrivate::File*)it1.current())->info.name() == op->arg(1)) { |
|
5692 delete ((Q3FileDialogPrivate::File*)it1.current())->i; |
|
5693 delete it1.current(); |
|
5694 ok1 = true; |
|
5695 } |
|
5696 if (i && i->name() == op->arg(1)) { |
|
5697 d->sortedList.removeRef(i); |
|
5698 i = d->sortedList.prev(); |
|
5699 ok2 = true; |
|
5700 } |
|
5701 if (ok1 && ok2) |
|
5702 break; |
|
5703 } |
|
5704 |
|
5705 i = 0; |
|
5706 Q3ListViewItemIterator it(files); |
|
5707 ok1 = false; |
|
5708 ok2 = false; |
|
5709 for (i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next()) { |
|
5710 if (((Q3FileDialogPrivate::File*)it.current())->info.name() == op->arg(0)) { |
|
5711 ((Q3FileDialogPrivate::File*)it.current())->info.setName(op->arg(1)); |
|
5712 ok1 = true; |
|
5713 } |
|
5714 if (i && i->name() == op->arg(0)) { |
|
5715 i->setName(op->arg(1)); |
|
5716 ok2 = true; |
|
5717 } |
|
5718 if (ok1 && ok2) |
|
5719 break; |
|
5720 } |
|
5721 |
|
5722 resortDir(); |
|
5723 } |
|
5724 |
|
5725 /*! |
|
5726 \property Q3FileDialog::infoPreview |
|
5727 |
|
5728 \brief whether the file dialog can provide preview information about |
|
5729 the currently selected file |
|
5730 |
|
5731 The default is false. |
|
5732 */ |
|
5733 bool Q3FileDialog::isInfoPreviewEnabled() const |
|
5734 { |
|
5735 return d->infoPreview; |
|
5736 } |
|
5737 |
|
5738 void Q3FileDialog::setInfoPreviewEnabled(bool info) |
|
5739 { |
|
5740 if (info == d->infoPreview) |
|
5741 return; |
|
5742 d->geometryDirty = true; |
|
5743 d->infoPreview = info; |
|
5744 updateGeometries(); |
|
5745 } |
|
5746 |
|
5747 |
|
5748 /*! |
|
5749 \property Q3FileDialog::contentsPreview |
|
5750 |
|
5751 \brief whether the file dialog can provide a contents preview of the |
|
5752 currently selected file |
|
5753 |
|
5754 The default is false. |
|
5755 |
|
5756 \sa setContentsPreview() setInfoPreviewEnabled() |
|
5757 */ |
|
5758 // ### improve the above documentation: how is the preview done, how can I add |
|
5759 // support for customized preview, etc. |
|
5760 |
|
5761 bool Q3FileDialog::isContentsPreviewEnabled() const |
|
5762 { |
|
5763 return d->contentsPreview; |
|
5764 } |
|
5765 |
|
5766 void Q3FileDialog::setContentsPreviewEnabled(bool contents) |
|
5767 { |
|
5768 if (contents == d->contentsPreview) |
|
5769 return; |
|
5770 d->geometryDirty = true; |
|
5771 d->contentsPreview = contents; |
|
5772 updateGeometries(); |
|
5773 } |
|
5774 |
|
5775 |
|
5776 /*! |
|
5777 Sets the widget to be used for displaying information about the file |
|
5778 to the widget \a w and a preview of that information to the |
|
5779 Q3FilePreview \a preview. |
|
5780 |
|
5781 Normally you would create a preview widget that derives from both QWidget and |
|
5782 Q3FilePreview, so you should pass the same widget twice. |
|
5783 |
|
5784 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 18 |
|
5785 |
|
5786 \sa setContentsPreview(), setInfoPreviewEnabled(), setPreviewMode() |
|
5787 |
|
5788 */ |
|
5789 |
|
5790 void Q3FileDialog::setInfoPreview(QWidget *w, Q3FilePreview *preview) |
|
5791 { |
|
5792 if (!w || !preview) |
|
5793 return; |
|
5794 |
|
5795 if (d->infoPreviewWidget) { |
|
5796 d->preview->removeWidget(d->infoPreviewWidget); |
|
5797 if ((void*)d->infoPreviewer == (void*)d->infoPreviewWidget) |
|
5798 d->infoPreviewer = 0; |
|
5799 delete d->infoPreviewWidget; |
|
5800 } |
|
5801 if (d->infoPreviewer) |
|
5802 delete d->infoPreviewer; |
|
5803 d->infoPreviewWidget = w; |
|
5804 d->infoPreviewer = preview; |
|
5805 w->reparent(d->preview, 0, QPoint(0, 0)); |
|
5806 } |
|
5807 |
|
5808 /*! |
|
5809 Sets the widget to be used for displaying the contents of the file |
|
5810 to the widget \a w and a preview of those contents to the |
|
5811 Q3FilePreview \a preview. |
|
5812 |
|
5813 Normally you would create a preview widget that derives from both QWidget and |
|
5814 Q3FilePreview, so you should pass the same widget twice. |
|
5815 |
|
5816 \snippet doc/src/snippets/code/src_qt3support_dialogs_q3filedialog.cpp 19 |
|
5817 |
|
5818 \sa setContentsPreviewEnabled(), setInfoPreview(), setPreviewMode() |
|
5819 */ |
|
5820 |
|
5821 void Q3FileDialog::setContentsPreview(QWidget *w, Q3FilePreview *preview) |
|
5822 { |
|
5823 if (!w || !preview) |
|
5824 return; |
|
5825 |
|
5826 if (d->contentsPreviewWidget) { |
|
5827 d->preview->removeWidget(d->contentsPreviewWidget); |
|
5828 if ((void*)d->contentsPreviewWidget == (void*)d->contentsPreviewer) |
|
5829 d->contentsPreviewer = 0; |
|
5830 delete d->contentsPreviewWidget; |
|
5831 } |
|
5832 if (d->contentsPreviewer) |
|
5833 delete d->contentsPreviewer; |
|
5834 d->contentsPreviewWidget = w; |
|
5835 d->contentsPreviewer = preview; |
|
5836 w->reparent(d->preview, 0, QPoint(0, 0)); |
|
5837 } |
|
5838 |
|
5839 /*! |
|
5840 Re-sorts the displayed directory. |
|
5841 |
|
5842 \sa rereadDir() |
|
5843 */ |
|
5844 |
|
5845 void Q3FileDialog::resortDir() |
|
5846 { |
|
5847 d->mimeTypeTimer->stop(); |
|
5848 d->pendingItems.clear(); |
|
5849 |
|
5850 Q3FileDialogPrivate::File *item = 0; |
|
5851 Q3FileDialogPrivate::MCItem *item2 = 0; |
|
5852 |
|
5853 d->sortedList.sort(); |
|
5854 |
|
5855 if (files->childCount() > 0 || d->moreFiles->count() > 0) { |
|
5856 d->moreFiles->clear(); |
|
5857 files->clear(); |
|
5858 d->last = 0; |
|
5859 files->setSorting(-1); |
|
5860 } |
|
5861 |
|
5862 QUrlInfo *i = sortAscending ? d->sortedList.first() : d->sortedList.last(); |
|
5863 for (; i; i = sortAscending ? d->sortedList.next() : d->sortedList.prev()) { |
|
5864 item = new Q3FileDialogPrivate::File(d, i, files); |
|
5865 item2 = new Q3FileDialogPrivate::MCItem(d->moreFiles, item, item2); |
|
5866 item->i = item2; |
|
5867 d->pendingItems.append(item); |
|
5868 if ((d->mode == ExistingFiles && item->info.isDir()) || |
|
5869 (isDirectoryMode(d->mode) && item->info.isFile())) { |
|
5870 item->setSelectable(false); |
|
5871 item2->setSelectable(false); |
|
5872 } |
|
5873 } |
|
5874 |
|
5875 // ##### As the Q3FileIconProvider only support QFileInfo and no |
|
5876 // QUrlInfo it can be only used for local files at the moment. In |
|
5877 // 3.0 we have to change the API of Q3FileIconProvider to work on |
|
5878 // QUrlInfo so that also remote filesystems can be show mime-type |
|
5879 // specific icons. |
|
5880 if (d->url.isLocalFile()) |
|
5881 d->mimeTypeTimer->start(0); |
|
5882 } |
|
5883 |
|
5884 /*! |
|
5885 Stops the current copy operation. |
|
5886 */ |
|
5887 |
|
5888 void Q3FileDialog::stopCopy() |
|
5889 { |
|
5890 if (d->ignoreStop) |
|
5891 return; |
|
5892 |
|
5893 d->url.blockSignals(true); |
|
5894 d->url.stop(); |
|
5895 if (d->progressDia) { |
|
5896 d->ignoreStop = true; |
|
5897 QTimer::singleShot(100, this, SLOT(removeProgressDia())); |
|
5898 } |
|
5899 d->url.blockSignals(false); |
|
5900 } |
|
5901 |
|
5902 /*! |
|
5903 \internal |
|
5904 */ |
|
5905 |
|
5906 void Q3FileDialog::removeProgressDia() |
|
5907 { |
|
5908 if (d->progressDia) |
|
5909 delete d->progressDia; |
|
5910 d->progressDia = 0; |
|
5911 } |
|
5912 |
|
5913 /*! |
|
5914 \internal |
|
5915 */ |
|
5916 |
|
5917 void Q3FileDialog::doMimeTypeLookup() |
|
5918 { |
|
5919 if (!iconProvider()) { |
|
5920 d->pendingItems.clear(); |
|
5921 d->mimeTypeTimer->stop(); |
|
5922 return; |
|
5923 } |
|
5924 |
|
5925 d->mimeTypeTimer->stop(); |
|
5926 if (d->pendingItems.count() == 0) { |
|
5927 return; |
|
5928 } |
|
5929 |
|
5930 QRect r; |
|
5931 Q3FileDialogPrivate::File *item = d->pendingItems.first(); |
|
5932 if (item) { |
|
5933 QFileInfo fi; |
|
5934 if (d->url.isLocalFile()) { |
|
5935 fi.setFile(Q3Url(d->url.path(), Q3FileDialogPrivate::encodeFileName(item->info.name())).path(false)); |
|
5936 } else |
|
5937 fi.setFile(item->info.name()); // ##### |
|
5938 const QPixmap *p = iconProvider()->pixmap(fi); |
|
5939 if (p && p != item->pixmap(0) && |
|
5940 (!item->pixmap(0) || p->serialNumber() != item->pixmap(0)->serialNumber()) && |
|
5941 p != fifteenTransparentPixels) { |
|
5942 item->hasMimePixmap = true; |
|
5943 |
|
5944 // evil hack to avoid much too much repaints! |
|
5945 QPointer<Q3FileDialog> that(this); // this may be deleted by an event handler |
|
5946 qApp->processEvents(); |
|
5947 if (that.isNull()) |
|
5948 return; |
|
5949 files->setUpdatesEnabled(false); |
|
5950 files->viewport()->setUpdatesEnabled(false); |
|
5951 if (item != d->pendingItems.first()) |
|
5952 return; |
|
5953 item->setPixmap(0, *p); |
|
5954 qApp->processEvents(); |
|
5955 if (that.isNull()) |
|
5956 return; |
|
5957 files->setUpdatesEnabled(true); |
|
5958 files->viewport()->setUpdatesEnabled(true); |
|
5959 |
|
5960 if (files->isVisible()) { |
|
5961 QRect ir(files->itemRect(item)); |
|
5962 if (ir != QRect(0, 0, -1, -1)) { |
|
5963 r = r.united(ir); |
|
5964 } |
|
5965 } else { |
|
5966 QRect ir(d->moreFiles->itemRect(item->i)); |
|
5967 if (ir != QRect(0, 0, -1, -1)) { |
|
5968 r = r.united(ir); |
|
5969 } |
|
5970 } |
|
5971 } |
|
5972 if (d->pendingItems.count()) |
|
5973 d->pendingItems.removeFirst(); |
|
5974 } |
|
5975 |
|
5976 if (d->moreFiles->isVisible()) { |
|
5977 d->moreFiles->viewport()->repaint(r); |
|
5978 } else { |
|
5979 files->viewport()->repaint(r); |
|
5980 } |
|
5981 |
|
5982 if (d->pendingItems.count()) |
|
5983 d->mimeTypeTimer->start(0); |
|
5984 else if (d->moreFiles->isVisible()) |
|
5985 d->moreFiles->triggerUpdate(true); |
|
5986 } |
|
5987 |
|
5988 /*! |
|
5989 If \a b is true then all the files in the current directory are selected; |
|
5990 otherwise, they are deselected. |
|
5991 */ |
|
5992 |
|
5993 void Q3FileDialog::selectAll(bool b) |
|
5994 { |
|
5995 if (d->mode != ExistingFiles) |
|
5996 return; |
|
5997 d->moreFiles->selectAll(b); |
|
5998 files->selectAll(b); |
|
5999 } |
|
6000 |
|
6001 void Q3FileDialog::goBack() |
|
6002 { |
|
6003 if (!d->goBack || !d->goBack->isEnabled() || d->history.isEmpty()) |
|
6004 return; |
|
6005 d->history.removeLast(); |
|
6006 if (d->history.size() < 2) |
|
6007 d->goBack->setEnabled(false); |
|
6008 setUrl(d->history.last()); |
|
6009 } |
|
6010 |
|
6011 // a class with wonderfully inflexible flexibility. why doesn't it |
|
6012 // just subclass QWidget in the first place? 'you have to derive your |
|
6013 // preview widget from QWidget and from this class' indeed. |
|
6014 |
|
6015 /*! |
|
6016 \class Q3FilePreview |
|
6017 \brief The Q3FilePreview class provides file previewing in Q3FileDialog. |
|
6018 |
|
6019 \compat |
|
6020 |
|
6021 This class is an abstract base class which is used to implement |
|
6022 widgets that can display a preview of a file in a Q3FileDialog. |
|
6023 |
|
6024 You must derive the preview widget from both QWidget and from this |
|
6025 class. Then you must reimplement this class's previewUrl() function, |
|
6026 which is called by the file dialog if the preview of a file |
|
6027 (specified as a URL) should be shown. |
|
6028 |
|
6029 See also Q3FileDialog::setPreviewMode(), Q3FileDialog::setContentsPreview(), |
|
6030 Q3FileDialog::setInfoPreview(), Q3FileDialog::setInfoPreviewEnabled(), |
|
6031 Q3FileDialog::setContentsPreviewEnabled(). |
|
6032 */ |
|
6033 |
|
6034 /*! |
|
6035 Constructs the Q3FilePreview. |
|
6036 */ |
|
6037 |
|
6038 Q3FilePreview::Q3FilePreview() |
|
6039 { |
|
6040 } |
|
6041 |
|
6042 /*! |
|
6043 \fn Q3FilePreview::~Q3FilePreview() |
|
6044 |
|
6045 Destroys the file preview object. |
|
6046 */ |
|
6047 |
|
6048 /*! |
|
6049 \fn void Q3FilePreview::previewUrl(const Q3Url &url) |
|
6050 |
|
6051 This function is called by Q3FileDialog if a preview |
|
6052 for the \a url should be shown. Reimplement this |
|
6053 function to provide file previewing. |
|
6054 */ |
|
6055 |
|
6056 #endif // QT_MAC_USE_COCOA |
|
6057 |
|
6058 QT_END_NAMESPACE |
|
6059 |
|
6060 #include "moc_q3filedialog.cpp" |
|
6061 #include "q3filedialog.moc" |
|
6062 |
|
6063 #endif |