src/qt3support/dialogs/q3filedialog.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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