00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qplatformdefs.h"
00025
00026 #include "q3filedialog.h"
00027
00028 #ifndef QT_NO_FILEDIALOG
00029
00030 #include "private/qapplication_p.h"
00031 #include "q3buttongroup.h"
00032 #include "q3header.h"
00033 #include "q3listview.h"
00034 #include "qapplication.h"
00035 #include "qbitmap.h"
00036 #include "qcheckbox.h"
00037 #include "q3cleanuphandler.h"
00038 #include "qcombobox.h"
00039 #include "q3combobox.h"
00040 #include "q3cstring.h"
00041 #include "qcursor.h"
00042 #include "qdesktopwidget.h"
00043 #include "q3dragobject.h"
00044 #include "qevent.h"
00045 #include "qfile.h"
00046 #include "qlabel.h"
00047 #include "qlayout.h"
00048 #include "qlibrary.h"
00049 #include "qlineedit.h"
00050 #include "q3listbox.h"
00051 #include "qmap.h"
00052 #include "qmessagebox.h"
00053 #include "qmime.h"
00054 #include "qpainter.h"
00055 #include "qpointer.h"
00056 #include "q3popupmenu.h"
00057 #include "q3progressbar.h"
00058 #include "q3ptrvector.h"
00059 #include "qpushbutton.h"
00060 #include "qregexp.h"
00061 #include "qsplitter.h"
00062 #include "q3strlist.h"
00063 #include "qstyle.h"
00064 #include "qtimer.h"
00065 #include "qtoolbutton.h"
00066 #include "qtooltip.h"
00067 #include "q3widgetstack.h"
00068 #include "q3urloperator.h"
00069 #include "q3vbox.h"
00070 #include "qurlinfo.h"
00071
00072 #ifdef Q_WS_WIN
00073 #ifndef QT_NO_THREAD
00074 # include "qwindowsstyle.h"
00075 # include "private/qmutexpool_p.h"
00076 #endif
00077 #endif // Q_WS_WIN
00078
00079 #ifndef Q_OS_TEMP
00080 #include <time.h>
00081 #else
00082 #include <shellapi.h>
00083 #endif // Q_OS_TEMP
00084 #include <stdlib.h>
00085 #include <limits.h>
00086 #include <ctype.h>
00087
00088 #ifdef Q_WS_MAC
00089 #include "qmacstyle_mac.h"
00090 #include "private/qt_mac_p.h"
00091 #include "private/qunicodetables_p.h"
00092 #undef check
00093 #endif
00094
00095
00096 static const char * const start_xpm[]={
00097 "16 15 8 1",
00098 "a c #cec6bd",
00099 "# c #000000",
00100 "e c #ffff00",
00101 "b c #999999",
00102 "f c #cccccc",
00103 "d c #dcdcdc",
00104 "c c #ffffff",
00105 ". c None",
00106 ".....######aaaaa",
00107 "...bb#cccc##aaaa",
00108 "..bcc#cccc#d#aaa",
00109 ".bcef#cccc#dd#aa",
00110 ".bcfe#cccc#####a",
00111 ".bcef#ccccccccc#",
00112 "bbbbbbbbbbbbccc#",
00113 "bccccccccccbbcc#",
00114 "bcefefefefee#bc#",
00115 ".bcefefefefef#c#",
00116 ".bcfefefefefe#c#",
00117 "..bcfefefefeeb##",
00118 "..bbbbbbbbbbbbb#",
00119 "...#############",
00120 "................"};
00121
00122
00123 static const char * const end_xpm[]={
00124 "16 15 9 1",
00125 "d c #a0a0a0",
00126 "c c #c3c3c3",
00127 "# c #cec6bd",
00128 ". c #000000",
00129 "f c #ffff00",
00130 "e c #999999",
00131 "g c #cccccc",
00132 "b c #ffffff",
00133 "a c None",
00134 "......####aaaaaa",
00135 ".bbbb..###aaaaaa",
00136 ".bbbb.c.##aaaaaa",
00137 ".bbbb....ddeeeea",
00138 ".bbbbbbb.bbbbbe.",
00139 ".bbbbbbb.bcfgfe.",
00140 "eeeeeeeeeeeeefe.",
00141 "ebbbbbbbbbbeege.",
00142 "ebfgfgfgfgff.ee.",
00143 "aebfgfgfgfgfg.e.",
00144 "aebgfgfgfgfgf.e.",
00145 "aaebgfgfgfgffe..",
00146 "aaeeeeeeeeeeeee.",
00147 "aaa.............",
00148 "aaaaaaaaaaaaaaaa"};
00149
00150
00151 static const char* const open_xpm[]={
00152 "16 16 6 1",
00153 ". c None",
00154 "b c #ffff00",
00155 "d c #000000",
00156 "* c #999999",
00157 "c c #cccccc",
00158 "a c #ffffff",
00159 "................",
00160 "................",
00161 "...*****........",
00162 "..*aaaaa*.......",
00163 ".*abcbcba******.",
00164 ".*acbcbcaaaaaa*d",
00165 ".*abcbcbcbcbcb*d",
00166 "*************b*d",
00167 "*aaaaaaaaaa**c*d",
00168 "*abcbcbcbcbbd**d",
00169 ".*abcbcbcbcbcd*d",
00170 ".*acbcbcbcbcbd*d",
00171 "..*acbcbcbcbb*dd",
00172 "..*************d",
00173 "...ddddddddddddd",
00174 "................"};
00175
00176
00177 static const char * const link_dir_xpm[]={
00178 "16 16 10 1",
00179 "h c #808080",
00180 "g c #a0a0a0",
00181 "d c #000000",
00182 "b c #ffff00",
00183 "f c #303030",
00184 "# c #999999",
00185 "a c #cccccc",
00186 "e c #585858",
00187 "c c #ffffff",
00188 ". c None",
00189 "................",
00190 "................",
00191 "..#####.........",
00192 ".#ababa#........",
00193 "#abababa######..",
00194 "#cccccccccccc#d.",
00195 "#cbababababab#d.",
00196 "#cabababababa#d.",
00197 "#cbababdddddddd.",
00198 "#cababadccccccd.",
00199 "#cbababdcececcd.",
00200 "#cababadcefdfcd.",
00201 "#cbababdccgdhcd.",
00202 "#######dccchccd.",
00203 ".dddddddddddddd.",
00204 "................"};
00205
00206
00207 static const char * const link_file_xpm[]={
00208 "16 16 10 1",
00209 "h c #808080",
00210 "g c #a0a0a0",
00211 "d c #c3c3c3",
00212 ". c #7f7f7f",
00213 "c c #000000",
00214 "b c #bfbfbf",
00215 "f c #303030",
00216 "e c #585858",
00217 "a c #ffffff",
00218 "# c None",
00219 "################",
00220 "..........######",
00221 ".aaaaaaaab.#####",
00222 ".aaaaaaaaba.####",
00223 ".aaaaaaaacccc###",
00224 ".aaaaaaaaaabc###",
00225 ".aaaaaaaaaabc###",
00226 ".aaaaaaaaaadc###",
00227 ".aaaaaaaaaadc###",
00228 ".aaaacccccccc###",
00229 ".aaaacaaaaaac###",
00230 ".aaaacaeaeaac###",
00231 ".aaaacaefcfac###",
00232 ".aaaacaagchac###",
00233 ".ddddcaaahaac###",
00234 "ccccccccccccc###"};
00235
00236
00237 static const char* const file_xpm[]={
00238 "16 16 5 1",
00239 ". c #7f7f7f",
00240 "# c None",
00241 "c c #000000",
00242 "b c #bfbfbf",
00243 "a c #ffffff",
00244 "################",
00245 "..........######",
00246 ".aaaaaaaab.#####",
00247 ".aaaaaaaaba.####",
00248 ".aaaaaaaacccc###",
00249 ".aaaaaaaaaabc###",
00250 ".aaaaaaaaaabc###",
00251 ".aaaaaaaaaabc###",
00252 ".aaaaaaaaaabc###",
00253 ".aaaaaaaaaabc###",
00254 ".aaaaaaaaaabc###",
00255 ".aaaaaaaaaabc###",
00256 ".aaaaaaaaaabc###",
00257 ".aaaaaaaaaabc###",
00258 ".bbbbbbbbbbbc###",
00259 "ccccccccccccc###"};
00260
00261
00262 static const char * const closed_xpm[]={
00263 "16 16 6 1",
00264 ". c None",
00265 "b c #ffff00",
00266 "d c #000000",
00267 "* c #999999",
00268 "a c #cccccc",
00269 "c c #ffffff",
00270 "................",
00271 "................",
00272 "..*****.........",
00273 ".*ababa*........",
00274 "*abababa******..",
00275 "*cccccccccccc*d.",
00276 "*cbababababab*d.",
00277 "*cabababababa*d.",
00278 "*cbababababab*d.",
00279 "*cabababababa*d.",
00280 "*cbababababab*d.",
00281 "*cabababababa*d.",
00282 "*cbababababab*d.",
00283 "**************d.",
00284 ".dddddddddddddd.",
00285 "................"};
00286
00287
00288
00289 static const char* const cdtoparent_xpm[]={
00290 "15 13 3 1",
00291 ". c None",
00292 "* c #000000",
00293 "a c #ffff99",
00294 "..*****........",
00295 ".*aaaaa*.......",
00296 "***************",
00297 "*aaaaaaaaaaaaa*",
00298 "*aaaa*aaaaaaaa*",
00299 "*aaa***aaaaaaa*",
00300 "*aa*****aaaaaa*",
00301 "*aaaa*aaaaaaaa*",
00302 "*aaaa*aaaaaaaa*",
00303 "*aaaa******aaa*",
00304 "*aaaaaaaaaaaaa*",
00305 "*aaaaaaaaaaaaa*",
00306 "***************"};
00307
00308
00309
00310 static const char* const newfolder_xpm[] = {
00311 "15 14 4 1",
00312 " c None",
00313 ". c #000000",
00314 "+ c #FFFF00",
00315 "@ c #FFFFFF",
00316 " . ",
00317 " ",
00318 " . ",
00319 " . . ",
00320 " .... . . . ",
00321 " .+@+@. . . ",
00322 ".......... . .",
00323 ".@+@+@+@+@.. ",
00324 ".+@+@+@+@+. . ",
00325 ".@+@+@+@+@. . ",
00326 ".+@+@+@+@+. ",
00327 ".@+@+@+@+@. ",
00328 ".+@+@+@+@+. ",
00329 "........... "};
00330
00331
00332 static const char* const detailedview_xpm[]={
00333 "14 11 3 1",
00334 ". c None",
00335 "* c #000000",
00336 "a c #000099",
00337 ".****.***.***.",
00338 "..............",
00339 "aaaaaaaaaaaaaa",
00340 "..............",
00341 ".****.***.***.",
00342 "..............",
00343 ".****.***.***.",
00344 "..............",
00345 ".****.***.***.",
00346 "..............",
00347 ".****.***.***."};
00348
00349
00350 static const char* const previewinfoview_xpm[]={
00351 "13 13 4 1",
00352 ". c #00007f",
00353 "a c black",
00354 "# c #cec6bd",
00355 "b c #000000",
00356 "..#####aaaaaa",
00357 ".#.#bb#a#####",
00358 "...####a#bbb#",
00359 "#######a#####",
00360 "#######a#bb##",
00361 "..#####a#####",
00362 ".#.#bb#a#bbb#",
00363 "...####a#####",
00364 "#######a#bb##",
00365 "#######a#####",
00366 "..#####a#bbb#",
00367 ".#.#bb#a#####",
00368 "...####aaaaaa"};
00369
00370
00371 static const char* const previewcontentsview_xpm[]={
00372 "14 13 5 1",
00373 ". c #00007f",
00374 "a c black",
00375 "c c #7f007f",
00376 "# c #cec6bd",
00377 "b c #000000",
00378 "..#####aaaaaaa",
00379 ".#.#bb#a#####a",
00380 "...####a#ccc#a",
00381 "#######a#ccc#a",
00382 "#######a#####a",
00383 "..#####a#bbb#a",
00384 ".#.#bb#a#####a",
00385 "...####a#bbb#a",
00386 "#######a#####a",
00387 "#######a#bbb#a",
00388 "..#####a#####a",
00389 ".#.#bb#a#####a",
00390 "...####aaaaaaa"};
00391
00392
00393 static const char* const mclistview_xpm[]={
00394 "15 11 4 1",
00395 "* c None",
00396 "b c #000000",
00397 ". c #000099",
00398 "a c #ffffff",
00399 "...*****...****",
00400 ".a.*bbb*.a.*bbb",
00401 "...*****...****",
00402 "***************",
00403 "...*****...****",
00404 ".a.*bbb*.a.*bbb",
00405 "...*****...****",
00406 "***************",
00407 "...*****...****",
00408 ".a.*bbb*.a.*bbb",
00409 "...*****...****"};
00410
00411
00412 static const char * const back_xpm [] = {
00413 "13 11 3 1",
00414 "a c #00ffff",
00415 "# c #000000",
00416 ". c None",
00417 ".....#.......",
00418 "....##.......",
00419 "...#a#.......",
00420 "..#aa########",
00421 ".#aaaaaaaaaa#",
00422 "#aaaaaaaaaaa#",
00423 ".#aaaaaaaaaa#",
00424 "..#aa########",
00425 "...#a#.......",
00426 "....##.......",
00427 ".....#......."};
00428
00429 static QPixmap * openFolderIcon = 0;
00430 static QPixmap * closedFolderIcon = 0;
00431 static QPixmap * detailViewIcon = 0;
00432 static QPixmap * multiColumnListViewIcon = 0;
00433 static QPixmap * cdToParentIcon = 0;
00434 static QPixmap * newFolderIcon = 0;
00435 static QPixmap * fifteenTransparentPixels = 0;
00436 static QPixmap * symLinkDirIcon = 0;
00437 static QPixmap * symLinkFileIcon = 0;
00438 static QPixmap * fileIcon = 0;
00439 static QPixmap * startCopyIcon = 0;
00440 static QPixmap * endCopyIcon = 0;
00441 static QPixmap * previewContentsViewIcon = 0;
00442 static QPixmap * previewInfoViewIcon = 0;
00443 static QPixmap *goBackIcon = 0;
00444 static Q3FileIconProvider * fileIconProvider = 0;
00445 static int lastWidth = 0;
00446 static int lastHeight = 0;
00447 static QString * workingDirectory = 0;
00448
00449 static bool bShowHiddenFiles = false;
00450 static int sortFilesBy = (int)QDir::Name;
00451 static bool sortAscending = true;
00452 static bool detailViewMode = false;
00453
00454 static Q3CleanupHandler<QPixmap> qfd_cleanup_pixmap;
00455 static Q3CleanupHandler<QString> qfd_cleanup_string;
00456
00457 static QString toRootIfNotExists( const QString &path )
00458 {
00459 if ( !path.isEmpty() )
00460 return path;
00461
00462 QFileInfoList drives = QDir::drives();
00463 Q_ASSERT( !drives.isEmpty() );
00464 return drives.first().filePath();
00465 }
00466
00467 static bool isDirectoryMode(int m)
00468 {
00469 return m == Q3FileDialog::Directory || m == Q3FileDialog::DirectoryOnly;
00470 }
00471
00472 static void updateLastSize(Q3FileDialog *that)
00473 {
00474 int extWidth = 0;
00475 int extHeight = 0;
00476 if (that->extension() && that->extension()->isVisible()) {
00477 if (that->orientation() == Qt::Vertical)
00478 extHeight = that->extension()->height();
00479 else
00480 extWidth = that->extension()->width();
00481 }
00482 lastWidth = that->width() - extWidth;
00483 lastHeight = that->height() - extHeight;
00484 }
00485
00486
00487
00488
00489
00490
00491 #if defined(Q_WS_WIN)
00492
00493 typedef UINT (WINAPI *PtrExtractIconEx)(LPCTSTR,int,HICON*,HICON*,UINT);
00494 static PtrExtractIconEx ptrExtractIconEx = 0;
00495
00496 static void resolveLibs()
00497 {
00498 #ifndef Q_OS_TEMP
00499 static bool triedResolve = false;
00500
00501 if (!triedResolve) {
00502 #ifndef QT_NO_THREAD
00503
00504 QMutexLocker locker(qt_global_mutexpool ?
00505 qt_global_mutexpool->get(&triedResolve) : 0);
00506
00507
00508 if (triedResolve) {
00509
00510
00511 return;
00512 }
00513 #endif
00514 triedResolve = true;
00515 if (qt_winUnicode()) {
00516 QLibrary lib("shell32");
00517 ptrExtractIconEx = (PtrExtractIconEx) lib.resolve("ExtractIconExW");
00518 }
00519 }
00520 #endif
00521 }
00522 #ifdef Q_OS_TEMP
00523 #define PtrExtractIconEx ExtractIconEx
00524 #endif
00525
00526 class QWindowsIconProvider : public Q3FileIconProvider
00527 {
00528 public:
00529 QWindowsIconProvider(QObject *parent=0, const char *name=0);
00530 ~QWindowsIconProvider();
00531
00532 const QPixmap * pixmap(const QFileInfo &fi);
00533
00534 private:
00535 QPixmap defaultFolder;
00536 QPixmap defaultFile;
00537 QPixmap defaultExe;
00538 QPixmap pix;
00539 int pixw, pixh;
00540 QMap< QString, QPixmap > cache;
00541
00542 };
00543 #endif
00544
00545 static void makeVariables() {
00546 if (!openFolderIcon) {
00547 workingDirectory = new QString(::toRootIfNotExists( QDir::currentDirPath() ));
00548 qfd_cleanup_string.add(&workingDirectory);
00549
00550 openFolderIcon = new QPixmap((const char **)open_xpm);
00551 qfd_cleanup_pixmap.add(&openFolderIcon);
00552 symLinkDirIcon = new QPixmap((const char **)link_dir_xpm);
00553 qfd_cleanup_pixmap.add(&symLinkDirIcon);
00554 symLinkFileIcon = new QPixmap((const char **)link_file_xpm);
00555 qfd_cleanup_pixmap.add(&symLinkFileIcon);
00556 fileIcon = new QPixmap((const char **)file_xpm);
00557 qfd_cleanup_pixmap.add(&fileIcon);
00558 closedFolderIcon = new QPixmap((const char **)closed_xpm);
00559 qfd_cleanup_pixmap.add(&closedFolderIcon);
00560 detailViewIcon = new QPixmap((const char **)detailedview_xpm);
00561 qfd_cleanup_pixmap.add(&detailViewIcon);
00562 multiColumnListViewIcon = new QPixmap((const char **)mclistview_xpm);
00563 qfd_cleanup_pixmap.add(&multiColumnListViewIcon);
00564 cdToParentIcon = new QPixmap((const char **)cdtoparent_xpm);
00565 qfd_cleanup_pixmap.add(&cdToParentIcon);
00566 newFolderIcon = new QPixmap((const char **)newfolder_xpm);
00567 qfd_cleanup_pixmap.add(&newFolderIcon);
00568 previewInfoViewIcon
00569 = new QPixmap((const char **)previewinfoview_xpm);
00570 qfd_cleanup_pixmap.add(&previewInfoViewIcon);
00571 previewContentsViewIcon
00572 = new QPixmap((const char **)previewcontentsview_xpm);
00573 qfd_cleanup_pixmap.add(&previewContentsViewIcon);
00574 startCopyIcon = new QPixmap((const char **)start_xpm);
00575 qfd_cleanup_pixmap.add(&startCopyIcon);
00576 endCopyIcon = new QPixmap((const char **)end_xpm);
00577 qfd_cleanup_pixmap.add(&endCopyIcon);
00578 goBackIcon = new QPixmap((const char **)back_xpm);
00579 qfd_cleanup_pixmap.add(&goBackIcon);
00580 fifteenTransparentPixels = new QPixmap(closedFolderIcon->width(), 1);
00581 qfd_cleanup_pixmap.add(&fifteenTransparentPixels);
00582 QBitmap m(fifteenTransparentPixels->width(), 1);
00583 m.fill(Qt::color0);
00584 fifteenTransparentPixels->setMask(m);
00585 bShowHiddenFiles = false;
00586 sortFilesBy = (int)QDir::Name;
00587 detailViewMode = false;
00588 #if defined(Q_WS_WIN)
00589 if (!fileIconProvider)
00590 fileIconProvider = new QWindowsIconProvider(qApp);
00591 #endif
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 class QRenameEdit : public QLineEdit
00602 {
00603 Q_OBJECT
00604
00605 public:
00606 QRenameEdit(QWidget *parent);
00607
00608 protected:
00609 void keyPressEvent(QKeyEvent *e);
00610 void focusOutEvent(QFocusEvent *e);
00611
00612 signals:
00613 void cancelRename();
00614 void doRename();
00615
00616 private slots:
00617 void slotReturnPressed();
00618
00619 private:
00620 bool doRenameAlreadyEmitted;
00621 };
00622
00623 QRenameEdit::QRenameEdit(QWidget *parent)
00624 : QLineEdit(parent, "qt_rename_edit"), doRenameAlreadyEmitted(false)
00625 {
00626 connect(this, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
00627 }
00628
00629 class QFileListBox : public Q3ListBox
00630 {
00631 friend class Q3FileDialog;
00632
00633 Q_OBJECT
00634
00635 private:
00636 QFileListBox(QWidget *parent, Q3FileDialog *d);
00637
00638 void clear();
00639 void show();
00640 void startRename(bool check = true);
00641 void viewportMousePressEvent(QMouseEvent *e);
00642 void viewportMouseReleaseEvent(QMouseEvent *e);
00643 void viewportMouseDoubleClickEvent(QMouseEvent *e);
00644 void viewportMouseMoveEvent(QMouseEvent *e);
00645 #ifndef QT_NO_DRAGANDDROP
00646 void viewportDragEnterEvent(QDragEnterEvent *e);
00647 void viewportDragMoveEvent(QDragMoveEvent *e);
00648 void viewportDragLeaveEvent(QDragLeaveEvent *e);
00649 void viewportDropEvent(QDropEvent *e);
00650 bool acceptDrop(const QPoint &pnt, QWidget *source);
00651 void setCurrentDropItem(const QPoint &pnt);
00652 #endif
00653 void keyPressEvent(QKeyEvent *e);
00654
00655 private slots:
00656 void rename();
00657 void cancelRename();
00658 void doubleClickTimeout();
00659 void changeDirDuringDrag();
00660 void dragObjDestroyed();
00661 void contentsMoved(int, int);
00662
00663 private:
00664 QRenameEdit *lined;
00665 Q3FileDialog *filedialog;
00666 bool renaming;
00667 QTimer* renameTimer;
00668 Q3ListBoxItem *renameItem, *dragItem;
00669 QPoint pressPos, oldDragPos;
00670 bool mousePressed;
00671 int urls;
00672 QString startDragDir;
00673 Q3ListBoxItem *currDropItem;
00674 QTimer *changeDirTimer;
00675 bool firstMousePressEvent;
00676 Q3UrlOperator startDragUrl;
00677
00678 };
00679
00680
00681 class Q3FileDialogQFileListView : public Q3ListView
00682 {
00683 Q_OBJECT
00684
00685 public:
00686 Q3FileDialogQFileListView(QWidget *parent, Q3FileDialog *d);
00687
00688 void clear();
00689 void startRename(bool check = true);
00690 void setSorting(int column, bool increasing = true);
00691
00692 QRenameEdit *lined;
00693 bool renaming;
00694 Q3ListViewItem *renameItem;
00695
00696 private:
00697 void viewportMousePressEvent(QMouseEvent *e);
00698 void viewportMouseDoubleClickEvent(QMouseEvent *e);
00699 void keyPressEvent(QKeyEvent *e);
00700 void viewportMouseReleaseEvent(QMouseEvent *e);
00701 void viewportMouseMoveEvent(QMouseEvent *e);
00702 #ifndef QT_NO_DRAGANDDROP
00703 void viewportDragEnterEvent(QDragEnterEvent *e);
00704 void viewportDragMoveEvent(QDragMoveEvent *e);
00705 void viewportDragLeaveEvent(QDragLeaveEvent *e);
00706 void viewportDropEvent(QDropEvent *e);
00707 bool acceptDrop(const QPoint &pnt, QWidget *source);
00708 void setCurrentDropItem(const QPoint &pnt);
00709 #endif
00710
00711 private slots:
00712 void rename();
00713 void cancelRename();
00714 void changeSortColumn2(int column);
00715 void doubleClickTimeout();
00716 void changeDirDuringDrag();
00717 void dragObjDestroyed();
00718 void contentsMoved(int, int);
00719
00720 private:
00721 Q3FileDialog *filedialog;
00722 QTimer* renameTimer;
00723 QPoint pressPos, oldDragPos;
00724 bool mousePressed;
00725 int urls;
00726 QString startDragDir;
00727 Q3ListViewItem *currDropItem, *dragItem;
00728 QTimer *changeDirTimer;
00729 bool firstMousePressEvent;
00730 bool ascending;
00731 int sortcolumn;
00732 Q3UrlOperator startDragUrl;
00733
00734 };
00735
00736
00737
00738
00739
00740
00741
00742 class QFDProgressAnimation : public QWidget
00743 {
00744 Q_OBJECT
00745
00746 public:
00747 QFDProgressAnimation(QWidget *parent);
00748 void start();
00749
00750 private slots:
00751 void next();
00752
00753 protected:
00754 void paintEvent(QPaintEvent *e);
00755
00756 private:
00757 int step;
00758 QTimer *timer;
00759
00760 };
00761
00762 QFDProgressAnimation::QFDProgressAnimation(QWidget *parent)
00763 : QWidget(parent, "qt_progressanimation")
00764 {
00765 setFixedSize(300, 50);
00766 step = -1;
00767 next();
00768 timer = new QTimer(this);
00769 connect(timer, SIGNAL(timeout()),
00770 this, SLOT(next()));
00771 }
00772
00773 void QFDProgressAnimation::start()
00774 {
00775 timer->start(150, false);
00776 }
00777
00778 void QFDProgressAnimation::next()
00779 {
00780 ++step;
00781 if (step > 10)
00782 step = 0;
00783 repaint();
00784 }
00785
00786 void QFDProgressAnimation::paintEvent(QPaintEvent *)
00787 {
00788 erase();
00789
00790 QPainter p;
00791 p.begin(this);
00792 if (step == 0) {
00793 p.drawPixmap(5, (height() - startCopyIcon->height()) / 2,
00794 *startCopyIcon);
00795 p.drawPixmap(width() - 5 - openFolderIcon->width(),
00796 (height() - openFolderIcon->height()) / 2 , *openFolderIcon);
00797 } else if (step == 10) {
00798 p.drawPixmap(5, (height() - openFolderIcon->height()) / 2,
00799 *openFolderIcon);
00800 p.drawPixmap(width() - 5 - endCopyIcon->width(),
00801 (height() - endCopyIcon->height()) / 2 , *endCopyIcon);
00802 } else {
00803 p.drawPixmap(5, (height() - openFolderIcon->height()) / 2,
00804 *openFolderIcon);
00805 p.drawPixmap(width() - 5 - openFolderIcon->width(),
00806 (height() - openFolderIcon->height()) / 2 , *openFolderIcon);
00807 int x = 10 + openFolderIcon->width();
00808 int w = width() - 2 * x;
00809 int s = w / 9;
00810 p.drawPixmap(x + s * step, (height() - fileIcon->height()) / 2 - fileIcon->height(),
00811 *fileIcon);
00812 }
00813 }
00814
00815
00816 class QFDProgressDialog : public QDialog
00817 {
00818 Q_OBJECT
00819
00820 public:
00821 QFDProgressDialog(QWidget *parent, const QString &fn, int steps);
00822
00823 void setReadProgress(int p);
00824 void setWriteProgress(int p);
00825 void setWriteLabel(const QString &s);
00826
00827 signals:
00828 void cancelled();
00829
00830 private:
00831 Q3ProgressBar *readBar;
00832 Q3ProgressBar *writeBar;
00833 QLabel *writeLabel;
00834 QFDProgressAnimation *animation;
00835
00836 };
00837
00838 QFDProgressDialog::QFDProgressDialog(QWidget *parent, const QString &fn, int steps)
00839 : QDialog(parent, "", true)
00840 {
00841 setWindowTitle(Q3FileDialog::tr("Copy or Move a File"));
00842 QVBoxLayout *layout = new QVBoxLayout(this);
00843 layout->setSpacing(5);
00844 layout->setMargin(5);
00845
00846 animation = new QFDProgressAnimation(this);
00847 layout->addWidget(animation);
00848
00849 layout->addWidget(new QLabel(Q3FileDialog::tr("Read: %1").arg(fn),
00850 this, "qt_read_lbl"));
00851 readBar = new Q3ProgressBar(steps, this, "qt_readbar");
00852 readBar->reset();
00853 readBar->setProgress(0);
00854 layout->addWidget(readBar);
00855 writeLabel = new QLabel(Q3FileDialog::tr("Write: %1").arg(QString()),
00856 this, "qt_write_lbl");
00857 layout->addWidget(writeLabel);
00858 writeBar = new Q3ProgressBar(steps, this, "qt_writebar");
00859 writeBar->reset();
00860 writeBar->setProgress(0);
00861 layout->addWidget(writeBar);
00862
00863 QPushButton *b = new QPushButton(Q3FileDialog::tr("Cancel"), this,
00864 "qt_cancel_btn");
00865 b->setFixedSize(b->sizeHint());
00866 layout->addWidget(b);
00867 connect(b, SIGNAL(clicked()),
00868 this, SIGNAL(cancelled()));
00869
00870 animation->start();
00871 }
00872
00873 void QFDProgressDialog::setReadProgress(int p)
00874 {
00875 readBar->setProgress(p);
00876 }
00877
00878 void QFDProgressDialog::setWriteProgress(int p)
00879 {
00880 writeBar->setProgress(p);
00881 }
00882
00883 void QFDProgressDialog::setWriteLabel(const QString &s)
00884 {
00885 writeLabel->setText(Q3FileDialog::tr("Write: %1").arg(s));
00886 }
00887
00888
00889
00890
00891
00892
00893
00894 class Q3FileDialogPrivate {
00895 public:
00896 ~Q3FileDialogPrivate();
00897
00898 QStringList history;
00899
00900 bool geometryDirty;
00901 Q3ComboBox * paths;
00902 QComboBox * types;
00903 QLabel * pathL;
00904 QLabel * fileL;
00905 QLabel * typeL;
00906
00907 QVBoxLayout * topLevelLayout;
00908 QHBoxLayout *buttonLayout, *leftLayout, *rightLayout;
00909 Q3PtrList<QHBoxLayout> extraWidgetsLayouts;
00910 Q3PtrList<QLabel> extraLabels;
00911 Q3PtrList<QWidget> extraWidgets;
00912 Q3PtrList<QWidget> extraButtons;
00913 Q3PtrList<QAbstractButton> toolButtons;
00914
00915 Q3WidgetStack * stack;
00916
00917 QToolButton * cdToParent, *newFolder, * detailView, * mcView,
00918 *previewInfo, *previewContents, *goBack;
00919 Q3ButtonGroup * modeButtons;
00920
00921 QString currentFileName;
00922 Q3ListViewItem *last;
00923
00924 Q3ListBoxItem *lastEFSelected;
00925
00926 struct File: public Q3ListViewItem {
00927 File(Q3FileDialogPrivate * dlgp,
00928 const QUrlInfo * fi, Q3ListViewItem * parent)
00929 : Q3ListViewItem(parent, dlgp->last), info(*fi), d(dlgp), i(0), hasMimePixmap(false)
00930 { setup(); dlgp->last = this; }
00931 File(Q3FileDialogPrivate * dlgp,
00932 const QUrlInfo * fi, Q3ListView * parent)
00933 : Q3ListViewItem(parent, dlgp->last), info(*fi), d(dlgp), i(0), hasMimePixmap(false)
00934 { setup(); dlgp->last = this; }
00935 File(Q3FileDialogPrivate * dlgp,
00936 const QUrlInfo * fi, Q3ListView * parent, Q3ListViewItem * after)
00937 : Q3ListViewItem(parent, after), info(*fi), d(dlgp), i(0), hasMimePixmap(false)
00938 { setup(); if (!nextSibling()) dlgp->last = this; }
00939 ~File();
00940
00941 QString text(int column) const;
00942 const QPixmap * pixmap(int) const;
00943
00944 QUrlInfo info;
00945 Q3FileDialogPrivate * d;
00946 Q3ListBoxItem *i;
00947 bool hasMimePixmap;
00948 };
00949
00950 class MCItem: public Q3ListBoxItem {
00951 public:
00952 MCItem(Q3ListBox *, Q3ListViewItem * item);
00953 MCItem(Q3ListBox *, Q3ListViewItem * item, Q3ListBoxItem *after);
00954 QString text() const;
00955 const QPixmap *pixmap() const;
00956 int height(const Q3ListBox *) const;
00957 int width(const Q3ListBox *) const;
00958 void paint(QPainter *);
00959 Q3ListViewItem * i;
00960 };
00961
00962 class UrlInfoList : public Q3PtrList<QUrlInfo> {
00963 public:
00964 UrlInfoList() { setAutoDelete(true); }
00965 int compareItems(Q3PtrCollection::Item n1, Q3PtrCollection::Item n2) {
00966 if (!n1 || !n2)
00967 return 0;
00968
00969 QUrlInfo *i1 = (QUrlInfo *)n1;
00970 QUrlInfo *i2 = (QUrlInfo *)n2;
00971
00972 if (i1->isDir() && !i2->isDir())
00973 return -1;
00974 if (!i1->isDir() && i2->isDir())
00975 return 1;
00976
00977 if (i1->name() == "..")
00978 return -1;
00979 if (i2->name() == "..")
00980 return 1;
00981
00982 if (sortFilesBy == QDir::Name) {
00983 #if defined(Q_OS_WIN32)
00984 QString name1 = i1->name().lower();
00985 QString name2 = i2->name().lower();
00986 return name1.localeAwareCompare( name2 );
00987 #else
00988 QString name1 = i1->name();
00989 QString name2 = i2->name();
00990 return name1.localeAwareCompare( name2 );
00991 #endif
00992 }
00993 if (QUrlInfo::equal(*i1, *i2, sortFilesBy))
00994 return 0;
00995 else if (QUrlInfo::greaterThan(*i1, *i2, sortFilesBy))
00996 return 1;
00997 else if (QUrlInfo::lessThan(*i1, *i2, sortFilesBy))
00998 return -1;
00999
01000 return 0;
01001 }
01002 QUrlInfo *operator[](int i) {
01003 return at(i);
01004 }
01005 };
01006
01007 UrlInfoList sortedList;
01008 Q3PtrList<File> pendingItems;
01009
01010 QFileListBox * moreFiles;
01011
01012 Q3FileDialog::Mode mode;
01013
01014 QString rw;
01015 QString ro;
01016 QString wo;
01017 QString inaccessible;
01018
01019 QString symLinkToFile;
01020 QString file;
01021 QString symLinkToDir;
01022 QString dir;
01023 QString symLinkToSpecial;
01024 QString special;
01025 Q3WidgetStack *preview;
01026 bool infoPreview, contentsPreview;
01027 QSplitter *splitter;
01028 Q3UrlOperator url, oldUrl;
01029 QWidget *infoPreviewWidget, *contentsPreviewWidget;
01030 Q3FilePreview *infoPreviewer, *contentsPreviewer;
01031 bool hadDotDot;
01032
01033 bool ignoreNextKeyPress;
01034
01035 bool ignoreNextRefresh;
01036 QFDProgressDialog *progressDia;
01037 bool checkForFilter;
01038 bool ignoreStop;
01039
01040 QTimer *mimeTypeTimer;
01041 const Q3NetworkOperation *currListChildren;
01042
01043
01044
01045 static QString encodeFileName(const QString& fName) {
01046
01047 QString newStr;
01048 Q3CString cName = fName.utf8();
01049 const Q3CString sChars(
01050 #ifdef Q_WS_WIN
01051 "#%"
01052 #else
01053 "<>#@\"&%$:,;?={}|^~[]\'`\\*"
01054 #endif
01055 );
01056
01057 int len = cName.length();
01058 if (!len)
01059 return QString();
01060 for (int i = 0; i < len ;++i) {
01061 uchar inCh = (uchar)cName[i];
01062 if (inCh >= 128 || sChars.contains(inCh))
01063 {
01064 newStr += QChar('%');
01065 ushort c = inCh / 16;
01066 c += c > 9 ? 'A' - 10 : '0';
01067 newStr += (char)c;
01068 c = inCh % 16;
01069 c += c > 9 ? 'A' - 10 : '0';
01070 newStr += (char)c;
01071 } else {
01072 newStr += (char)inCh;
01073 }
01074 }
01075 return newStr;
01076 }
01077
01078 static bool fileExists(const Q3UrlOperator &url, const QString& name)
01079 {
01080 Q3Url u(url, Q3FileDialogPrivate::encodeFileName(name));
01081 if (u.isLocalFile()) {
01082 QFileInfo f(u.path());
01083 return f.exists();
01084 } else {
01085 Q3NetworkProtocol *p = Q3NetworkProtocol::getNetworkProtocol(url.protocol());
01086 if (p && (p->supportedOperations()&Q3NetworkProtocol::OpListChildren)) {
01087 QUrlInfo ui(url.info(name.isEmpty() ? QString::fromLatin1(".") : name));
01088 return ui.isValid();
01089 }
01090 }
01091 return true;
01092 }
01093
01094 #ifndef Q_NO_CURSOR
01095 bool cursorOverride;
01096 #endif
01097 };
01098
01099 Q3FileDialogPrivate::~Q3FileDialogPrivate()
01100 {
01101 delete modeButtons;
01102 }
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 void QRenameEdit::keyPressEvent(QKeyEvent *e)
01113 {
01114 if (e->key() == Qt::Key_Escape)
01115 emit cancelRename();
01116 else
01117 QLineEdit::keyPressEvent(e);
01118 e->accept();
01119 }
01120
01121 void QRenameEdit::focusOutEvent(QFocusEvent *)
01122 {
01123 if (!doRenameAlreadyEmitted) {
01124 doRenameAlreadyEmitted = true;
01125 emit doRename();
01126 }
01127 }
01128
01129 void QRenameEdit::slotReturnPressed()
01130 {
01131 doRenameAlreadyEmitted = true;
01132 emit doRename();
01133 }
01134
01135
01136
01137
01138
01139
01140
01141 QFileListBox::QFileListBox(QWidget *parent, Q3FileDialog *dlg)
01142 : Q3ListBox(parent, "filelistbox"), filedialog(dlg),
01143 renaming(false), renameItem(0), mousePressed(false),
01144 firstMousePressEvent(true)
01145 {
01146 changeDirTimer = new QTimer(this);
01147 Q3VBox *box = new Q3VBox(viewport(), "qt_vbox");
01148 box->setFrameStyle(QFrame::Box | QFrame::Plain);
01149 lined = new QRenameEdit(box);
01150 lined->setFixedHeight(lined->sizeHint().height());
01151 box->hide();
01152 box->setBackgroundRole(QPalette::Base);
01153 renameTimer = new QTimer(this);
01154 connect(lined, SIGNAL(doRename()),
01155 this, SLOT (rename()));
01156 connect(lined, SIGNAL(cancelRename()),
01157 this, SLOT(cancelRename()));
01158 connect(renameTimer, SIGNAL(timeout()),
01159 this, SLOT(doubleClickTimeout()));
01160 connect(changeDirTimer, SIGNAL(timeout()),
01161 this, SLOT(changeDirDuringDrag()));
01162 connect(this, SIGNAL(contentsMoving(int,int)),
01163 this, SLOT(contentsMoved(int,int)));
01164 viewport()->setAcceptDrops(true);
01165 dragItem = 0;
01166 }
01167
01168 void QFileListBox::show()
01169 {
01170 setBackgroundRole(QPalette::Base);
01171 viewport()->setBackgroundRole(QPalette::Base);
01172 Q3ListBox::show();
01173 }
01174
01175 void QFileListBox::keyPressEvent(QKeyEvent *e)
01176 {
01177 if ((e->key() == Qt::Key_Enter ||
01178 e->key() == Qt::Key_Return) &&
01179 renaming)
01180 return;
01181
01182 QString keyPressed = ((QKeyEvent *)e)->text().toLower();
01183 QChar keyChar = keyPressed[0];
01184 if (keyChar.isLetterOrNumber()) {
01185 Q3ListBoxItem * i = 0;
01186 if (currentItem())
01187 i = item(currentItem());
01188 else
01189 i = firstItem();
01190 if (i->next())
01191 i = i->next();
01192 else
01193 i = firstItem();
01194 while (i != item(currentItem())) {
01195 QString it = text(index(i));
01196 if (it[0].toLower() == keyChar) {
01197 clearSelection();
01198 setCurrentItem(i);
01199 } else {
01200 if (i->next())
01201 i = i->next();
01202 else
01203 i = firstItem();
01204 }
01205 }
01206 }
01207 cancelRename();
01208 Q3ListBox::keyPressEvent(e);
01209 }
01210
01211 void QFileListBox::viewportMousePressEvent(QMouseEvent *e)
01212 {
01213 pressPos = e->pos();
01214 mousePressed = false;
01215
01216 bool didRename = renaming;
01217
01218 cancelRename();
01219 if (!hasFocus() && !viewport()->hasFocus())
01220 setFocus();
01221
01222 if (e->button() != Qt::LeftButton) {
01223 Q3ListBox::viewportMousePressEvent(e);
01224 firstMousePressEvent = false;
01225 return;
01226 }
01227
01228 int i = currentItem();
01229 bool wasSelected = false;
01230 if (i != -1)
01231 wasSelected = item(i)->isSelected();
01232 Q3ListBox::mousePressEvent(e);
01233
01234 Q3FileDialogPrivate::MCItem *i1 = (Q3FileDialogPrivate::MCItem*)item(currentItem());
01235 if (i1)
01236 mousePressed = (!((Q3FileDialogPrivate::File*)i1->i)->info.isDir())
01237 || (filedialog->mode() == Q3FileDialog::Directory) || (filedialog->mode() == Q3FileDialog::DirectoryOnly);
01238
01239 if (itemAt(e->pos()) != item(i)) {
01240 firstMousePressEvent = false;
01241 return;
01242 }
01243
01244 if (!firstMousePressEvent && !didRename && i == currentItem() && currentItem() != -1 &&
01245 wasSelected && QUrlInfo(filedialog->d->url.info(".")).isWritable() && item(currentItem())->text() != "..") {
01246 renameTimer->start(QApplication::doubleClickInterval(), true);
01247 renameItem = item(i);
01248 }
01249
01250 firstMousePressEvent = false;
01251 }
01252
01253 void QFileListBox::viewportMouseReleaseEvent(QMouseEvent *e)
01254 {
01255 dragItem = 0;
01256 Q3ListBox::viewportMouseReleaseEvent(e);
01257 mousePressed = false;
01258 }
01259
01260 void QFileListBox::viewportMouseDoubleClickEvent(QMouseEvent *e)
01261 {
01262 renameTimer->stop();
01263 Q3ListBox::viewportMouseDoubleClickEvent(e);
01264 }
01265
01266 void QFileListBox::viewportMouseMoveEvent(QMouseEvent *e)
01267 {
01268 if (!dragItem)
01269 dragItem = itemAt(e->pos());
01270 renameTimer->stop();
01271 #ifndef QT_NO_DRAGANDDROP
01272 if ( (pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance() && mousePressed) {
01273 Q3ListBoxItem *item = dragItem;
01274 dragItem = 0;
01275 if (item) {
01276 if (!itemRect(item).contains(e->pos()))
01277 return;
01278 Q3UriDrag* drag = new Q3UriDrag(viewport());
01279 QStringList files;
01280 if (filedialog->mode() == Q3FileDialog::ExistingFiles)
01281 files = filedialog->selectedFiles();
01282 else
01283 files = QStringList(filedialog->selectedFile());
01284 drag->setFileNames(files);
01285
01286 if (lined->parentWidget()->isVisible())
01287 cancelRename();
01288
01289 connect(drag, SIGNAL(destroyed()),
01290 this, SLOT(dragObjDestroyed()));
01291 drag->drag();
01292
01293 mousePressed = false;
01294 }
01295 } else
01296 #endif
01297 {
01298 Q3ListBox::viewportMouseMoveEvent(e);
01299 }
01300
01301 }
01302
01303 void QFileListBox::dragObjDestroyed()
01304 {
01305 #ifndef QT_NO_DRAGANDDROP
01306
01307
01308 #endif
01309 }
01310
01311 #ifndef QT_NO_DRAGANDDROP
01312 void QFileListBox::viewportDragEnterEvent(QDragEnterEvent *e)
01313 {
01314 startDragUrl = filedialog->d->url;
01315 startDragDir = filedialog->dirPath();
01316 currDropItem = 0;
01317
01318 if (!Q3UriDrag::canDecode(e)) {
01319 e->ignore();
01320 return;
01321 }
01322
01323 QStringList l;
01324 Q3UriDrag::decodeLocalFiles(e, l);
01325 urls = (int)l.count();
01326
01327 if (acceptDrop(e->pos(), e->source())) {
01328 e->accept();
01329 setCurrentDropItem(e->pos());
01330 } else {
01331 e->ignore();
01332 setCurrentDropItem(QPoint(-1, -1));
01333 }
01334
01335 oldDragPos = e->pos();
01336 }
01337
01338 void QFileListBox::viewportDragMoveEvent(QDragMoveEvent *e)
01339 {
01340 if (acceptDrop(e->pos(), e->source())) {
01341 switch (e->action()) {
01342 case QDropEvent::Copy:
01343 e->acceptAction();
01344 break;
01345 case QDropEvent::Move:
01346 e->acceptAction();
01347 break;
01348 case QDropEvent::Link:
01349 break;
01350 default:
01351 break;
01352 }
01353 if (oldDragPos != e->pos())
01354 setCurrentDropItem(e->pos());
01355 } else {
01356 changeDirTimer->stop();
01357 e->ignore();
01358 setCurrentDropItem(QPoint(-1, -1));
01359 }
01360
01361 oldDragPos = e->pos();
01362 }
01363
01364 void QFileListBox::viewportDragLeaveEvent(QDragLeaveEvent *)
01365 {
01366 changeDirTimer->stop();
01367 setCurrentDropItem(QPoint(-1, -1));
01368
01369
01370
01371 }
01372
01373 void QFileListBox::viewportDropEvent(QDropEvent *e)
01374 {
01375 changeDirTimer->stop();
01376
01377 if (!Q3UriDrag::canDecode(e)) {
01378 e->ignore();
01379 return;
01380 }
01381
01382 Q3StrList l;
01383 Q3UriDrag::decode(e, l);
01384
01385 bool move = e->action() == QDropEvent::Move;
01386
01387
01388 Q3UrlOperator dest;
01389 if (currDropItem)
01390 dest = Q3UrlOperator(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text()));
01391 else
01392 dest = filedialog->d->url;
01393 QStringList lst;
01394 for (uint i = 0; i < l.count(); ++i) {
01395 lst << l.at(i);
01396 }
01397
01398 filedialog->d->url.copy(lst, dest, move);
01399
01400
01401 e->acceptAction();
01402 currDropItem = 0;
01403 }
01404
01405 bool QFileListBox::acceptDrop(const QPoint &pnt, QWidget *source)
01406 {
01407 Q3ListBoxItem *item = itemAt(pnt);
01408 if (!item || item && !itemRect(item).contains(pnt)) {
01409 if (source == viewport() && startDragDir == filedialog->dirPath())
01410 return false;
01411 return true;
01412 }
01413
01414 QUrlInfo fi(filedialog->d->url.info(item->text().isEmpty() ? QString::fromLatin1(".") : item->text()));
01415
01416 if (fi.isDir() && itemRect(item).contains(pnt))
01417 return true;
01418 return false;
01419 }
01420
01421 void QFileListBox::setCurrentDropItem(const QPoint &pnt)
01422 {
01423 changeDirTimer->stop();
01424
01425 Q3ListBoxItem *item = 0;
01426 if (pnt != QPoint(-1, -1))
01427 item = itemAt(pnt);
01428 if (item && !QUrlInfo(filedialog->d->url.info(item->text().isEmpty() ? QString::fromLatin1(".") : item->text())).isDir())
01429 item = 0;
01430 if (item && !itemRect(item).contains(pnt))
01431 item = 0;
01432
01433 currDropItem = item;
01434 if (currDropItem)
01435 setCurrentItem(currDropItem);
01436 changeDirTimer->start(750);
01437 }
01438 #endif // QT_NO_DRAGANDDROP
01439
01440 void QFileListBox::changeDirDuringDrag()
01441 {
01442 #ifndef QT_NO_DRAGANDDROP
01443 if (!currDropItem)
01444 return;
01445 changeDirTimer->stop();
01446 Q3Url u(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text()));
01447 filedialog->setDir(u);
01448 currDropItem = 0;
01449 #endif
01450 }
01451
01452 void QFileListBox::doubleClickTimeout()
01453 {
01454 startRename();
01455 renameTimer->stop();
01456 }
01457
01458 void QFileListBox::startRename(bool check)
01459 {
01460 if (check && (!renameItem || renameItem != item(currentItem())))
01461 return;
01462
01463 int i = currentItem();
01464 setSelected(i, true);
01465 QRect r = itemRect(item(i));
01466 int bdr = item(i)->pixmap() ?
01467 item(i)->pixmap()->width() : 16;
01468 int x = r.x() + bdr;
01469 int y = r.y();
01470 int w = item(i)->width(this) - bdr;
01471 int h = qMax(lined->height() + 2, r.height());
01472 y = y + r.height() / 2 - h / 2;
01473
01474 lined->parentWidget()->setGeometry(x, y, w + 6, h);
01475 lined->setFocus();
01476 lined->setText(item(i)->text());
01477 lined->selectAll();
01478 lined->setFrame(false);
01479 lined->parentWidget()->show();
01480 viewport()->setFocusProxy(lined);
01481 renaming = true;
01482 }
01483
01484 void QFileListBox::clear()
01485 {
01486 cancelRename();
01487 Q3ListBox::clear();
01488 }
01489
01490 void QFileListBox::rename()
01491 {
01492 if (!lined->text().isEmpty()) {
01493 QString file = currentText();
01494
01495 if (lined->text() != file)
01496 filedialog->d->url.rename(file, lined->text());
01497 }
01498 cancelRename();
01499 }
01500
01501 void QFileListBox::cancelRename()
01502 {
01503 renameItem = 0;
01504 lined->parentWidget()->hide();
01505 viewport()->setFocusProxy(this);
01506 renaming = false;
01507 updateItem(currentItem());
01508 if (lined->hasFocus())
01509 viewport()->setFocus();
01510 }
01511
01512 void QFileListBox::contentsMoved(int, int)
01513 {
01514 changeDirTimer->stop();
01515 #ifndef QT_NO_DRAGANDDROP
01516 setCurrentDropItem(QPoint(-1, -1));
01517 #endif
01518 }
01519
01520
01521
01522
01523
01524
01525
01526 Q3FileDialogQFileListView::Q3FileDialogQFileListView(QWidget *parent, Q3FileDialog *dlg)
01527 : Q3ListView(parent, "qt_filedlg_listview"), renaming(false), renameItem(0),
01528 filedialog(dlg), mousePressed(false),
01529 firstMousePressEvent(true)
01530 {
01531 changeDirTimer = new QTimer(this);
01532 Q3VBox *box = new Q3VBox(viewport(), "qt_vbox");
01533 box->setFrameStyle(QFrame::Box | QFrame::Plain);
01534 lined = new QRenameEdit(box);
01535 lined->setFixedHeight(lined->sizeHint().height());
01536 box->hide();
01537 box->setBackgroundRole(QPalette::Base);
01538 renameTimer = new QTimer(this);
01539 connect(lined, SIGNAL(doRename()),
01540 this, SLOT (rename()));
01541 connect(lined, SIGNAL(cancelRename()),
01542 this, SLOT(cancelRename()));
01543 header()->setMovingEnabled(false);
01544 connect(renameTimer, SIGNAL(timeout()),
01545 this, SLOT(doubleClickTimeout()));
01546 connect(changeDirTimer, SIGNAL(timeout()),
01547 this, SLOT(changeDirDuringDrag()));
01548 disconnect(header(), SIGNAL(sectionClicked(int)),
01549 this, SLOT(changeSortColumn(int)));
01550 connect(header(), SIGNAL(sectionClicked(int)),
01551 this, SLOT(changeSortColumn2(int)));
01552 connect(this, SIGNAL(contentsMoving(int,int)),
01553 this, SLOT(contentsMoved(int,int)));
01554
01555 viewport()->setAcceptDrops(true);
01556 sortcolumn = 0;
01557 ascending = true;
01558 dragItem = 0;
01559 }
01560
01561 void Q3FileDialogQFileListView::setSorting(int column, bool increasing)
01562 {
01563 if (column == -1) {
01564 Q3ListView::setSorting(column, increasing);
01565 return;
01566 }
01567
01568 sortAscending = ascending = increasing;
01569 sortcolumn = column;
01570 switch (column) {
01571 case 0:
01572 sortFilesBy = QDir::Name;
01573 break;
01574 case 1:
01575 sortFilesBy = QDir::Size;
01576 break;
01577 case 3:
01578 sortFilesBy = QDir::Time;
01579 break;
01580 default:
01581 sortFilesBy = QDir::Name;
01582 break;
01583 }
01584
01585 filedialog->resortDir();
01586 }
01587
01588 void Q3FileDialogQFileListView::changeSortColumn2(int column)
01589 {
01590 int lcol = header()->mapToLogical(column);
01591 setSorting(lcol, sortcolumn == lcol ? !ascending : true);
01592 }
01593
01594 void Q3FileDialogQFileListView::keyPressEvent(QKeyEvent *e)
01595 {
01596 if ((e->key() == Qt::Key_Enter ||
01597 e->key() == Qt::Key_Return) &&
01598 renaming)
01599 return;
01600
01601 QString keyPressed = e->text().toLower();
01602 QChar keyChar = keyPressed[0];
01603 if (keyChar.isLetterOrNumber()) {
01604 Q3ListViewItem * i = 0;
01605 if (currentItem())
01606 i = currentItem();
01607 else
01608 i = firstChild();
01609 if (i->nextSibling())
01610 i = i->nextSibling();
01611 else
01612 i = firstChild();
01613 while (i != currentItem()) {
01614 QString it = i->text(0);
01615 if (it[0].toLower() == keyChar) {
01616 clearSelection();
01617 ensureItemVisible(i);
01618 setCurrentItem(i);
01619 } else {
01620 if (i->nextSibling())
01621 i = i->nextSibling();
01622 else
01623 i = firstChild();
01624 }
01625 }
01626 return;
01627 }
01628
01629 cancelRename();
01630 Q3ListView::keyPressEvent(e);
01631 }
01632
01633 void Q3FileDialogQFileListView::viewportMousePressEvent(QMouseEvent *e)
01634 {
01635 pressPos = e->pos();
01636 mousePressed = false;
01637
01638 bool didRename = renaming;
01639 cancelRename();
01640 if (!hasFocus() && !viewport()->hasFocus())
01641 setFocus();
01642
01643 if (e->button() != Qt::LeftButton) {
01644 Q3ListView::viewportMousePressEvent(e);
01645 firstMousePressEvent = false;
01646 return;
01647 }
01648
01649 Q3ListViewItem *i = currentItem();
01650 Q3ListView::viewportMousePressEvent(e);
01651
01652 Q3FileDialogPrivate::File *i1 = (Q3FileDialogPrivate::File*)currentItem();
01653 if (i1)
01654 mousePressed = !i1->info.isDir() || (filedialog->mode() == Q3FileDialog::Directory) || (filedialog->mode() == Q3FileDialog::DirectoryOnly);
01655
01656
01657 if (itemAt(e->pos()) != i ||
01658 e->x() + contentsX() > columnWidth(0)) {
01659 firstMousePressEvent = false;
01660 return;
01661 }
01662
01663 if (!firstMousePressEvent && !didRename && i == currentItem() && currentItem() &&
01664 QUrlInfo(filedialog->d->url.info(".")).isWritable() && currentItem()->text(0) != "..") {
01665 renameTimer->start(QApplication::doubleClickInterval(), true);
01666 renameItem = currentItem();
01667 }
01668
01669 firstMousePressEvent = false;
01670 }
01671
01672 void Q3FileDialogQFileListView::viewportMouseDoubleClickEvent(QMouseEvent *e)
01673 {
01674 renameTimer->stop();
01675 Q3ListView::viewportMouseDoubleClickEvent(e);
01676 }
01677
01678 void Q3FileDialogQFileListView::viewportMouseReleaseEvent(QMouseEvent *e)
01679 {
01680 Q3ListView::viewportMouseReleaseEvent(e);
01681 mousePressed = false;
01682 dragItem = 0;
01683 }
01684
01685 void Q3FileDialogQFileListView::viewportMouseMoveEvent(QMouseEvent *e)
01686 {
01687 renameTimer->stop();
01688 if (!dragItem)
01689 dragItem = itemAt(e->pos());
01690 #ifndef QT_NO_DRAGANDDROP
01691 if ( (pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance() && mousePressed) {
01692 Q3ListViewItem *item = dragItem;
01693 dragItem = 0;
01694 if (item) {
01695 Q3UriDrag* drag = new Q3UriDrag(viewport());
01696 QStringList files;
01697 if (filedialog->mode() == Q3FileDialog::ExistingFiles)
01698 files = filedialog->selectedFiles();
01699 else
01700 files = QStringList(filedialog->selectedFile());
01701 drag->setFileNames(files);
01702
01703 if (lined->isVisible())
01704 cancelRename();
01705
01706 connect(drag, SIGNAL(destroyed()),
01707 this, SLOT(dragObjDestroyed()));
01708 drag->drag();
01709
01710 mousePressed = false;
01711 }
01712 }
01713 #endif
01714 }
01715
01716 void Q3FileDialogQFileListView::dragObjDestroyed()
01717 {
01718 #ifndef QT_NO_DRAGANDDROP
01719
01720
01721 #endif
01722 }
01723
01724 #ifndef QT_NO_DRAGANDDROP
01725 void Q3FileDialogQFileListView::viewportDragEnterEvent(QDragEnterEvent *e)
01726 {
01727 startDragUrl = filedialog->d->url;
01728 startDragDir = filedialog->dirPath();
01729 currDropItem = 0;
01730
01731 if (!Q3UriDrag::canDecode(e)) {
01732 e->ignore();
01733 return;
01734 }
01735
01736 QStringList l;
01737 Q3UriDrag::decodeLocalFiles(e, l);
01738 urls = (int)l.count();
01739
01740 if (acceptDrop(e->pos(), e->source())) {
01741 e->accept();
01742 setCurrentDropItem(e->pos());
01743 } else {
01744 e->ignore();
01745 setCurrentDropItem(QPoint(-1, -1));
01746 }
01747
01748 oldDragPos = e->pos();
01749 }
01750
01751 void Q3FileDialogQFileListView::viewportDragMoveEvent(QDragMoveEvent *e)
01752 {
01753 if (acceptDrop(e->pos(), e->source())) {
01754 if (oldDragPos != e->pos())
01755 setCurrentDropItem(e->pos());
01756 switch (e->action()) {
01757 case QDropEvent::Copy:
01758 e->acceptAction();
01759 break;
01760 case QDropEvent::Move:
01761 e->acceptAction();
01762 break;
01763 case QDropEvent::Link:
01764 break;
01765 default:
01766 break;
01767 }
01768 } else {
01769 changeDirTimer->stop();
01770 e->ignore();
01771 setCurrentDropItem(QPoint(-1, -1));
01772 }
01773
01774 oldDragPos = e->pos();
01775 }
01776
01777 void Q3FileDialogQFileListView::viewportDragLeaveEvent(QDragLeaveEvent *)
01778 {
01779 changeDirTimer->stop();
01780 setCurrentDropItem(QPoint(-1, -1));
01781
01782
01783
01784 }
01785
01786 void Q3FileDialogQFileListView::viewportDropEvent(QDropEvent *e)
01787 {
01788 changeDirTimer->stop();
01789
01790 if (!Q3UriDrag::canDecode(e)) {
01791 e->ignore();
01792 return;
01793 }
01794
01795 QStringList l;
01796 Q3UriDrag::decodeToUnicodeUris(e, l);
01797
01798 bool move = e->action() == QDropEvent::Move;
01799
01800
01801 Q3UrlOperator dest;
01802 if (currDropItem)
01803 dest = Q3UrlOperator(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text(0)));
01804 else
01805 dest = filedialog->d->url;
01806 filedialog->d->url.copy(l, dest, move);
01807
01808
01809 e->acceptAction();
01810 currDropItem = 0;
01811 }
01812
01813 bool Q3FileDialogQFileListView::acceptDrop(const QPoint &pnt, QWidget *source)
01814 {
01815 Q3ListViewItem *item = itemAt(pnt);
01816 if (!item || item && !itemRect(item).contains(pnt)) {
01817 if (source == viewport() && startDragDir == filedialog->dirPath())
01818 return false;
01819 return true;
01820 }
01821
01822 QUrlInfo fi(filedialog->d->url.info(item->text(0).isEmpty() ? QString::fromLatin1(".") : item->text(0)));
01823
01824 if (fi.isDir() && itemRect(item).contains(pnt))
01825 return true;
01826 return false;
01827 }
01828
01829 void Q3FileDialogQFileListView::setCurrentDropItem(const QPoint &pnt)
01830 {
01831 changeDirTimer->stop();
01832
01833 Q3ListViewItem *item = itemAt(pnt);
01834 if (pnt == QPoint(-1, -1))
01835 item = 0;
01836 if (item && !QUrlInfo(filedialog->d->url.info(item->text(0).isEmpty() ? QString::fromLatin1(".") : item->text(0))).isDir())
01837 item = 0;
01838
01839 if (item && !itemRect(item).contains(pnt))
01840 item = 0;
01841
01842 currDropItem = item;
01843
01844 if (currDropItem)
01845 setCurrentItem(currDropItem);
01846
01847 changeDirTimer->start(750);
01848 }
01849 #endif // QT_NO_DRAGANDDROP
01850
01851 void Q3FileDialogQFileListView::changeDirDuringDrag()
01852 {
01853 #ifndef QT_NO_DRAGANDDROP
01854 if (!currDropItem)
01855 return;
01856 changeDirTimer->stop();
01857 Q3Url u(filedialog->d->url, Q3FileDialogPrivate::encodeFileName(currDropItem->text(0)));
01858 filedialog->setDir(u);
01859 currDropItem = 0;
01860 #endif // QT_NO_DRAGANDDROP
01861 }
01862
01863
01864 void Q3FileDialogQFileListView::doubleClickTimeout()
01865 {
01866 startRename();
01867 renameTimer->stop();
01868 }
01869
01870 void Q3FileDialogQFileListView::startRename(bool check)
01871 {
01872 if (check && (!renameItem || renameItem != currentItem()))
01873 return;
01874
01875 Q3ListViewItem *i = currentItem();
01876 setSelected(i, true);
01877
01878 QRect r = itemRect(i);
01879 int bdr = i->pixmap(0) ?
01880 i->pixmap(0)->width() : 16;
01881 int x = r.x() + bdr;
01882 int y = r.y();
01883 int w = columnWidth(0) - bdr;
01884 int h = qMax(lined->height() + 2, r.height());
01885 y = y + r.height() / 2 - h / 2;
01886
01887 lined->parentWidget()->setGeometry(x, y, w + 6, h);
01888 lined->setFocus();
01889 lined->setText(i->text(0));
01890 lined->selectAll();
01891 lined->setFrame(false);
01892 lined->parentWidget()->show();
01893 viewport()->setFocusProxy(lined);
01894 renaming = true;
01895 }
01896
01897 void Q3FileDialogQFileListView::clear()
01898 {
01899 cancelRename();
01900 Q3ListView::clear();
01901 }
01902
01903 void Q3FileDialogQFileListView::rename()
01904 {
01905 if (!lined->text().isEmpty()) {
01906 QString file = currentItem()->text(0);
01907
01908 if (lined->text() != file)
01909 filedialog->d->url.rename(file, lined->text());
01910 }
01911 cancelRename();
01912 }
01913
01914 void Q3FileDialogQFileListView::cancelRename()
01915 {
01916 renameItem = 0;
01917 lined->parentWidget()->hide();
01918 viewport()->setFocusProxy(this);
01919 renaming = false;
01920 if (currentItem())
01921 currentItem()->repaint();
01922 if (lined->hasFocus())
01923 viewport()->setFocus();
01924 }
01925
01926 void Q3FileDialogQFileListView::contentsMoved(int, int)
01927 {
01928 changeDirTimer->stop();
01929 #ifndef QT_NO_DRAGANDDROP
01930 setCurrentDropItem(QPoint(-1, -1));
01931 #endif
01932 }
01933
01934
01935 Q3FileDialogPrivate::File::~File()
01936 {
01937 if (d->pendingItems.findRef(this))
01938 d->pendingItems.removeRef(this);
01939 }
01940
01941 QString Q3FileDialogPrivate::File::text(int column) const
01942 {
01943 makeVariables();
01944
01945 switch(column) {
01946 case 0:
01947 return info.name();
01948 case 1:
01949 if (info.isFile()) {
01950 QIODevice::Offset size = info.size();
01951 return QString::number(size);
01952 } else {
01953 return QString::fromLatin1("");
01954 }
01955 case 2:
01956 if (info.isFile() && info.isSymLink()) {
01957 return d->symLinkToFile;
01958 } else if (info.isFile()) {
01959 return d->file;
01960 } else if (info.isDir() && info.isSymLink()) {
01961 return d->symLinkToDir;
01962 } else if (info.isDir()) {
01963 return d->dir;
01964 } else if (info.isSymLink()) {
01965 return d->symLinkToSpecial;
01966 } else {
01967 return d->special;
01968 }
01969 case 3: {
01970 return info.lastModified().toString(Qt::LocalDate);
01971 }
01972 case 4:
01973 if (info.isReadable())
01974 return info.isWritable() ? d->rw : d->ro;
01975 else
01976 return info.isWritable() ? d->wo : d->inaccessible;
01977 }
01978
01979 return QString::fromLatin1("<--->");
01980 }
01981
01982 const QPixmap * Q3FileDialogPrivate::File::pixmap(int column) const
01983 {
01984 if (column) {
01985 return 0;
01986 } else if (Q3ListViewItem::pixmap(column)) {
01987 return Q3ListViewItem::pixmap(column);
01988 } else if (info.isSymLink()) {
01989 if (info.isFile())
01990 return symLinkFileIcon;
01991 else
01992 return symLinkDirIcon;
01993 } else if (info.isDir()) {
01994 return closedFolderIcon;
01995 } else if (info.isFile()) {
01996 return fileIcon;
01997 } else {
01998 return fifteenTransparentPixels;
01999 }
02000 }
02001
02002 Q3FileDialogPrivate::MCItem::MCItem(Q3ListBox * lb, Q3ListViewItem * item)
02003 : Q3ListBoxItem()
02004 {
02005 i = item;
02006 if (lb)
02007 lb->insertItem(this);
02008 }
02009
02010 Q3FileDialogPrivate::MCItem::MCItem(Q3ListBox * lb, Q3ListViewItem * item, Q3ListBoxItem *after)
02011 : Q3ListBoxItem()
02012 {
02013 i = item;
02014 if (lb)
02015 lb->insertItem(this, after);
02016 }
02017
02018 QString Q3FileDialogPrivate::MCItem::text() const
02019 {
02020 return i->text(0);
02021 }
02022
02023
02024 const QPixmap *Q3FileDialogPrivate::MCItem::pixmap() const
02025 {
02026 return i->pixmap(0);
02027 }
02028
02029
02030 int Q3FileDialogPrivate::MCItem::height(const Q3ListBox * lb) const
02031 {
02032 int hf = lb->fontMetrics().height();
02033 int hp = pixmap() ? pixmap()->height() : 0;
02034 return qMax(hf, hp) + 2;
02035 }
02036
02037
02038 int Q3FileDialogPrivate::MCItem::width(const Q3ListBox * lb) const
02039 {
02040 QFontMetrics fm = lb->fontMetrics();
02041 int w = 2;
02042 if (pixmap())
02043 w += pixmap()->width() + 4;
02044 else
02045 w += 18;
02046 w += fm.width(text());
02047 w += -fm.minLeftBearing();
02048 w += -fm.minRightBearing();
02049 w += 6;
02050 return w;
02051 }
02052
02053
02054 void Q3FileDialogPrivate::MCItem::paint(QPainter * ptr)
02055 {
02056 QFontMetrics fm = ptr->fontMetrics();
02057
02058 int h;
02059
02060 if (pixmap())
02061 h = qMax(fm.height(), pixmap()->height()) + 2;
02062 else
02063 h = fm.height() + 2;
02064
02065 const QPixmap * pm = pixmap();
02066 if (pm)
02067 ptr->drawPixmap(2, 1, *pm);
02068
02069 ptr->drawText(pm ? pm->width() + 4 : 22, h - fm.descent() - 2,
02070 text());
02071 }
02072
02073 static QStringList makeFiltersList(const QString &filter)
02074 {
02075 if (filter.isEmpty())
02076 return QStringList();
02077
02078 int i = filter.indexOf(";;", 0);
02079 QString sep(";;");
02080 if (i == -1) {
02081 if (filter.contains('\n')) {
02082 sep = "\n";
02083 i = filter.indexOf(sep);
02084 }
02085 }
02086
02087 return QStringList::split(sep, filter);
02088 }
02089
02305 extern const char qt3_file_dialog_filter_reg_exp[] = "([a-zA-Z0-9]*)\\(([a-zA-Z0-9_.*? +;#\\[\\]]*)\\)$";
02306
02313 Q3FileDialog::Q3FileDialog(QWidget *parent, const char *name, bool modal)
02314 : QDialog(parent, name, modal,
02315 (modal ?
02316 (Qt::WStyle_Customize | Qt::WStyle_DialogBorder | Qt::WStyle_Title | Qt::WStyle_SysMenu) : Qt::WindowFlags(0)))
02317 {
02318 init();
02319 d->mode = ExistingFile;
02320 d->types->insertItem(tr("All Files (*)"));
02321 d->cursorOverride = false;
02322 emit dirEntered(d->url.dirPath());
02323 rereadDir();
02324 }
02325
02326
02339 Q3FileDialog::Q3FileDialog(const QString& dirName, const QString & filter,
02340 QWidget *parent, const char *name, bool modal)
02341 : QDialog(parent, name, modal,
02342 (modal ? (Qt::WStyle_Customize | Qt::WStyle_DialogBorder | Qt::WStyle_Title | Qt::WStyle_SysMenu)
02343 : Qt::WindowFlags(0)))
02344 {
02345 init();
02346 d->mode = ExistingFile;
02347 rereadDir();
02348 Q3UrlOperator u(dirName);
02349 if (!dirName.isEmpty() && (!u.isLocalFile() || QDir(dirName).exists()))
02350 setSelection(dirName);
02351 else if (workingDirectory && !workingDirectory->isEmpty())
02352 setDir(*workingDirectory);
02353
02354 if (!filter.isEmpty()) {
02355 setFilters(filter);
02356 if (!dirName.isEmpty()) {
02357 int dotpos = dirName.indexOf(QChar('.'), 0, Qt::CaseInsensitive);
02358 if (dotpos != -1) {
02359 for (int b=0 ; b<d->types->count() ; b++) {
02360 if (d->types->text(b).contains(dirName.right(dirName.length() - dotpos))) {
02361 d->types->setCurrentItem(b);
02362 setFilter(d->types->text(b));
02363 return;
02364 }
02365 }
02366 }
02367 }
02368 } else {
02369 d->types->insertItem(tr("All Files (*)"));
02370 }
02371 }
02372
02373
02379 void Q3FileDialog::init()
02380 {
02381 setSizeGripEnabled(true);
02382 d = new Q3FileDialogPrivate();
02383 d->mode = AnyFile;
02384 d->last = 0;
02385 d->lastEFSelected = 0;
02386 d->moreFiles = 0;
02387 d->infoPreview = false;
02388 d->contentsPreview = false;
02389 d->hadDotDot = false;
02390 d->ignoreNextKeyPress = false;
02391 d->progressDia = 0;
02392 d->checkForFilter = false;
02393 d->ignoreNextRefresh = false;
02394 d->ignoreStop = false;
02395 d->mimeTypeTimer = new QTimer(this);
02396 d->cursorOverride = false;
02397 connect(d->mimeTypeTimer, SIGNAL(timeout()),
02398 this, SLOT(doMimeTypeLookup()));
02399
02400 d->url = Q3UrlOperator(::toRootIfNotExists( QDir::currentDirPath() ));
02401 d->oldUrl = d->url;
02402 d->currListChildren = 0;
02403
02404 connect(&d->url, SIGNAL(start(Q3NetworkOperation*)),
02405 this, SLOT(urlStart(Q3NetworkOperation*)));
02406 connect(&d->url, SIGNAL(finished(Q3NetworkOperation*)),
02407 this, SLOT(urlFinished(Q3NetworkOperation*)));
02408 connect(&d->url, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
02409 this, SLOT(insertEntry(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)));
02410 connect(&d->url, SIGNAL(removed(Q3NetworkOperation*)),
02411 this, SLOT(removeEntry(Q3NetworkOperation*)));
02412 connect(&d->url, SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)),
02413 this, SLOT(createdDirectory(QUrlInfo,Q3NetworkOperation*)));
02414 connect(&d->url, SIGNAL(itemChanged(Q3NetworkOperation*)),
02415 this, SLOT(itemChanged(Q3NetworkOperation*)));
02416 connect(&d->url, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)),
02417 this, SLOT(dataTransferProgress(int,int,Q3NetworkOperation*)));
02418
02419 nameEdit = new QLineEdit(this, "name/filter editor");
02420 nameEdit->setMaxLength(255);
02421 connect(nameEdit, SIGNAL(textChanged(QString)),
02422 this, SLOT(fileNameEditDone()));
02423 nameEdit->installEventFilter(this);
02424
02425 d->splitter = new QSplitter(this, "qt_splitter");
02426
02427 d->stack = new Q3WidgetStack(d->splitter, "files and more files");
02428
02429 d->splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
02430
02431 files = new Q3FileDialogQFileListView(d->stack, this);
02432 QFontMetrics fm = fontMetrics();
02433 files->addColumn(tr("Name"));
02434 files->addColumn(tr("Size"));
02435 files->setColumnAlignment(1, Qt::AlignRight);
02436 files->addColumn(tr("Type"));
02437 files->addColumn(tr("Date"));
02438 files->addColumn(tr("Attributes"));
02439 files->header()->setStretchEnabled(true, 0);
02440
02441 files->setMinimumSize(50, 25 + 2*fm.lineSpacing());
02442
02443 connect(files, SIGNAL(selectionChanged()),
02444 this, SLOT(detailViewSelectionChanged()));
02445 connect(files, SIGNAL(currentChanged(Q3ListViewItem*)),
02446 this, SLOT(updateFileNameEdit(Q3ListViewItem*)));
02447 connect(files, SIGNAL(doubleClicked(Q3ListViewItem*)),
02448 this, SLOT(selectDirectoryOrFile(Q3ListViewItem*)));
02449 connect(files, SIGNAL(returnPressed(Q3ListViewItem*)),
02450 this, SLOT(selectDirectoryOrFile(Q3ListViewItem*)));
02451 connect(files, SIGNAL(contextMenuRequested(Q3ListViewItem*,QPoint,int)),
02452 this, SLOT(popupContextMenu(Q3ListViewItem*,QPoint,int)));
02453
02454 files->installEventFilter(this);
02455 files->viewport()->installEventFilter(this);
02456
02457 d->moreFiles = new QFileListBox(d->stack, this);
02458 d->moreFiles->setRowMode(Q3ListBox::FitToHeight);
02459 d->moreFiles->setVariableWidth(true);
02460
02461 connect(d->moreFiles, SIGNAL(selected(Q3ListBoxItem*)),
02462 this, SLOT(selectDirectoryOrFile(Q3ListBoxItem*)));
02463 connect(d->moreFiles, SIGNAL(selectionChanged()),
02464 this, SLOT(listBoxSelectionChanged()));
02465 connect(d->moreFiles, SIGNAL(highlighted(Q3ListBoxItem*)),
02466 this, SLOT(updateFileNameEdit(Q3ListBoxItem*)));
02467 connect(d->moreFiles, SIGNAL(contextMenuRequested(Q3ListBoxItem*,QPoint)),
02468 this, SLOT(popupContextMenu(Q3ListBoxItem*,QPoint)));
02469
02470 d->moreFiles->installEventFilter(this);
02471 d->moreFiles->viewport()->installEventFilter(this);
02472
02473 okB = new QPushButton(tr("&OK"), this, "OK");
02474 okB->setDefault(true);
02475 okB->setEnabled(false);
02476 connect(okB, SIGNAL(clicked()), this, SLOT(okClicked()));
02477 cancelB = new QPushButton(tr("Cancel") , this, "Cancel");
02478 connect(cancelB, SIGNAL(clicked()), this, SLOT(cancelClicked()));
02479
02480 d->paths = new Q3ComboBox(true, this, "directory history/editor");
02481 d->paths->setDuplicatesEnabled(false);
02482 d->paths->setInsertionPolicy(Q3ComboBox::NoInsertion);
02483 makeVariables();
02484
02485 QFileInfoList rootDrives = QDir::drives();
02486 for (int i = 0; i < rootDrives.size(); ++i) {
02487 QFileInfo fi = rootDrives.at(i);
02488 d->paths->insertItem(*openFolderIcon, fi.absFilePath());
02489 }
02490
02491 if (QDir::homeDirPath().size()) {
02492 if (!d->paths->listBox()->findItem(QDir::homeDirPath()))
02493 d->paths->insertItem(*openFolderIcon, QDir::homeDirPath());
02494 }
02495
02496 connect(d->paths, SIGNAL(activated(QString)),
02497 this, SLOT(setDir(QString)));
02498
02499 d->paths->installEventFilter(this);
02500 QObjectList ol = d->paths->queryList("QLineEdit");
02501 if (ol.size())
02502 ol.at(0)->installEventFilter(this);
02503
02504 d->geometryDirty = true;
02505 d->types = new QComboBox(true, this, "file types");
02506 d->types->setDuplicatesEnabled(false);
02507 d->types->setEditable(false);
02508 connect(d->types, SIGNAL(activated(QString)),
02509 this, SLOT(setFilter(QString)));
02510 connect(d->types, SIGNAL(activated(QString)),
02511 this, SIGNAL(filterSelected(QString)));
02512
02513 d->pathL = new QLabel(d->paths, tr("Look &in:"), this, "qt_looin_lbl");
02514 d->fileL = new QLabel(nameEdit, tr("File &name:"), this, "qt_filename_lbl");
02515 d->typeL = new QLabel(d->types, tr("File &type:"), this, "qt_filetype_lbl");
02516
02517 d->goBack = new QToolButton(this, "go back");
02518 d->goBack->setEnabled(false);
02519 d->goBack->setFocusPolicy(Qt::TabFocus);
02520 connect(d->goBack, SIGNAL(clicked()), this, SLOT(goBack()));
02521 #ifndef QT_NO_TOOLTIP
02522 QToolTip::add(d->goBack, tr("Back"));
02523 #endif
02524 d->goBack->setIconSet(*goBackIcon);
02525
02526 d->cdToParent = new QToolButton(this, "cd to parent");
02527 d->cdToParent->setFocusPolicy(Qt::TabFocus);
02528 #ifndef QT_NO_TOOLTIP
02529 QToolTip::add(d->cdToParent, tr("One directory up"));
02530 #endif
02531 d->cdToParent->setIconSet(*cdToParentIcon);
02532 connect(d->cdToParent, SIGNAL(clicked()),
02533 this, SLOT(cdUpClicked()));
02534
02535 d->newFolder = new QToolButton(this, "new folder");
02536 d->newFolder->setFocusPolicy(Qt::TabFocus);
02537 #ifndef QT_NO_TOOLTIP
02538 QToolTip::add(d->newFolder, tr("Create New Folder"));
02539 #endif
02540 d->newFolder->setIconSet(*newFolderIcon);
02541 connect(d->newFolder, SIGNAL(clicked()),
02542 this, SLOT(newFolderClicked()));
02543
02544 d->modeButtons = new Q3ButtonGroup(0, "invisible group");
02545 connect(d->modeButtons, SIGNAL(destroyed()),
02546 this, SLOT(modeButtonsDestroyed()));
02547 d->modeButtons->setExclusive(true);
02548 connect(d->modeButtons, SIGNAL(clicked(int)),
02549 d->stack, SLOT(raiseWidget(int)));
02550 connect(d->modeButtons, SIGNAL(clicked(int)),
02551 this, SLOT(changeMode(int)));
02552
02553 d->mcView = new QToolButton(this, "mclistbox view");
02554 d->mcView->setFocusPolicy(Qt::TabFocus);
02555 #ifndef QT_NO_TOOLTIP
02556 QToolTip::add(d->mcView, tr("List View"));
02557 #endif
02558 d->mcView->setIconSet(*multiColumnListViewIcon);
02559 d->mcView->setToggleButton(true);
02560 d->stack->addWidget(d->moreFiles, d->modeButtons->insert(d->mcView));
02561 d->detailView = new QToolButton(this, "list view");
02562 d->detailView->setFocusPolicy(Qt::TabFocus);
02563 #ifndef QT_NO_TOOLTIP
02564 QToolTip::add(d->detailView, tr("Detail View"));
02565 #endif
02566 d->detailView->setIconSet(*detailViewIcon);
02567 d->detailView->setToggleButton(true);
02568 d->stack->addWidget(files, d->modeButtons->insert(d->detailView));
02569
02570 d->previewInfo = new QToolButton(this, "preview info view");
02571 d->previewInfo->setFocusPolicy(Qt::TabFocus);
02572 #ifndef QT_NO_TOOLTIP
02573 QToolTip::add(d->previewInfo, tr("Preview File Info"));
02574 #endif
02575 d->previewInfo->setIconSet(*previewInfoViewIcon);
02576 d->previewInfo->setToggleButton(true);
02577 d->modeButtons->insert(d->previewInfo);
02578
02579 d->previewContents = new QToolButton(this, "preview info view");
02580 #if defined(Q_WS_WIN) && !defined(Q_OS_TEMP)
02581 if ((qWinVersion() & Qt::WV_NT_based) > Qt::WV_NT)
02582 #else
02583 if (!qstrcmp(style()->className(), "QWindowsStyle"))
02584 #endif
02585 {
02586 d->goBack->setAutoRaise(true);
02587 d->cdToParent->setAutoRaise(true);
02588 d->newFolder->setAutoRaise(true);
02589 d->mcView->setAutoRaise(true);
02590 d->detailView->setAutoRaise(true);
02591 d->previewInfo->setAutoRaise(true);
02592 d->previewContents->setAutoRaise(true);
02593 }
02594 d->previewContents->setFocusPolicy(Qt::TabFocus);
02595 #ifndef QT_NO_TOOLTIP
02596 QToolTip::add(d->previewContents, tr("Preview File Contents"));
02597 #endif
02598 d->previewContents->setIconSet(*previewContentsViewIcon);
02599 d->previewContents->setToggleButton(true);
02600 d->modeButtons->insert(d->previewContents);
02601
02602 connect(d->detailView, SIGNAL(clicked()),
02603 d->moreFiles, SLOT(cancelRename()));
02604 connect(d->detailView, SIGNAL(clicked()),
02605 files, SLOT(cancelRename()));
02606 connect(d->mcView, SIGNAL(clicked()),
02607 d->moreFiles, SLOT(cancelRename()));
02608 connect(d->mcView, SIGNAL(clicked()),
02609 files, SLOT(cancelRename()));
02610
02611 d->stack->raiseWidget(d->moreFiles);
02612 d->mcView->setOn(true);
02613
02614 QHBoxLayout *lay = new QHBoxLayout(this);
02615 lay->setMargin(6);
02616 d->leftLayout = new QHBoxLayout(lay, 5);
02617 d->topLevelLayout = new QVBoxLayout((QWidget*)0, 5);
02618 lay->addLayout(d->topLevelLayout, 1);
02619
02620 QHBoxLayout * h;
02621
02622 d->preview = new Q3WidgetStack(d->splitter, "qt_preview");
02623
02624 d->infoPreviewWidget = new QWidget(d->preview, "qt_preview_info");
02625 d->contentsPreviewWidget = new QWidget(d->preview, "qt_preview_contents");
02626 d->infoPreviewer = d->contentsPreviewer = 0;
02627
02628 h = new QHBoxLayout(0);
02629 d->buttonLayout = h;
02630 d->topLevelLayout->addLayout(h);
02631 h->addWidget(d->pathL);
02632 h->addSpacing(8);
02633 h->addWidget(d->paths);
02634 h->addSpacing(8);
02635 if (d->goBack)
02636 h->addWidget(d->goBack);
02637 h->addWidget(d->cdToParent);
02638 h->addSpacing(2);
02639 h->addWidget(d->newFolder);
02640 h->addSpacing(4);
02641 h->addWidget(d->mcView);
02642 h->addWidget(d->detailView);
02643 h->addWidget(d->previewInfo);
02644 h->addWidget(d->previewContents);
02645
02646 d->topLevelLayout->addWidget(d->splitter);
02647
02648 h = new QHBoxLayout();
02649 d->topLevelLayout->addLayout(h);
02650 h->addWidget(d->fileL);
02651 h->addWidget(nameEdit);
02652 h->addSpacing(15);
02653 h->addWidget(okB);
02654
02655 h = new QHBoxLayout();
02656 d->topLevelLayout->addLayout(h);
02657 h->addWidget(d->typeL);
02658 h->addWidget(d->types);
02659 h->addSpacing(15);
02660 h->addWidget(cancelB);
02661
02662 d->rightLayout = new QHBoxLayout(lay, 5);
02663 d->topLevelLayout->setStretchFactor(d->mcView, 1);
02664 d->topLevelLayout->setStretchFactor(files, 1);
02665
02666 updateGeometries();
02667
02668 if (d->goBack) {
02669 setTabOrder(d->paths, d->goBack);
02670 setTabOrder(d->goBack, d->cdToParent);
02671 } else {
02672 setTabOrder(d->paths, d->cdToParent);
02673 }
02674 setTabOrder(d->cdToParent, d->newFolder);
02675 setTabOrder(d->newFolder, d->mcView);
02676 setTabOrder(d->mcView, d->detailView);
02677 setTabOrder(d->detailView, d->moreFiles);
02678 setTabOrder(d->moreFiles, files);
02679 setTabOrder(files, nameEdit);
02680 setTabOrder(nameEdit, d->types);
02681 setTabOrder(d->types, okB);
02682 setTabOrder(okB, cancelB);
02683
02684 d->rw = tr("Read-write");
02685 d->ro = tr("Read-only");
02686 d->wo = tr("Write-only");
02687 d->inaccessible = tr("Inaccessible");
02688
02689 d->symLinkToFile = tr("Symlink to File");
02690 d->symLinkToDir = tr("Symlink to Directory");
02691 d->symLinkToSpecial = tr("Symlink to Special");
02692 d->file = tr("File");
02693 d->dir = tr("Dir");
02694 d->special = tr("Special");
02695
02696 if (lastWidth == 0) {
02697 QRect screen = QApplication::desktop()->screenGeometry(pos());
02698 if (screen.width() < 1024 || screen.height() < 768) {
02699 resize(qMin(screen.width(), 420), qMin(screen.height(), 236));
02700 } else {
02701 QSize s = files->sizeHint();
02702 s = QSize(s.width() + 300, s.height() + 82);
02703
02704 if (s.width() * 3 > screen.width() * 2)
02705 s.setWidth(screen.width() * 2 / 3);
02706
02707 if (s.height() * 3 > screen.height() * 2)
02708 s.setHeight(screen.height() * 2 / 3);
02709 else if (s.height() * 3 < screen.height())
02710 s.setHeight(screen.height() / 3);
02711
02712 resize(s);
02713 }
02714 updateLastSize(this);
02715 } else {
02716 resize(lastWidth, lastHeight);
02717 }
02718
02719 if (detailViewMode) {
02720 d->stack->raiseWidget(files);
02721 d->mcView->setOn(false);
02722 d->detailView->setOn(true);
02723 }
02724
02725 d->preview->hide();
02726 nameEdit->setFocus();
02727
02728 connect(nameEdit, SIGNAL(returnPressed()),
02729 this, SLOT(fileNameEditReturnPressed()));
02730 }
02731
02736 void Q3FileDialog::fileNameEditReturnPressed()
02737 {
02738 d->oldUrl = d->url;
02739 if (!isDirectoryMode(d->mode)) {
02740 okClicked();
02741 } else {
02742 d->currentFileName.clear();
02743 if (nameEdit->text().isEmpty()) {
02744 emit fileSelected(selectedFile());
02745 accept();
02746 } else {
02747 QUrlInfo f;
02748 Q3FileDialogPrivate::File * c
02749 = (Q3FileDialogPrivate::File *)files->currentItem();
02750 if (c && files->isSelected(c))
02751 f = c->info;
02752 else
02753 f = QUrlInfo(d->url.info(nameEdit->text().isEmpty() ? QString::fromLatin1(".") : nameEdit->text()));
02754 if (f.isDir()) {
02755 setUrl(Q3UrlOperator(d->url,
02756 Q3FileDialogPrivate::encodeFileName(nameEdit->text() + "/")));
02757 d->checkForFilter = true;
02758 trySetSelection(true, d->url, true);
02759 d->checkForFilter = false;
02760 }
02761 }
02762 nameEdit->setText(QString());
02763 }
02764 }
02765
02771 void Q3FileDialog::updatePreviews(const Q3Url &u)
02772 {
02773 if (d->infoPreviewer)
02774 d->infoPreviewer->previewUrl(u);
02775 if (d->contentsPreviewer)
02776 d->contentsPreviewer->previewUrl(u);
02777 }
02778
02784 void Q3FileDialog::changeMode(int id)
02785 {
02786 if (!d->infoPreview && !d->contentsPreview)
02787 return;
02788
02789 QAbstractButton*btn = d->modeButtons->find(id);
02790 if (!btn)
02791 return;
02792
02793 if (btn == d->previewContents && !d->contentsPreview)
02794 return;
02795 if (btn == d->previewInfo && !d->infoPreview)
02796 return;
02797
02798 if (btn != d->previewContents && btn != d->previewInfo) {
02799 d->preview->hide();
02800 } else {
02801 if (files->currentItem())
02802 updatePreviews(Q3Url(d->url, files->currentItem()->text(0)));
02803 if (btn == d->previewInfo)
02804 d->preview->raiseWidget(d->infoPreviewWidget);
02805 else
02806 d->preview->raiseWidget(d->contentsPreviewWidget);
02807 d->preview->show();
02808 }
02809 }
02810
02815 Q3FileDialog::~Q3FileDialog()
02816 {
02817
02818
02819 files->blockSignals(true);
02820 d->moreFiles->blockSignals(true);
02821 files->clear();
02822 d->moreFiles->clear();
02823 d->moreFiles->blockSignals(false);
02824 files->blockSignals(false);
02825
02826 #ifndef QT_NO_CURSOR
02827 if (d->cursorOverride)
02828 QApplication::restoreOverrideCursor();
02829 #endif
02830
02831 delete d;
02832 d = 0;
02833 }
02834
02835
02847 QString Q3FileDialog::selectedFile() const
02848 {
02849 QString s = d->currentFileName;
02850
02851 QString prot = Q3Url(s).protocol();
02852 if (!prot.isEmpty()) {
02853 prot += ":";
02854 s.remove(0, prot.length());
02855 }
02856 Q3Url u(prot + Q3FileDialogPrivate::encodeFileName(s));
02857 if (u.isLocalFile()) {
02858 QString s = u.toString();
02859 if (s.left(5) == "file:")
02860 s.remove((uint)0, 5);
02861 return s;
02862 }
02863 return d->currentFileName;
02864 }
02865
02874 QString Q3FileDialog::selectedFilter() const
02875 {
02876 return d->types->currentText();
02877 }
02878
02887 void Q3FileDialog::setSelectedFilter(int n)
02888 {
02889 d->types->setCurrentItem(n);
02890 QString f = d->types->currentText();
02891 QRegExp r(QString::fromLatin1(qt3_file_dialog_filter_reg_exp));
02892 int index = r.indexIn(f);
02893 if (index >= 0)
02894 f = r.cap(2);
02895 d->url.setNameFilter(f);
02896 rereadDir();
02897 }
02898
02904 void Q3FileDialog::setSelectedFilter(const QString& mask)
02905 {
02906 int n;
02907
02908 for (n = 0; n < d->types->count(); n++) {
02909 if (d->