1 /////////////////////////////////////////////////////////////////////////////
3 // File : qfiledialogP.cxx
4 // Description : the patch for Qt's QFileDialog class (qfiledialog.cpp)
5 /////////////////////////////////////////////////////////////////////////////
7 /****************************************************************************
10 ** Implementation of QFileDialog class
14 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
16 ** This file is part of the dialogs module of the Qt GUI Toolkit.
18 ** This file may be distributed under the terms of the Q Public License
19 ** as defined by Trolltech AS of Norway and appearing in the file
20 ** LICENSE.QPL included in the packaging of this file.
22 ** This file may be distributed and/or modified under the terms of the
23 ** GNU General Public License version 2 as published by the Free Software
24 ** Foundation and appearing in the file LICENSE.GPL included in the
25 ** packaging of this file.
27 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
28 ** licenses may use this file in accordance with the Qt Commercial License
29 ** Agreement provided with the Software.
31 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
32 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
35 ** information about Qt Commercial License Agreements.
36 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
37 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
39 ** Contact info@trolltech.com if any conditions of this licensing are
42 **********************************************************************/
44 #include "qplatformdefs.h"
46 // Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.
51 #include "qfiledialogP.h"
53 #ifndef QT_NO_FILEDIALOG
55 #include "qlineedit.h"
56 #include "qcombobox.h"
57 #include "qlistview.h"
60 #include "qpushbutton.h"
61 #include "qtoolbutton.h"
62 #include "qmessagebox.h"
63 #include "qapplication.h"
64 #include "private/qapplication_p.h"
67 #include "qpopupmenu.h"
68 #include "qwidgetstack.h"
69 #include "qbuttongroup.h"
70 #include "qptrvector.h"
78 #include "qdragobject.h"
80 #include "qprogressbar.h"
83 #include "qobjectlist.h"
84 #include "qcheckbox.h"
85 #include "qsplitter.h"
87 #include "qnetworkprotocol.h"
88 #include "qsemimodal.h"
90 #include "qcleanuphandler.h"
106 #include "qt_windows.h"
110 static const char * const start_xpm[]={
137 static const char * const end_xpm[]={
165 static const char* const open_xpm[]={
191 static const char * const link_dir_xpm[]={
221 static const char * const link_file_xpm[]={
251 static const char* const file_xpm[]={
276 static const char * const closed_xpm[]={
303 static const char* const cdtoparent_xpm[]={
324 static const char* const newfolder_xpm[] = {
346 static const char* const detailedview_xpm[]={
364 static const char* const previewinfoview_xpm[]={
385 static const char* const previewcontentsview_xpm[]={
407 static const char* const mclistview_xpm[]={
426 static const char * const back_xpm [] = {
443 static QPixmap * openFolderIcon = 0;
444 static QPixmap * closedFolderIcon = 0;
445 static QPixmap * detailViewIcon = 0;
446 static QPixmap * multiColumnListViewIcon = 0;
447 static QPixmap * cdToParentIcon = 0;
448 static QPixmap * newFolderIcon = 0;
449 static QPixmap * fifteenTransparentPixels = 0;
450 static QPixmap * symLinkDirIcon = 0;
451 static QPixmap * symLinkFileIcon = 0;
452 static QPixmap * fileIcon = 0;
453 static QPixmap * startCopyIcon = 0;
454 static QPixmap * endCopyIcon = 0;
455 static QPixmap * previewContentsViewIcon = 0;
456 static QPixmap * previewInfoViewIcon = 0;
457 static QPixmap *goBackIcon = 0;
458 static QFileIconProviderP * fileIconProvider = 0;
459 static QSize *lastSize = 0;
460 static QString * workingDirectory = 0;
462 static bool bShowHiddenFiles = FALSE;
463 static int sortFilesBy = (int)QDir::Name;
464 static bool sortAscending = TRUE;
465 static bool detailViewMode = FALSE;
467 static QCleanupHandler<QPixmap> qfd_cleanup_pixmap;
468 static QCleanupHandler<QSize> qfd_cleanup_size;
469 static QCleanupHandler<QString> qfd_cleanup_string;
471 static bool isDirectoryMode( int m )
473 return m == QFileDialogP::Directory || m == QFileDialogP::DirectoryOnly;
476 #if defined(Q_WS_WIN)
478 class QWindowsIconProvider : public QFileIconProviderP
481 QWindowsIconProvider( QObject *parent=0, const char *name=0 );
482 ~QWindowsIconProvider();
484 const QPixmap * pixmap( const QFileInfo &fi );
487 QPixmap defaultFolder;
492 QMap< QString, QPixmap > cache;
496 static void makeVariables() {
497 if ( !openFolderIcon ) {
498 workingDirectory = new QString( QDir::currentDirPath() );
499 qfd_cleanup_string.add( &workingDirectory );
501 openFolderIcon = new QPixmap( (const char **)open_xpm);
502 qfd_cleanup_pixmap.add( &openFolderIcon );
503 symLinkDirIcon = new QPixmap( (const char **)link_dir_xpm);
504 qfd_cleanup_pixmap.add( &symLinkDirIcon );
505 symLinkFileIcon = new QPixmap( (const char **)link_file_xpm);
506 qfd_cleanup_pixmap.add( &symLinkFileIcon );
507 fileIcon = new QPixmap( (const char **)file_xpm);
508 qfd_cleanup_pixmap.add( &fileIcon );
509 closedFolderIcon = new QPixmap( (const char **)closed_xpm);
510 qfd_cleanup_pixmap.add( &closedFolderIcon );
511 detailViewIcon = new QPixmap( (const char **)detailedview_xpm);
512 qfd_cleanup_pixmap.add( &detailViewIcon );
513 multiColumnListViewIcon = new QPixmap( (const char **)mclistview_xpm);
514 qfd_cleanup_pixmap.add( &multiColumnListViewIcon );
515 cdToParentIcon = new QPixmap( (const char **)cdtoparent_xpm);
516 qfd_cleanup_pixmap.add( &cdToParentIcon );
517 newFolderIcon = new QPixmap( (const char **)newfolder_xpm);
518 qfd_cleanup_pixmap.add( &newFolderIcon );
520 = new QPixmap( (const char **)previewinfoview_xpm );
521 qfd_cleanup_pixmap.add( &previewInfoViewIcon );
522 previewContentsViewIcon
523 = new QPixmap( (const char **)previewcontentsview_xpm );
524 qfd_cleanup_pixmap.add( &previewContentsViewIcon );
525 startCopyIcon = new QPixmap( (const char **)start_xpm );
526 qfd_cleanup_pixmap.add( &startCopyIcon );
527 endCopyIcon = new QPixmap( (const char **)end_xpm );
528 qfd_cleanup_pixmap.add( &endCopyIcon );
529 goBackIcon = new QPixmap( (const char **)back_xpm );
530 qfd_cleanup_pixmap.add( &goBackIcon );
531 fifteenTransparentPixels = new QPixmap( closedFolderIcon->width(), 1 );
532 qfd_cleanup_pixmap.add( &fifteenTransparentPixels );
533 QBitmap m( fifteenTransparentPixels->width(), 1 );
534 m.fill( Qt::color0 );
535 fifteenTransparentPixels->setMask( m );
536 bShowHiddenFiles = FALSE;
537 sortFilesBy = (int)QDir::Name;
538 detailViewMode = FALSE;
539 #if defined(Q_WS_WIN)
540 if ( !fileIconProvider )
541 fileIconProvider = new QWindowsIconProvider( qApp );
546 QFDProgressAnimation::QFDProgressAnimation( QWidget *parent )
547 : QWidget( parent, "qt_progressanimation" )
549 setFixedSize( 300, 50 );
552 timer = new QTimer( this );
553 connect( timer, SIGNAL( timeout() ),
554 this, SLOT( next() ) );
557 void QFDProgressAnimation::start()
559 timer->start( 150, FALSE );
562 void QFDProgressAnimation::next()
570 void QFDProgressAnimation::paintEvent( QPaintEvent * )
577 p.drawPixmap( 5, ( height() - startCopyIcon->height() ) / 2,
579 p.drawPixmap( width() - 5 - openFolderIcon->width(),
580 ( height() - openFolderIcon->height() ) / 2 , *openFolderIcon );
581 } else if ( step == 10 ) {
582 p.drawPixmap( 5, ( height() - openFolderIcon->height() ) / 2,
584 p.drawPixmap( width() - 5 - endCopyIcon->width(),
585 ( height() - endCopyIcon->height() ) / 2 , *endCopyIcon );
587 p.drawPixmap( 5, ( height() - openFolderIcon->height() ) / 2,
589 p.drawPixmap( width() - 5 - openFolderIcon->width(),
590 ( height() - openFolderIcon->height() ) / 2 , *openFolderIcon );
591 int x = 10 + openFolderIcon->width();
592 int w = width() - 2 * x;
594 p.drawPixmap( x + s * step, ( height() - fileIcon->height() ) / 2 - fileIcon->height(),
599 QFDProgressDialog::QFDProgressDialog( QWidget *parent, const QString &fn, int steps )
600 : QDialog( parent, "", TRUE )
602 #ifndef QT_NO_WIDGET_TOPEXTRA
603 setCaption( QFileDialogP::tr( "Copy or Move a File" ) );
605 QVBoxLayout *layout = new QVBoxLayout( this );
606 layout->setSpacing( 5 );
607 layout->setMargin( 5 );
609 animation = new QFDProgressAnimation( this );
610 layout->addWidget( animation );
612 layout->addWidget( new QLabel( QFileDialogP::tr( "Read: %1" ).arg( fn ),
613 this, "qt_read_lbl" ) );
614 readBar = new QProgressBar( steps, this, "qt_readbar" );
616 readBar->setProgress( 0 );
617 layout->addWidget( readBar );
618 writeLabel = new QLabel( QFileDialogP::tr( "Write: %1" ).arg( QString::null ),
619 this, "qt_write_lbl" );
620 layout->addWidget( writeLabel );
621 writeBar = new QProgressBar( steps, this, "qt_writebar" );
623 writeBar->setProgress( 0 );
624 layout->addWidget( writeBar );
626 QPushButton *b = new QPushButton( QFileDialogP::tr( "Cancel" ), this,
628 b->setFixedSize( b->sizeHint() );
629 layout->addWidget( b );
630 connect( b, SIGNAL( clicked() ),
631 this, SIGNAL( cancelled() ) );
636 void QFDProgressDialog::setReadProgress( int p )
638 readBar->setProgress( p );
641 void QFDProgressDialog::setWriteProgress( int p )
643 writeBar->setProgress( p );
646 void QFDProgressDialog::setWriteLabel( const QString &s )
648 writeLabel->setText( QFileDialogP::tr( "Write: %1" ).arg( s ) );
651 /************************************************************************
653 * Private QFileDialogP members
655 ************************************************************************/
657 class QFileDialogPrivate {
659 ~QFileDialogPrivate();
670 QVBoxLayout * topLevelLayout;
671 QHBoxLayout *buttonLayout, *leftLayout, *rightLayout;
672 QPtrList<QHBoxLayout> extraWidgetsLayouts;
673 QPtrList<QLabel> extraLabels;
674 QPtrList<QWidget> extraWidgets;
675 QPtrList<QWidget> extraButtons;
676 QPtrList<QButton> toolButtons;
678 QWidgetStack * stack;
680 QToolButton * cdToParent, *newFolder, * detailView, * mcView,
681 *previewInfo, *previewContents, *goBack;
682 QButtonGroup * modeButtons;
684 QString currentFileName;
687 struct File: public QListViewItem {
688 File( QFileDialogPrivate * dlgp,
689 const QUrlInfo * fi, QListViewItem * parent )
690 : QListViewItem( parent, dlgp->last ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE )
691 { setup(); dlgp->last = this; }
692 File( QFileDialogPrivate * dlgp,
693 const QUrlInfo * fi, QListView * parent )
694 : QListViewItem( parent, dlgp->last ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE )
695 { setup(); dlgp->last = this; }
696 File( QFileDialogPrivate * dlgp,
697 const QUrlInfo * fi, QListView * parent, QListViewItem * after )
698 : QListViewItem( parent, after ), info( *fi ), d(dlgp), i( 0 ), hasMimePixmap( FALSE )
699 { setup(); if ( !nextSibling() ) dlgp->last = this; }
702 QString text( int column ) const;
703 const QPixmap * pixmap( int ) const;
706 QFileDialogPrivate * d;
711 class MCItem: public QListBoxItem {
713 MCItem( QListBox *, QListViewItem * item );
714 MCItem( QListBox *, QListViewItem * item, QListBoxItem *after );
715 QString text() const;
716 const QPixmap *pixmap() const;
717 int height( const QListBox * ) const;
718 int width( const QListBox * ) const;
719 void paint( QPainter * );
723 class UrlInfoList : public QPtrList<QUrlInfo> {
725 UrlInfoList() { setAutoDelete( TRUE ); }
726 int compareItems( QPtrCollection::Item n1, QPtrCollection::Item n2 ) {
730 QUrlInfo *i1 = ( QUrlInfo *)n1;
731 QUrlInfo *i2 = ( QUrlInfo *)n2;
733 if ( i1->isDir() && !i2->isDir() )
735 if ( !i1->isDir() && i2->isDir() )
738 if ( i1->name() == ".." )
740 if ( i2->name() == ".." )
743 #if defined(Q_OS_WIN32)
744 if ( sortFilesBy == QDir::Name ) {
745 QString name1 = i1->name().lower();
746 QString name2 = i2->name().lower();
747 return name1.compare( name2 );
750 if ( QUrlInfo::equal( *i1, *i2, sortFilesBy ) )
752 else if ( QUrlInfo::greaterThan( *i1, *i2, sortFilesBy ) )
754 else if ( QUrlInfo::lessThan( *i1, *i2, sortFilesBy ) )
759 QUrlInfo *operator[]( int i ) {
764 UrlInfoList sortedList;
765 QPtrList<File> pendingItems;
767 QFileListBox * moreFiles;
769 QFileDialogP::Mode mode;
774 QString inaccessible;
776 QString symLinkToFile;
778 QString symLinkToDir;
780 QString symLinkToSpecial;
782 QWidgetStack *preview;
783 bool infoPreview, contentsPreview;
785 QUrlOperator url, oldUrl;
786 QWidget *infoPreviewWidget, *contentsPreviewWidget;
787 QFilePreviewP *infoPreviewer, *contentsPreviewer;
790 bool ignoreNextKeyPress;
791 // ignores the next refresh operation in case the user forced a selection
792 bool ignoreNextRefresh;
793 QFDProgressDialog *progressDia;
798 QTimer *mimeTypeTimer;
799 const QNetworkOperation *currListChildren;
801 // this is similar to QUrl::encode but does encode "*" and
802 // doesn't encode whitespaces
803 static QString encodeFileName( const QString& fName ) {
806 QCString cName = fName.utf8();
807 const QCString sChars(
811 "<>#@\"&%$:,;?={}|^~[]\'`\\*"
815 int len = cName.length();
817 return QString::null;
818 for ( int i = 0; i < len ;++i ) {
819 uchar inCh = (uchar)cName[ i ];
820 if ( inCh >= 128 || sChars.contains(inCh) )
822 newStr += QChar( '%' );
823 ushort c = inCh / 16;
824 c += c > 9 ? 'A' - 10 : '0';
827 c += c > 9 ? 'A' - 10 : '0';
838 QFileDialogPrivate::~QFileDialogPrivate()
845 /************************************************************************
847 * Internal class QRenameEdit
849 ************************************************************************/
851 void QRenameEdit::keyPressEvent( QKeyEvent *e )
853 if ( e->key() == Key_Escape )
854 emit escapePressed();
856 QLineEdit::keyPressEvent( e );
860 void QRenameEdit::focusOutEvent( QFocusEvent * )
862 emit escapePressed();
865 /************************************************************************
867 * Internal class QFileListBox
869 ************************************************************************/
871 QFileListBox::QFileListBox( QWidget *parent, QFileDialogP *dlg )
872 : QListBox( parent, "filelistbox" ), filedialog( dlg ),
873 renaming( FALSE ), renameItem( 0 ), mousePressed( FALSE ),
874 firstMousePressEvent( TRUE )
876 changeDirTimer = new QTimer( this );
877 QVBox *box = new QVBox( viewport(), "qt_vbox" );
878 box->setFrameStyle( QFrame::Box | QFrame::Plain );
879 lined = new QRenameEdit( box );
880 lined->setFixedHeight( lined->sizeHint().height() );
882 box->setBackgroundMode( PaletteBase );
883 renameTimer = new QTimer( this );
884 connect( lined, SIGNAL( returnPressed() ),
885 this, SLOT (rename() ) );
886 connect( lined, SIGNAL( escapePressed() ),
887 this, SLOT( cancelRename() ) );
888 connect( renameTimer, SIGNAL( timeout() ),
889 this, SLOT( doubleClickTimeout() ) );
890 connect( changeDirTimer, SIGNAL( timeout() ),
891 this, SLOT( changeDirDuringDrag() ) );
892 connect( this, SIGNAL( contentsMoving( int, int ) ),
893 this, SLOT( contentsMoved( int, int ) ) );
894 viewport()->setAcceptDrops( TRUE );
898 void QFileListBox::show()
900 setBackgroundMode( PaletteBase );
901 viewport()->setBackgroundMode( PaletteBase );
905 void QFileListBox::keyPressEvent( QKeyEvent *e )
907 if ( ( e->key() == Key_Enter ||
908 e->key() == Key_Return ) &&
912 QString keyPressed = ((QKeyEvent *)e)->text().lower();
913 QChar keyChar = keyPressed[0];
914 if ( keyChar.isLetterOrNumber() ) {
915 QListBoxItem * i = 0;
917 i = item( currentItem() );
924 while ( i != item( currentItem() ) ) {
925 QString it = text( index( i ) );
926 if ( it[0].lower() == keyChar ) {
938 QListBox::keyPressEvent( e );
941 void QFileListBox::viewportMousePressEvent( QMouseEvent *e )
944 mousePressed = FALSE;
946 bool didRename = renaming;
949 if ( !hasFocus() && !viewport()->hasFocus() )
952 if ( e->button() != LeftButton ) {
953 QListBox::viewportMousePressEvent( e );
954 firstMousePressEvent = FALSE;
958 int i = currentItem();
959 bool wasSelected = FALSE;
961 wasSelected = item( i )->isSelected();
962 QListBox::viewportMousePressEvent( e );
964 QFileDialogPrivate::MCItem *i1 = (QFileDialogPrivate::MCItem*)item( currentItem() );
966 mousePressed = !( (QFileDialogPrivate::File*)i1->i )->info.isDir();
968 if ( itemAt( e->pos() ) != item( i ) ) {
969 firstMousePressEvent = FALSE;
973 if ( !firstMousePressEvent && !didRename && i == currentItem() && currentItem() != -1 &&
974 wasSelected && filedialog->mode() != QFileDialogP::ExistingFiles &&
975 QUrlInfo( filedialog->d->url, "." ).isWritable() && item( currentItem() )->text() != ".." ) {
976 renameTimer->start( QApplication::doubleClickInterval(), TRUE );
977 renameItem = item( i );
980 firstMousePressEvent = FALSE;
983 void QFileListBox::viewportMouseReleaseEvent( QMouseEvent *e )
986 QListBox::viewportMouseReleaseEvent( e );
987 mousePressed = FALSE;
990 void QFileListBox::viewportMouseDoubleClickEvent( QMouseEvent *e )
993 QListBox::viewportMouseDoubleClickEvent( e );
996 void QFileListBox::viewportMouseMoveEvent( QMouseEvent *e )
999 dragItem = itemAt( e->pos() );
1000 renameTimer->stop();
1001 #ifndef QT_NO_DRAGANDDROP
1002 if ( ( pressPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() && mousePressed ) {
1003 QListBoxItem *item = dragItem;
1006 if ( !itemRect( item ).contains( e->pos() ) )
1008 QUriDrag* drag = new QUriDrag( viewport() );
1009 drag->setUnicodeUris( filedialog->selectedFiles() );
1011 if ( lined->parentWidget()->isVisible() )
1014 connect( drag, SIGNAL( destroyed() ),
1015 this, SLOT( dragObjDestroyed() ) );
1018 mousePressed = FALSE;
1023 QListBox::viewportMouseMoveEvent( e );
1028 void QFileListBox::dragObjDestroyed()
1030 #ifndef QT_NO_DRAGANDDROP
1032 //filedialog->rereadDir();
1036 #ifndef QT_NO_DRAGANDDROP
1037 void QFileListBox::viewportDragEnterEvent( QDragEnterEvent *e )
1039 startDragUrl = filedialog->d->url;
1040 startDragDir = filedialog->dirPath();
1043 if ( !QUriDrag::canDecode( e ) ) {
1049 QUriDrag::decodeLocalFiles( e, l );
1050 urls = (int)l.count();
1052 if ( acceptDrop( e->pos(), e->source() ) ) {
1054 setCurrentDropItem( e->pos() );
1057 setCurrentDropItem( QPoint( -1, -1 ) );
1060 oldDragPos = e->pos();
1063 void QFileListBox::viewportDragMoveEvent( QDragMoveEvent *e )
1065 if ( acceptDrop( e->pos(), e->source() ) ) {
1066 switch ( e->action() ) {
1067 case QDropEvent::Copy:
1070 case QDropEvent::Move:
1073 case QDropEvent::Link:
1078 if ( oldDragPos != e->pos() )
1079 setCurrentDropItem( e->pos() );
1081 changeDirTimer->stop();
1083 setCurrentDropItem( QPoint( -1, -1 ) );
1086 oldDragPos = e->pos();
1089 void QFileListBox::viewportDragLeaveEvent( QDragLeaveEvent * )
1091 changeDirTimer->stop();
1092 setCurrentDropItem( QPoint( -1, -1 ) );
1094 // if ( startDragDir != filedialog->d->url )
1095 // filedialog->setUrl( startDragUrl );
1098 void QFileListBox::viewportDropEvent( QDropEvent *e )
1100 changeDirTimer->stop();
1102 if ( !QUriDrag::canDecode( e ) ) {
1108 QUriDrag::decode( e, l );
1110 bool move = e->action() == QDropEvent::Move;
1111 // bool supportAction = move || e->action() == QDropEvent::Copy;
1115 dest = QUrlOperator( filedialog->d->url, QFileDialogPrivate::encodeFileName( currDropItem->text() ) );
1117 dest = filedialog->d->url;
1119 for ( uint i = 0; i < l.count(); ++i ) {
1123 filedialog->d->url.copy( lst, dest, move );
1125 // ##### what is supportAction for?
1130 bool QFileListBox::acceptDrop( const QPoint &pnt, QWidget *source )
1132 QListBoxItem *item = itemAt( pnt );
1133 if ( !item || item && !itemRect( item ).contains( pnt ) ) {
1134 if ( source == viewport() && startDragDir == filedialog->dirPath() )
1139 QUrlInfo fi( filedialog->d->url, item->text() );
1141 if ( fi.isDir() && itemRect( item ).contains( pnt ) )
1146 void QFileListBox::setCurrentDropItem( const QPoint &pnt )
1148 changeDirTimer->stop();
1150 QListBoxItem *item = 0;
1151 if ( pnt != QPoint( -1, -1 ) )
1152 item = itemAt( pnt );
1153 if ( item && !QUrlInfo( filedialog->d->url, item->text() ).isDir() )
1155 if ( item && !itemRect( item ).contains( pnt ) )
1158 currDropItem = item;
1160 setCurrentItem( currDropItem );
1161 changeDirTimer->start( 750 );
1163 #endif // QT_NO_DRAGANDDROP
1165 void QFileListBox::changeDirDuringDrag()
1167 #ifndef QT_NO_DRAGANDDROP
1168 if ( !currDropItem )
1170 changeDirTimer->stop();
1171 QUrl u( filedialog->d->url, QFileDialogPrivate::encodeFileName(currDropItem->text()) );
1172 filedialog->setDir( u );
1177 void QFileListBox::doubleClickTimeout()
1180 renameTimer->stop();
1183 void QFileListBox::startRename( bool check )
1185 if ( check && ( !renameItem || renameItem != item( currentItem() ) ) )
1188 int i = currentItem();
1189 setSelected( i, TRUE );
1190 QRect r = itemRect( item( i ) );
1191 int bdr = item( i )->pixmap() ?
1192 item( i )->pixmap()->width() : 16;
1193 int x = r.x() + bdr;
1195 int w = item( i )->width( this ) - bdr;
1196 int h = QMAX( lined->height() + 2, r.height() );
1197 y = y + r.height() / 2 - h / 2;
1199 lined->parentWidget()->setGeometry( x, y, w + 6, h );
1201 lined->setText( item( i )->text() );
1203 lined->setFrame( FALSE );
1204 lined->parentWidget()->show();
1205 viewport()->setFocusProxy( lined );
1209 void QFileListBox::clear()
1215 void QFileListBox::rename()
1217 if ( !lined->text().isEmpty() ) {
1218 QString file = currentText();
1220 if ( lined->text() != file )
1221 filedialog->d->url.rename( file, lined->text() );
1226 void QFileListBox::cancelRename()
1229 lined->parentWidget()->hide();
1230 viewport()->setFocusProxy( this );
1232 updateItem( currentItem() );
1233 if ( lined->hasFocus() )
1234 viewport()->setFocus();
1237 void QFileListBox::contentsMoved( int, int )
1239 changeDirTimer->stop();
1240 #ifndef QT_NO_DRAGANDDROP
1241 setCurrentDropItem( QPoint( -1, -1 ) );
1245 /************************************************************************
1247 * Internal class QFileListView
1249 ************************************************************************/
1251 QFileDialogQFileListView::QFileDialogQFileListView( QWidget *parent, QFileDialogP *dlg )
1252 : QListView( parent, "qt_filedlg_listview" ), renaming( FALSE ), renameItem( 0 ),
1253 filedialog( dlg ), mousePressed( FALSE ),
1254 firstMousePressEvent( TRUE )
1256 changeDirTimer = new QTimer( this );
1257 QVBox *box = new QVBox( viewport(), "qt_vbox" );
1258 box->setFrameStyle( QFrame::Box | QFrame::Plain );
1259 lined = new QRenameEdit( box );
1260 lined->setFixedHeight( lined->sizeHint().height() );
1262 box->setBackgroundMode( PaletteBase );
1263 renameTimer = new QTimer( this );
1264 connect( lined, SIGNAL( returnPressed() ),
1265 this, SLOT (rename() ) );
1266 connect( lined, SIGNAL( escapePressed() ),
1267 this, SLOT( cancelRename() ) );
1268 header()->setMovingEnabled( FALSE );
1269 connect( renameTimer, SIGNAL( timeout() ),
1270 this, SLOT( doubleClickTimeout() ) );
1271 connect( changeDirTimer, SIGNAL( timeout() ),
1272 this, SLOT( changeDirDuringDrag() ) );
1273 disconnect( header(), SIGNAL( sectionClicked( int ) ),
1274 this, SLOT( changeSortColumn( int ) ) );
1275 connect( header(), SIGNAL( sectionClicked( int ) ),
1276 this, SLOT( changeSortColumn2( int ) ) );
1277 connect( this, SIGNAL( contentsMoving( int, int ) ),
1278 this, SLOT( contentsMoved( int, int ) ) );
1280 viewport()->setAcceptDrops( TRUE );
1286 void QFileDialogQFileListView::setSorting( int column, bool increasing )
1288 if ( column == -1 ) {
1289 QListView::setSorting( column, increasing );
1293 sortAscending = ascending = increasing;
1294 sortcolumn = column;
1297 sortFilesBy = QDir::Name;
1300 sortFilesBy = QDir::Size;
1303 sortFilesBy = QDir::Time;
1306 sortFilesBy = QDir::Name; // #### ???
1310 filedialog->resortDir();
1313 void QFileDialogQFileListView::changeSortColumn2( int column )
1315 int lcol = header()->mapToLogical( column );
1316 setSorting( lcol, sortcolumn == lcol ? !ascending : TRUE );
1319 void QFileDialogQFileListView::keyPressEvent( QKeyEvent *e )
1321 if ( ( e->key() == Key_Enter ||
1322 e->key() == Key_Return ) &&
1326 QString keyPressed = e->text().lower();
1327 QChar keyChar = keyPressed[0];
1328 if ( keyChar.isLetterOrNumber() ) {
1329 QListViewItem * i = 0;
1330 if ( currentItem() )
1334 if ( i->nextSibling() )
1335 i = i->nextSibling();
1338 while ( i != currentItem() ) {
1339 QString it = i->text(0);
1340 if ( it[0].lower() == keyChar ) {
1342 ensureItemVisible( i );
1343 setCurrentItem( i );
1345 if ( i->nextSibling() )
1346 i = i->nextSibling();
1355 QListView::keyPressEvent( e );
1358 void QFileDialogQFileListView::viewportMousePressEvent( QMouseEvent *e )
1360 pressPos = e->pos();
1361 mousePressed = FALSE;
1363 bool didRename = renaming;
1365 if ( !hasFocus() && !viewport()->hasFocus() )
1368 if ( e->button() != LeftButton ) {
1369 QListView::viewportMousePressEvent( e );
1370 firstMousePressEvent = FALSE;
1374 QListViewItem *i = currentItem();
1375 QListView::viewportMousePressEvent( e );
1377 QFileDialogPrivate::File *i1 = (QFileDialogPrivate::File*)currentItem();
1379 mousePressed = !i1->info.isDir();
1381 if ( itemAt( e->pos() ) != i ||
1382 e->x() + contentsX() > columnWidth( 0 ) ) {
1383 firstMousePressEvent = FALSE;
1387 if ( !firstMousePressEvent && !didRename && i == currentItem() && currentItem() &&
1388 filedialog->mode() != QFileDialogP::ExistingFiles &&
1389 QUrlInfo( filedialog->d->url, "." ).isWritable() && currentItem()->text( 0 ) != ".." ) {
1390 renameTimer->start( QApplication::doubleClickInterval(), TRUE );
1391 renameItem = currentItem();
1394 firstMousePressEvent = FALSE;
1397 void QFileDialogQFileListView::viewportMouseDoubleClickEvent( QMouseEvent *e )
1399 renameTimer->stop();
1400 QListView::viewportMouseDoubleClickEvent( e );
1403 void QFileDialogQFileListView::viewportMouseReleaseEvent( QMouseEvent *e )
1405 QListView::viewportMouseReleaseEvent( e );
1406 mousePressed = FALSE;
1410 void QFileDialogQFileListView::viewportMouseMoveEvent( QMouseEvent *e )
1412 renameTimer->stop();
1414 dragItem = itemAt( e->pos() );
1415 #ifndef QT_NO_DRAGANDDROP
1416 if ( ( pressPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() && mousePressed ) {
1417 QListViewItem *item = dragItem;
1420 QUriDrag* drag = new QUriDrag( viewport() );
1421 drag->setUnicodeUris( filedialog->selectedFiles() );
1423 if ( lined->isVisible() )
1426 connect( drag, SIGNAL( destroyed() ),
1427 this, SLOT( dragObjDestroyed() ) );
1430 mousePressed = FALSE;
1436 void QFileDialogQFileListView::dragObjDestroyed()
1438 #ifndef QT_NO_DRAGANDDROP
1440 //filedialog->rereadDir();
1444 #ifndef QT_NO_DRAGANDDROP
1445 void QFileDialogQFileListView::viewportDragEnterEvent( QDragEnterEvent *e )
1447 startDragUrl = filedialog->d->url;
1448 startDragDir = filedialog->dirPath();
1451 if ( !QUriDrag::canDecode( e ) ) {
1457 QUriDrag::decodeLocalFiles( e, l );
1458 urls = (int)l.count();
1460 if ( acceptDrop( e->pos(), e->source() ) ) {
1462 setCurrentDropItem( e->pos() );
1465 setCurrentDropItem( QPoint( -1, -1 ) );
1468 oldDragPos = e->pos();
1471 void QFileDialogQFileListView::viewportDragMoveEvent( QDragMoveEvent *e )
1473 if ( acceptDrop( e->pos(), e->source() ) ) {
1474 if ( oldDragPos != e->pos() )
1475 setCurrentDropItem( e->pos() );
1476 switch ( e->action() ) {
1477 case QDropEvent::Copy:
1480 case QDropEvent::Move:
1483 case QDropEvent::Link:
1489 changeDirTimer->stop();
1491 setCurrentDropItem( QPoint( -1, -1 ) );
1494 oldDragPos = e->pos();
1497 void QFileDialogQFileListView::viewportDragLeaveEvent( QDragLeaveEvent * )
1499 changeDirTimer->stop();
1500 setCurrentDropItem( QPoint( -1, -1 ) );
1502 // if ( startDragDir != filedialog->d->url )
1503 // filedialog->setUrl( startDragUrl );
1506 void QFileDialogQFileListView::viewportDropEvent( QDropEvent *e )
1508 changeDirTimer->stop();
1510 if ( !QUriDrag::canDecode( e ) ) {
1516 QUriDrag::decodeToUnicodeUris( e, l );
1518 bool move = e->action() == QDropEvent::Move;
1519 // bool supportAction = move || e->action() == QDropEvent::Copy;
1523 dest = QUrlOperator( filedialog->d->url, QFileDialogPrivate::encodeFileName( currDropItem->text( 0 ) ) );
1525 dest = filedialog->d->url;
1526 filedialog->d->url.copy( l, dest, move );
1528 // ##### what is supportAction for?
1533 bool QFileDialogQFileListView::acceptDrop( const QPoint &pnt, QWidget *source )
1535 QListViewItem *item = itemAt( pnt );
1536 if ( !item || item && !itemRect( item ).contains( pnt ) ) {
1537 if ( source == viewport() && startDragDir == filedialog->dirPath() )
1542 QUrlInfo fi( filedialog->d->url, item->text( 0 ) );
1544 if ( fi.isDir() && itemRect( item ).contains( pnt ) )
1549 void QFileDialogQFileListView::setCurrentDropItem( const QPoint &pnt )
1551 changeDirTimer->stop();
1553 QListViewItem *item = itemAt( pnt );
1554 if ( pnt == QPoint( -1, -1 ) )
1556 if ( item && !QUrlInfo( filedialog->d->url, item->text( 0 ) ).isDir() )
1559 if ( item && !itemRect( item ).contains( pnt ) )
1562 currDropItem = item;
1565 setCurrentItem( currDropItem );
1567 changeDirTimer->start( 750 );
1569 #endif // QT_NO_DRAGANDDROP
1571 void QFileDialogQFileListView::changeDirDuringDrag()
1573 #ifndef QT_NO_DRAGANDDROP
1574 if ( !currDropItem )
1576 changeDirTimer->stop();
1577 QUrl u( filedialog->d->url, QFileDialogPrivate::encodeFileName(currDropItem->text( 0 ) ) );
1578 filedialog->setDir( u );
1580 #endif // QT_NO_DRAGANDDROP
1584 void QFileDialogQFileListView::doubleClickTimeout()
1587 renameTimer->stop();
1590 void QFileDialogQFileListView::startRename( bool check )
1592 if ( check && ( !renameItem || renameItem != currentItem() ) )
1595 QListViewItem *i = currentItem();
1596 setSelected( i, TRUE );
1598 QRect r = itemRect( i );
1599 int bdr = i->pixmap( 0 ) ?
1600 i->pixmap( 0 )->width() : 16;
1601 int x = r.x() + bdr;
1603 int w = columnWidth( 0 ) - bdr;
1604 int h = QMAX( lined->height() + 2, r.height() );
1605 y = y + r.height() / 2 - h / 2;
1607 lined->parentWidget()->setGeometry( x, y, w + 6, h );
1609 lined->setText( i->text( 0 ) );
1611 lined->setFrame( FALSE );
1612 lined->parentWidget()->show();
1613 viewport()->setFocusProxy( lined );
1617 void QFileDialogQFileListView::clear()
1623 void QFileDialogQFileListView::rename()
1625 if ( !lined->text().isEmpty() ) {
1626 QString file = currentItem()->text( 0 );
1628 if ( lined->text() != file )
1629 filedialog->d->url.rename( file, lined->text() );
1634 void QFileDialogQFileListView::cancelRename()
1637 lined->parentWidget()->hide();
1638 viewport()->setFocusProxy( this );
1640 if ( currentItem() )
1641 currentItem()->repaint();
1642 if ( lined->hasFocus() )
1643 viewport()->setFocus();
1646 void QFileDialogQFileListView::contentsMoved( int, int )
1648 changeDirTimer->stop();
1649 #ifndef QT_NO_DRAGANDDROP
1650 setCurrentDropItem( QPoint( -1, -1 ) );
1655 QFileDialogPrivate::File::~File()
1657 if ( d->pendingItems.findRef( this ) )
1658 d->pendingItems.removeRef( this );
1661 QString QFileDialogPrivate::File::text( int column ) const
1669 if ( info.isFile() )
1670 return QString::number(info.size());
1672 return QString::fromLatin1("");
1674 if ( info.isFile() && info.isSymLink() ) {
1675 return d->symLinkToFile;
1676 } else if ( info.isFile() ) {
1678 } else if ( info.isDir() && info.isSymLink() ) {
1679 return d->symLinkToDir;
1680 } else if ( info.isDir() ) {
1682 } else if ( info.isSymLink() ) {
1683 return d->symLinkToSpecial;
1688 return info.lastModified().toString( Qt::LocalDate );
1691 if ( info.isReadable() )
1692 return info.isWritable() ? d->rw : d->ro;
1694 return info.isWritable() ? d->wo : d->inaccessible;
1697 return QString::fromLatin1("<--->");
1700 const QPixmap * QFileDialogPrivate::File::pixmap( int column ) const
1704 } else if ( QListViewItem::pixmap( column ) ) {
1705 return QListViewItem::pixmap( column );
1706 } else if ( info.isSymLink() ) {
1707 if ( info.isFile() )
1708 return symLinkFileIcon;
1710 return symLinkDirIcon;
1711 } else if ( info.isDir() ) {
1712 return closedFolderIcon;
1713 } else if ( info.isFile() ) {
1716 return fifteenTransparentPixels;
1720 QFileDialogPrivate::MCItem::MCItem( QListBox * lb, QListViewItem * item )
1725 lb->insertItem( this );
1728 QFileDialogPrivate::MCItem::MCItem( QListBox * lb, QListViewItem * item, QListBoxItem *after )
1733 lb->insertItem( this, after );
1736 QString QFileDialogPrivate::MCItem::text() const
1738 return i->text( 0 );
1742 const QPixmap *QFileDialogPrivate::MCItem::pixmap() const
1744 return i->pixmap( 0 );
1748 int QFileDialogPrivate::MCItem::height( const QListBox * lb ) const
1751 return QMAX( lb->fontMetrics().height(), pixmap()->height()) + 2;
1753 return lb->fontMetrics().height() + 2;
1757 int QFileDialogPrivate::MCItem::width( const QListBox * lb ) const
1759 QFontMetrics fm = lb->fontMetrics();
1762 w += pixmap()->width() + 4;
1765 w += fm.width( text() );
1766 w += -fm.minLeftBearing();
1767 w += -fm.minRightBearing();
1773 void QFileDialogPrivate::MCItem::paint( QPainter * ptr )
1775 QFontMetrics fm = ptr->fontMetrics();
1780 h = QMAX( fm.height(), pixmap()->height()) + 2;
1782 h = fm.height() + 2;
1784 const QPixmap * pm = pixmap();
1786 ptr->drawPixmap( 2, 1, *pm );
1788 ptr->drawText( pm ? pm->width() + 4 : 22, h - fm.descent() - 2,
1792 static QStringList makeFiltersList( const QString &filter )
1794 if ( filter.isEmpty() )
1795 return QStringList();
1797 int i = filter.find( ";;", 0 );
1798 QString sep( ";;" );
1800 if ( filter.find( "\n", 0 ) != -1 ) {
1802 i = filter.find( sep, 0 );
1806 return QStringList::split( sep, filter );
1810 \class QFileDialogP qfiledialog.h
1811 \brief The QFileDialogP class provides dialogs that allow users to select files or directories.
1815 The QFileDialogP class enables a user to traverse their file system in
1816 order to select one or many files or a directory.
1818 The easiest way to create a QFileDialogP is to use the static
1819 functions. On Windows, these static functions will call the native
1820 Windows file dialog and on Mac OS X, these static function will call
1821 the native Mac OS X file dialog.
1824 QString s = QFileDialogP::getOpenFileName(
1826 "Images (*.png *.xpm *.jpg)",
1832 In the above example, a modal QFileDialogP is created using a static
1833 function. The startup directory is set to "/home". The file filter
1834 is set to "Images (*.png *.xpm *.jpg)". The parent of the file dialog
1835 is set to \e this and it is given the identification name - "open file
1836 dialog". The caption at the top of file dialog is set to "Choose a
1839 You can create your own QFileDialogP without using the static
1840 functions. By calling setMode(), you can set what can be returned by
1844 QFileDialogP* fd = new QFileDialogP( this, "file dialog", TRUE );
1845 fd->setMode( QFileDialogP::AnyFile );
1848 In the above example, the mode of the file dialog is set to \c
1849 AnyFile, meaning that the user can select any file, or even specify a
1850 file that doesn't exist. This mode is useful for creating a "File Save
1851 As" file dialog. Use \c ExistingFile if the user must select an
1852 existing file or \c Directory if only a directory may be selected.
1853 (See the \l QFileDialogP::Mode enum for the complete list of modes.)
1855 You can retrieve the dialog's mode with mode(). Use setFilter() to set
1856 the dialog's file filter, e.g.
1859 fd->setFilter( "Images (*.png *.xpm *.jpg)" );
1862 In the above example, the filter is set to "Images (*.png *.xpm
1863 *.jpg)", this means that only files with the extension \c png, \c xpm
1864 or \c jpg will be shown in the QFileDialogP. You can apply
1865 several filters by using setFilters() and add additional filters with
1866 addFilter(). Use setSelectedFilter() to select one of the filters
1867 you've given as the file dialog's default filter. Whenever the user
1868 changes the filter the filterSelected() signal is emitted.
1870 The file dialog has two view modes, QFileDialogP::List which simply
1871 lists file and directory names and QFileDialogP::Detail which
1872 displays additional information alongside each name, e.g. file size,
1873 modification date, etc. Set the mode with setViewMode().
1876 fd->setViewMode( QFileDialogP::Detail );
1879 The last important function you will need to use when creating your
1880 own file dialog is selectedFile().
1884 if ( fd->exec() == QDialog::Accepted )
1885 fileName = fd->selectedFile();
1888 In the above example, a modal file dialog is created and shown. If
1889 the user clicked OK, then the file they selected is put in \c
1892 If you are using the \c ExistingFiles mode then you will need to use
1893 selectedFiles() which will return the selected files in a QStringList.
1895 The dialog's working directory can be set with setDir(). The display
1896 of hidden files is controlled with setShowHiddenFiles(). The dialog
1897 can be forced to re-read the directory with rereadDir() and re-sort
1898 the directory with resortDir(). All the files in the current directory
1899 can be selected with selectAll().
1901 \section1 Creating and using preview widgets
1903 There are two kinds of preview widgets that can be used with
1904 QFileDialogPs: \e content preview widgets and \e information preview
1905 widgets. They are created and used in the same way except that the
1906 function names differ, e.g. setContentsPreview() and setInfoPreview().
1908 A preview widget is a widget that is placed inside a QFileDialogP so
1909 that the user can see either the contents of the file, or information
1913 class Preview : public QLabel, public QFilePreviewP
1916 Preview( QWidget *parent=0 ) : QLabel( parent ) {}
1918 void previewUrl( const QUrl &u )
1920 QString path = u.path();
1921 QPixmap pix( path );
1923 setText( "This is not a pixmap" );
1930 In the above snippet, we create a preview widget which inherits from
1931 QLabel and QFilePreviewP. File preview widgets \e must inherit from
1934 Inside the class we reimplement QFilePreviewP::previewUrl(), this is
1935 where we determine what happens when a file is selected. In the
1936 above example we only show a preview of the file if it is a valid
1937 pixmap. Here's how to make a file dialog use a preview widget:
1940 Preview* p = new Preview;
1942 QFileDialogP* fd = new QFileDialogP( this );
1943 fd->setContentsPreviewEnabled( TRUE );
1944 fd->setContentsPreview( p, p );
1945 fd->setPreviewMode( QFileDialogP::Contents );
1949 The first line creates an instance of our preview widget. We then
1950 create our file dialog and call setContentsPreviewEnabled( TRUE ),
1951 this tell the file dialog to preview the contents of the currently
1952 selected file. We then call setContentsPreview() -- note that we pass
1953 the same preview widget twice. Finally, before showing the file
1954 dialog, we call setPreviewMode() setting the mode to \e Contents which
1955 will show the contents preview of the file that the user has selected.
1957 If you create another preview widget that is used for displaying
1958 information about a file, create it in the same way as the contents
1959 preview widget and call setInfoPreviewEnabled(), and
1960 setInfoPreview(). Then the user will be able to switch between the
1963 For more information about creating a QFilePreviewP widget see
1966 <img src=qfiledlg-m.png> <img src=qfiledlg-w.png>
1971 /*! \enum QFileDialogP::Mode
1973 This enum is used to indicate what the user may select in the file
1974 dialog, i.e. what the dialog will return if the user clicks OK.
1976 \value AnyFile The name of a file, whether it exists or not.
1977 \value ExistingFile The name of a single existing file.
1978 \value Directory The name of a directory. Both files and directories
1980 \value DirectoryOnly The name of a directory. The file dialog will only display directories.
1981 \value ExistingFiles The names of zero or more existing files.
1987 \enum QFileDialogP::ViewMode
1989 This enum describes the view mode of the file dialog, i.e. what
1990 information about each file will be displayed.
1992 \value List Display file and directory names with icons.
1993 \value Detail Display file and directory names with icons plus
1994 additional information, such as file size and modification date.
2000 \enum QFileDialogP::PreviewMode
2002 This enum describes the preview mode of the file dialog.
2004 \value NoPreview No preview is shown at all.
2005 \value Contents Show a preview of the contents of the current file
2006 using the contents preview widget.
2007 \value Info Show information about the current file using the
2008 info preview widget.
2010 See setPreviewMode(), setContentsPreview() and setInfoPreview().
2014 \fn void QFileDialogP::detailViewSelectionChanged()
2019 \fn void QFileDialogP::listBoxSelectionChanged()
2023 extern const char qt_file_dialog_filter_reg_exp[] =
2024 "([a-zA-Z0-9 ]*)\\(([a-zA-Z0-9_.*? +;#\\[\\]]*)\\)$";
2027 Constructs a file dialog called \a name, with the parent, \a parent.
2028 If \a modal is TRUE then the file dialog is modal; otherwise it is
2032 QFileDialogP::QFileDialogP( QWidget *parent, const char *name, bool modal )
2033 : QDialog( parent, name, modal,
2035 (WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu) : 0) )
2038 d->mode = ExistingFile;
2039 d->types->insertItem( tr( "All Files (*)" ) );
2040 emit dirEntered( d->url.dirPath() );
2046 Constructs a file dialog called \a name with the parent, \a parent.
2047 If \a modal is TRUE then the file dialog is modal; otherwise it is
2050 If \a dirName is specified then it will be used as the dialog's
2051 working directory, i.e. it will be the directory that is shown when
2052 the dialog appears. If \a filter is specified it will be used as the
2053 dialog's file filter.
2057 QFileDialogP::QFileDialogP( const QString& dirName, const QString & filter,
2058 QWidget *parent, const char *name, bool modal )
2059 : QDialog( parent, name, modal,
2061 (WStyle_Customize | WStyle_DialogBorder | WStyle_Title | WStyle_SysMenu) : 0) )
2064 d->mode = ExistingFile;
2066 if ( !dirName.isEmpty() )
2067 setSelection( dirName );
2068 else if ( workingDirectory && !workingDirectory->isEmpty() )
2069 setDir( *workingDirectory );
2071 if ( !filter.isEmpty() ) {
2072 setFilters( filter );
2073 if ( !dirName.isEmpty() ) {
2074 int dotpos = dirName.find( QChar('.'), 0, FALSE );
2075 if ( dotpos != -1 ) {
2076 for ( int b=0 ; b<d->types->count() ; b++ ) {
2077 if ( d->types->text(b).contains( dirName.right( dirName.length() - dotpos ) ) ) {
2078 d->types->setCurrentItem( b );
2079 setFilter( d->types->text( b ) );
2086 d->types->insertItem( tr( "All Files (*)" ) );
2093 Initializes the file dialog.
2096 void QFileDialogP::init()
2098 setSizeGripEnabled( TRUE );
2099 d = new QFileDialogPrivate();
2103 d->infoPreview = FALSE;
2104 d->contentsPreview = FALSE;
2105 d->hadDotDot = FALSE;
2106 d->ignoreNextKeyPress = FALSE;
2108 d->checkForFilter = FALSE;
2109 d->ignoreReturn = FALSE;
2110 d->ignoreNextRefresh = FALSE;
2111 d->ignoreStop = FALSE;
2112 d->pendingItems.setAutoDelete( FALSE );
2113 d->mimeTypeTimer = new QTimer( this );
2114 connect( d->mimeTypeTimer, SIGNAL( timeout() ),
2115 this, SLOT( doMimeTypeLookup() ) );
2117 d->url = QUrlOperator( QDir::currentDirPath() );
2119 d->currListChildren = 0;
2121 connect( &d->url, SIGNAL( start( QNetworkOperation * ) ),
2122 this, SLOT( urlStart( QNetworkOperation * ) ) );
2123 connect( &d->url, SIGNAL( finished( QNetworkOperation * ) ),
2124 this, SLOT( urlFinished( QNetworkOperation * ) ) );
2125 connect( &d->url, SIGNAL( newChildren( const QValueList<QUrlInfo> &, QNetworkOperation * ) ),
2126 this, SLOT( insertEntry( const QValueList<QUrlInfo> &, QNetworkOperation * ) ) );
2127 connect( &d->url, SIGNAL( removed( QNetworkOperation * ) ),
2128 this, SLOT( removeEntry( QNetworkOperation * ) ) );
2129 connect( &d->url, SIGNAL( createdDirectory( const QUrlInfo &, QNetworkOperation * ) ),
2130 this, SLOT( createdDirectory( const QUrlInfo &, QNetworkOperation * ) ) );
2131 connect( &d->url, SIGNAL( itemChanged( QNetworkOperation * ) ),
2132 this, SLOT( itemChanged( QNetworkOperation * ) ) );
2133 connect( &d->url, SIGNAL( dataTransferProgress( int, int, QNetworkOperation * ) ),
2134 this, SLOT( dataTransferProgress( int, int, QNetworkOperation * ) ) );
2136 nameEdit = new QLineEdit( this, "name/filter editor" );
2137 nameEdit->setMaxLength( 255 ); //_POSIX_MAX_PATH
2138 connect( nameEdit, SIGNAL(textChanged(const QString&)),
2139 this, SLOT(fileNameEditDone()) );
2140 nameEdit->installEventFilter( this );
2142 d->splitter = new QSplitter( this, "qt_splitter" );
2144 d->stack = new QWidgetStack( d->splitter, "files and more files" );
2146 d->splitter->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
2148 files = new QFileDialogQFileListView( d->stack, this );
2149 QFontMetrics fm = fontMetrics();
2150 files->addColumn( tr("Name") );
2151 files->addColumn( tr("Size") );
2152 files->setColumnAlignment( 1, AlignRight );
2153 files->addColumn( tr("Type") );
2154 files->addColumn( tr("Date") );
2155 files->addColumn( tr("Attributes") );
2156 files->header()->setStretchEnabled( TRUE, 0 );
2158 files->setMinimumSize( 50, 25 + 2*fm.lineSpacing() );
2160 connect( files, SIGNAL( selectionChanged() ),
2161 this, SLOT( detailViewSelectionChanged() ) );
2162 connect( files, SIGNAL(currentChanged(QListViewItem *)),
2163 this, SLOT(updateFileNameEdit(QListViewItem *)) );
2164 connect( files, SIGNAL(doubleClicked(QListViewItem *)),
2165 this, SLOT(selectDirectoryOrFile(QListViewItem *)) );
2166 connect( files, SIGNAL(returnPressed(QListViewItem *)),
2167 this, SLOT(selectDirectoryOrFile(QListViewItem *)) );
2168 connect( files, SIGNAL(rightButtonPressed(QListViewItem *,
2169 const QPoint &, int)),
2170 this, SLOT(popupContextMenu(QListViewItem *,
2171 const QPoint &, int)) );
2173 files->installEventFilter( this );
2174 files->viewport()->installEventFilter( this );
2176 d->moreFiles = new QFileListBox( d->stack, this );
2177 d->moreFiles->setRowMode( QListBox::FitToHeight );
2178 d->moreFiles->setVariableWidth( TRUE );
2180 connect( d->moreFiles, SIGNAL(selected(QListBoxItem *)),
2181 this, SLOT(selectDirectoryOrFile(QListBoxItem *)) );
2182 connect( d->moreFiles, SIGNAL( selectionChanged() ),
2183 this, SLOT( listBoxSelectionChanged() ) );
2184 connect( d->moreFiles, SIGNAL(highlighted(QListBoxItem *)),
2185 this, SLOT(updateFileNameEdit(QListBoxItem *)) );
2186 connect( d->moreFiles, SIGNAL( rightButtonPressed( QListBoxItem *, const QPoint & ) ),
2187 this, SLOT( popupContextMenu( QListBoxItem *, const QPoint & ) ) );
2189 d->moreFiles->installEventFilter( this );
2190 d->moreFiles->viewport()->installEventFilter( this );
2192 okB = new QPushButton( tr("OK"), this, "OK" ); //### Or "Save (see other "OK")
2193 okB->setDefault( TRUE );
2194 okB->setEnabled( FALSE );
2195 connect( okB, SIGNAL(clicked()), this, SLOT(okClicked()) );
2196 cancelB = new QPushButton( tr("Cancel") , this, "Cancel" );
2197 connect( cancelB, SIGNAL(clicked()), this, SLOT(cancelClicked()) );
2199 d->paths = new QComboBox( TRUE, this, "directory history/editor" );
2200 d->paths->setDuplicatesEnabled( FALSE );
2201 d->paths->setInsertionPolicy( QComboBox::NoInsertion );
2202 const QFileInfoList * rootDrives = QDir::drives();
2203 QFileInfoListIterator it( *rootDrives );
2207 while ( (fi = it.current()) != 0 ) {
2209 d->paths->insertItem( *openFolderIcon, fi->absFilePath() );
2212 if ( !!QDir::homeDirPath() ) {
2213 if ( !d->paths->listBox()->findItem( QDir::homeDirPath() ) )
2214 d->paths->insertItem( *openFolderIcon, QDir::homeDirPath() );
2217 connect( d->paths, SIGNAL(activated(const QString&)),
2218 this, SLOT(setDir(const QString&)) );
2220 d->paths->installEventFilter( this );
2221 QObjectList *ol = d->paths->queryList( "QLineEdit" );
2222 if ( ol && ol->first() )
2223 ( (QLineEdit*)ol->first() )->installEventFilter( this );
2226 d->geometryDirty = TRUE;
2227 d->types = new QComboBox( TRUE, this, "file types" );
2228 d->types->setDuplicatesEnabled( FALSE );
2229 d->types->setEditable( FALSE );
2230 connect( d->types, SIGNAL(activated(const QString&)),
2231 this, SLOT(setFilter(const QString&)) );
2232 connect( d->types, SIGNAL(activated(const QString&)),
2233 this, SIGNAL(filterSelected(const QString&)) );
2235 d->pathL = new QLabel( d->paths, tr("Look &in:"), this, "qt_looin_lbl" );
2236 d->fileL = new QLabel( nameEdit, tr("File &name:"), this, "qt_filename_lbl" );
2237 d->typeL = new QLabel( d->types, tr("File &type:"), this, "qt_filetype_lbl" );
2239 #if defined(Q_WS_WIN)
2240 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP ) {
2241 d->goBack = new QToolButton( this, "go back" );
2242 d->goBack->setAutoRaise( TRUE );
2243 d->goBack->setEnabled( FALSE );
2244 d->goBack->setFocusPolicy( TabFocus );
2245 connect( d->goBack, SIGNAL( clicked() ),
2246 this, SLOT( goBack() ) );
2247 QToolTip::add( d->goBack, tr( "Back" ) );
2248 d->goBack->setIconSet( *goBackIcon );
2256 d->cdToParent = new QToolButton( this, "cd to parent" );
2257 #if defined(Q_WS_WIN)
2258 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2259 d->cdToParent->setAutoRaise( TRUE );
2261 d->cdToParent->setFocusPolicy( TabFocus );
2262 #ifndef QT_NO_TOOLTIP
2263 QToolTip::add( d->cdToParent, tr( "One directory up" ) );
2265 d->cdToParent->setIconSet( *cdToParentIcon );
2266 connect( d->cdToParent, SIGNAL(clicked()),
2267 this, SLOT(cdUpClicked()) );
2269 d->newFolder = new QToolButton( this, "new folder" );
2270 #if defined(Q_WS_WIN)
2271 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2272 d->newFolder->setAutoRaise( TRUE );
2274 d->newFolder->setFocusPolicy( TabFocus );
2275 #ifndef QT_NO_TOOLTIP
2276 QToolTip::add( d->newFolder, tr( "Create New Folder" ) );
2278 d->newFolder->setIconSet( *newFolderIcon );
2279 connect( d->newFolder, SIGNAL(clicked()),
2280 this, SLOT(newFolderClicked()) );
2282 d->modeButtons = new QButtonGroup( 0, "invisible group" );
2283 connect( d->modeButtons, SIGNAL(destroyed()),
2284 this, SLOT(modeButtonsDestroyed()) );
2285 d->modeButtons->setExclusive( TRUE );
2286 connect( d->modeButtons, SIGNAL(clicked(int)),
2287 d->stack, SLOT(raiseWidget(int)) );
2288 connect( d->modeButtons, SIGNAL(clicked(int)),
2289 this, SLOT(changeMode(int)) );
2291 d->mcView = new QToolButton( this, "mclistbox view" );
2292 #if defined(Q_WS_WIN)
2293 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2294 d->mcView->setAutoRaise( TRUE );
2296 d->mcView->setFocusPolicy( TabFocus );
2297 #ifndef QT_NO_TOOLTIP
2298 QToolTip::add( d->mcView, tr( "List View" ) );
2300 d->mcView->setIconSet( *multiColumnListViewIcon );
2301 d->mcView->setToggleButton( TRUE );
2302 d->stack->addWidget( d->moreFiles, d->modeButtons->insert( d->mcView ) );
2303 d->detailView = new QToolButton( this, "list view" );
2304 #if defined(Q_WS_WIN)
2305 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2306 d->detailView->setAutoRaise( TRUE );
2308 d->detailView->setFocusPolicy( TabFocus );
2309 #ifndef QT_NO_TOOLTIP
2310 QToolTip::add( d->detailView, tr( "Detail View" ) );
2312 d->detailView->setIconSet( *detailViewIcon );
2313 d->detailView->setToggleButton( TRUE );
2314 d->stack->addWidget( files, d->modeButtons->insert( d->detailView ) );
2316 d->previewInfo = new QToolButton( this, "preview info view" );
2317 #if defined(Q_WS_WIN)
2318 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2319 d->previewInfo->setAutoRaise( TRUE );
2321 d->previewInfo->setFocusPolicy( TabFocus );
2322 #ifndef QT_NO_TOOLTIP
2323 QToolTip::add( d->previewInfo, tr( "Preview File Info" ) );
2325 d->previewInfo->setIconSet( *previewInfoViewIcon );
2326 d->previewInfo->setToggleButton( TRUE );
2327 d->modeButtons->insert( d->previewInfo );
2329 d->previewContents = new QToolButton( this, "preview info view" );
2330 #if defined(Q_WS_WIN)
2331 if ( qt_winver == Qt::WV_2000 || qt_winver == Qt::WV_XP )
2332 d->previewContents->setAutoRaise( TRUE );
2334 d->previewContents->setFocusPolicy( TabFocus );
2335 #ifndef QT_NO_TOOLTIP
2336 QToolTip::add( d->previewContents, tr( "Preview File Contents" ) );
2338 d->previewContents->setIconSet( *previewContentsViewIcon );
2339 d->previewContents->setToggleButton( TRUE );
2340 d->modeButtons->insert( d->previewContents );
2342 connect( d->detailView, SIGNAL( clicked() ),
2343 d->moreFiles, SLOT( cancelRename() ) );
2344 connect( d->detailView, SIGNAL( clicked() ),
2345 files, SLOT( cancelRename() ) );
2346 connect( d->mcView, SIGNAL( clicked() ),
2347 d->moreFiles, SLOT( cancelRename() ) );
2348 connect( d->mcView, SIGNAL( clicked() ),
2349 files, SLOT( cancelRename() ) );
2351 d->stack->raiseWidget( d->moreFiles );
2352 d->mcView->setOn( TRUE );
2354 QHBoxLayout *lay = new QHBoxLayout( this );
2355 lay->setMargin( 6 );
2356 d->leftLayout = new QHBoxLayout( lay, 5 );
2357 d->topLevelLayout = new QVBoxLayout( (QWidget*)0, 5 );
2358 lay->addLayout( d->topLevelLayout, 1 );
2359 d->extraWidgetsLayouts.setAutoDelete( FALSE );
2360 d->extraLabels.setAutoDelete( FALSE );
2361 d->extraWidgets.setAutoDelete( FALSE );
2362 d->extraButtons.setAutoDelete( FALSE );
2363 d->toolButtons.setAutoDelete( FALSE );
2367 d->preview = new QWidgetStack( d->splitter, "qt_preview" );
2369 d->infoPreviewWidget = new QWidget( d->preview, "qt_preview_info" );
2370 d->contentsPreviewWidget = new QWidget( d->preview, "qt_preview_contents" );
2371 d->infoPreviewer = d->contentsPreviewer = 0;
2373 h = new QHBoxLayout( 0 );
2374 d->buttonLayout = h;
2375 d->topLevelLayout->addLayout( h );
2376 h->addWidget( d->pathL );
2378 h->addWidget( d->paths );
2381 h->addWidget( d->goBack );
2382 h->addWidget( d->cdToParent );
2384 h->addWidget( d->newFolder );
2386 h->addWidget( d->mcView );
2387 h->addWidget( d->detailView );
2388 h->addWidget( d->previewInfo );
2389 h->addWidget( d->previewContents );
2391 d->topLevelLayout->addWidget( d->splitter );
2393 h = new QHBoxLayout();
2394 d->topLevelLayout->addLayout( h );
2395 h->addWidget( d->fileL );
2396 h->addWidget( nameEdit );
2397 h->addSpacing( 15 );
2398 h->addWidget( okB );
2400 h = new QHBoxLayout();
2401 d->topLevelLayout->addLayout( h );
2402 h->addWidget( d->typeL );
2403 h->addWidget( d->types );
2404 h->addSpacing( 15 );
2405 h->addWidget( cancelB );
2407 d->rightLayout = new QHBoxLayout( lay, 5 );
2408 d->topLevelLayout->setStretchFactor( d->mcView, 1 );
2409 d->topLevelLayout->setStretchFactor( files, 1 );
2414 setTabOrder( d->paths, d->goBack );
2415 setTabOrder( d->goBack, d->cdToParent );
2417 setTabOrder( d->paths, d->cdToParent );
2419 setTabOrder( d->cdToParent, d->newFolder );
2420 setTabOrder( d->newFolder, d->mcView );
2421 setTabOrder( d->mcView, d->detailView );
2422 setTabOrder( d->detailView, d->moreFiles );
2423 setTabOrder( d->moreFiles, files );
2424 setTabOrder( files, nameEdit );
2425 setTabOrder( nameEdit, d->types );
2426 setTabOrder( d->types, okB );
2427 setTabOrder( okB, cancelB );
2429 d->rw = tr( "Read-write" );
2430 d->ro = tr( "Read-only" );
2431 d->wo = tr( "Write-only" );
2432 d->inaccessible = tr( "Inaccessible" );
2434 d->symLinkToFile = tr( "Symlink to File" );
2435 d->symLinkToDir = tr( "Symlink to Directory" );
2436 d->symLinkToSpecial = tr( "Symlink to Special" );
2437 d->file = tr( "File" );
2438 d->dir = tr( "Dir" );
2439 d->special = tr( "Special" );
2442 QRect screen = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber( pos() ) );
2443 if ( screen.width() < 1024 ||
2444 screen.height() < 768 ) {
2445 resize( QMIN(screen.width(),420),
2446 QMIN(screen.height(),236) );
2448 QSize s( files->sizeHint() );
2449 s = QSize( s.width() + 300, s.height() + 82 );
2451 if ( s.width() * 3 > screen.width() * 2 )
2452 s.setWidth( screen.width() * 2 / 3 );
2454 if ( s.height() * 3 > screen.height() * 2 )
2455 s.setHeight( screen.height() * 2 / 3 );
2456 else if ( s.height() * 3 < screen.height() )
2457 s.setHeight( screen.height() / 3 );
2461 lastSize = new QSize;
2462 qfd_cleanup_size.add( &lastSize );
2465 resize( *lastSize );
2467 if ( detailViewMode ) {
2468 d->stack->raiseWidget( files );
2469 d->mcView->setOn( FALSE );
2470 d->detailView->setOn( TRUE );
2474 nameEdit->setFocus();
2476 connect( nameEdit, SIGNAL( returnPressed() ),
2477 this, SLOT( fileNameEditReturnPressed() ) );
2484 void QFileDialogP::fileNameEditReturnPressed()
2487 if ( !isDirectoryMode( d->mode ) ) {
2490 d->currentFileName = QString::null;
2491 if ( nameEdit->text().isEmpty() ) {
2492 emit fileSelected( selectedFile() );
2496 QFileDialogPrivate::File * c
2497 = (QFileDialogPrivate::File *)files->currentItem();
2498 if ( c && files->isSelected(c) )
2501 f = QUrlInfo( d->url, nameEdit->text() );
2503 setUrl( QUrlOperator( d->url, QFileDialogPrivate::encodeFileName(nameEdit->text() + "/" ) ) );
2504 d->checkForFilter = TRUE;
2505 trySetSelection( TRUE, d->url, TRUE );
2506 d->checkForFilter = FALSE;
2509 nameEdit->setText( QString::null );
2510 d->ignoreReturn = TRUE;
2516 Changes the preview mode to the mode specified at \a id.
2519 void QFileDialogP::changeMode( int id )
2521 if ( !d->infoPreview && !d->contentsPreview )
2524 QButton *btn = (QButton*)d->modeButtons->find( id );
2528 if ( btn == d->previewContents && !d->contentsPreview )
2530 if ( btn == d->previewInfo && !d->infoPreview )
2533 if ( btn != d->previewContents && btn != d->previewInfo ) {
2536 if ( files->currentItem() ) {
2537 if ( d->infoPreviewer )
2538 d->infoPreviewer->previewUrl( QUrl( d->url, files->currentItem()->text( 0 ) ) );
2539 if ( d->contentsPreviewer )
2540 d->contentsPreviewer->previewUrl( QUrl( d->url, files->currentItem()->text( 0 ) ) );
2542 if ( btn == d->previewInfo )
2543 d->preview->raiseWidget( d->infoPreviewWidget );
2545 d->preview->raiseWidget( d->contentsPreviewWidget );
2551 Destroys the file dialog.
2554 QFileDialogP::~QFileDialogP()
2556 // since clear might call setContentsPos which would emit
2557 // a signal and thus cause a recompute of sizes...
2558 files->blockSignals( TRUE );
2559 d->moreFiles->blockSignals( TRUE );
2561 d->moreFiles->clear();
2562 d->moreFiles->blockSignals( FALSE );
2563 files->blockSignals( FALSE );
2564 if ( QApplication::overrideCursor() )
2565 QApplication::restoreOverrideCursor();
2572 \property QFileDialogP::selectedFile
2574 \brief the name of the selected file
2576 If a file was selected selectedFile contains the file's name including
2577 its absolute path; otherwise selectedFile is empty.
2579 \sa QString::isEmpty(), selectedFiles, selectedFilter
2582 QString QFileDialogP::selectedFile() const
2584 QString s = d->currentFileName;
2585 // remove the protocol because we do not want to encode it...
2586 QString prot = QUrl( s ).protocol();
2587 if ( !prot.isEmpty() ) {
2589 s.remove( 0, prot.length() );
2591 QUrl u( prot + QFileDialogPrivate::encodeFileName( s ) );
2592 if ( u.isLocalFile() ) {
2593 QString s = u.toString();
2594 if ( s.left( 5 ) == "file:" )
2598 return d->currentFileName;
2602 \property QFileDialogP::selectedFilter
2604 \brief the filter which the user has selected in the file dialog
2606 \sa filterSelected(), selectedFiles, selectedFile
2609 QString QFileDialogP::selectedFilter() const
2611 return d->types->currentText();
2616 Sets the current filter selected in the file dialog to the
2617 \a{n}-th filter in the filter list.
2619 \sa filterSelected(), selectedFilter(), selectedFiles(), selectedFile()
2622 void QFileDialogP::setSelectedFilter( int n )
2624 d->types->setCurrentItem( n );
2625 QString f = d->types->currentText();
2626 QRegExp r( QString::fromLatin1(qt_file_dialog_filter_reg_exp) );
2627 int index = r.search( f );
2630 d->url.setNameFilter( f );
2635 Sets the current filter selected in the file dialog to the first
2636 one that contains the text \a mask.
2639 void QFileDialogP::setSelectedFilter( const QString& mask )
2643 for ( n = 0; n < d->types->count(); n++ ) {
2644 if ( d->types->text( n ).contains( mask, FALSE ) ) {
2645 d->types->setCurrentItem( n );
2647 QRegExp r( QString::fromLatin1(qt_file_dialog_filter_reg_exp) );
2648 int index = r.search( f );
2651 d->url.setNameFilter( f );
2659 \property QFileDialogP::selectedFiles
2661 \brief the list of selected files
2663 If one or more files are selected, selectedFiles contains their
2664 names including their absolute paths. If no files are selected or
2665 the mode isn't ExistingFiles selectedFiles is an empty list.
2667 It is more convenient to use selectedFile() if the mode is
2668 \c ExistingFile, \c Directory or \c DirectoryOnly.
2670 Note that if you want to iterate over the list, you should
2671 iterate over a copy, e.g.
2673 QStringList list = myFileDialog.selectedFiles();
2674 QStringList::Iterator it = list.begin();
2675 while( it != list.end() ) {
2676 myProcessing( *it );
2681 \sa selectedFile, selectedFilter, QValueList::empty()
2684 QStringList QFileDialogP::selectedFiles() const
2688 if ( mode() == ExistingFiles ) {
2689 QStringList selectedLst;
2690 QString selectedFiles = nameEdit->text();
2691 selectedFiles.truncate( selectedFiles.findRev( '\"' ) );
2692 selectedLst = selectedLst.split( QString("\" "), selectedFiles );
2693 for ( QStringList::Iterator it = selectedLst.begin(); it != selectedLst.end(); ++it ) {
2695 if ( (*it)[0] == '\"' ) {
2696 u = QUrl( d->url, QFileDialogPrivate::encodeFileName( (*it).mid(1) ) );
2698 u = QUrl( d->url, QFileDialogPrivate::encodeFileName( (*it) ) );
2700 if ( u.isLocalFile() ) {
2701 QString s = u.toString();
2702 if ( s.left( 5 ) == "file:" )
2706 lst << u.toString();
2715 Sets the default selection to \a filename. If \a filename is
2716 absolute, setDir() is also called to set the file dialog's working
2717 directory to the filename's directory.
2720 Only for external use. Not useful inside QFileDialogP.
2724 void QFileDialogP::setSelection( const QString & filename )
2727 QString nf = d->url.nameFilter();
2728 if ( QUrl::isRelativeUrl( filename ) )
2729 d->url = QUrlOperator( d->url, QFileDialogPrivate::encodeFileName( filename ) );
2731 d->url = QUrlOperator( filename );
2732 d->url.setNameFilter( nf );
2733 d->checkForFilter = TRUE;
2735 bool isDir = d->url.isDir( &isDirOk );
2737 isDir = d->url.path().right( 1 ) == "/";
2739 QUrlOperator u( d->url );
2740 d->url.setPath( d->url.dirPath() );
2741 trySetSelection( FALSE, u, TRUE );
2742 d->ignoreNextRefresh = TRUE;
2743 nameEdit->selectAll();
2745 emit dirEntered( d->url.dirPath() );
2747 if ( !d->url.path().isEmpty() &&
2748 d->url.path().right( 1 ) != "/" ) {
2749 QString p = d->url.path();
2751 d->url.setPath( p );
2753 trySetSelection( TRUE, d->url, FALSE );
2755 emit dirEntered( d->url.dirPath() );
2756 nameEdit->setText( QString::fromLatin1("") );
2758 d->checkForFilter = FALSE;
2762 \property QFileDialogP::dirPath
2764 \brief the file dialog's working directory
2769 QString QFileDialogP::dirPath() const
2771 return d->url.dirPath();
2777 Sets the filter used in the file dialog to \a newFilter.
2779 If \a newFilter contains a pair of parentheses containing one or more
2780 of <em><b>anything*something</b></em> separated by spaces or by
2781 semi-colons then only the text contained in the parentheses is used as
2782 the filter. This means that these calls are all equivalent:
2785 fd->setFilter( "All C++ files (*.cpp *.cc *.C *.cxx *.c++)" );
2786 fd->setFilter( "*.cpp *.cc *.C *.cxx *.c++" );
2787 fd->setFilter( "All C++ files (*.cpp;*.cc;*.C;*.cxx;*.c++)" );
2788 fd->setFilter( "*.cpp;*.cc;*.C;*.cxx;*.c++" );
2794 void QFileDialogP::setFilter( const QString & newFilter )
2796 if ( newFilter.isEmpty() )
2798 QString f = newFilter;
2799 QRegExp r( QString::fromLatin1(qt_file_dialog_filter_reg_exp) );
2800 int index = r.search( f );
2803 d->url.setNameFilter( f );
2804 if ( d->types->count() == 1 ) {
2806 d->types->insertItem( newFilter );
2808 for ( int i = 0; i < d->types->count(); ++i ) {
2809 if ( d->types->text( i ).left( newFilter.length() ) == newFilter ) {
2810 d->types->setCurrentItem( i );
2820 Sets the file dialog's working directory to \a pathstr.
2825 void QFileDialogP::setDir( const QString & pathstr )
2827 QString dr = pathstr;
2831 #if defined(Q_OS_UNIX)
2832 if ( dr.length() && dr[0] == '~' ) {
2837 while( i < (int)dr.length() && dr[i] != '/' )
2841 user = ::getlogin();
2843 user = getenv( "LOGNAME" );
2845 user = dr.mid( 1, i-1 ).local8Bit();
2846 dr = dr.mid( i, dr.length() );
2847 pw = ::getpwnam( user );
2849 dr.prepend( QString::fromLocal8Bit(pw->pw_dir) );
2857 Returns the current directory shown in the file dialog.
2859 The ownership of the QDir pointer is transferred to the caller, so
2860 it must be deleted by the caller when no longer required.
2865 const QDir *QFileDialogP::dir() const
2867 if ( d->url.isLocalFile() )
2868 return new QDir( d->url.path() );
2874 Sets the file dialog's working directory to \a dir.
2878 void QFileDialogP::setDir( const QDir &dir )
2881 QString nf( d->url.nameFilter() );
2882 d->url = dir.canonicalPath();
2883 d->url.setNameFilter( nf );
2884 QUrlInfo i( d->url, nameEdit->text() );
2885 d->checkForFilter = TRUE;
2886 trySetSelection( i.isDir(), QUrlOperator( d->url, QFileDialogPrivate::encodeFileName(nameEdit->text() ) ), FALSE );
2887 d->checkForFilter = FALSE;
2889 emit dirEntered( d->url.path() );
2893 Sets the file dialog's working directory to the directory specified at \a url.
2898 void QFileDialogP::setUrl( const QUrlOperator &url )
2900 QString nf = d->url.nameFilter();
2902 d->url = QUrl( d->url, url.toString( FALSE, FALSE ) );
2903 d->url.setNameFilter( nf );
2905 d->checkForFilter = TRUE;
2906 if ( !d->url.isDir() ) {
2907 QUrlOperator u = d->url;
2908 d->url.setPath( d->url.dirPath() );
2909 trySetSelection( FALSE, u, FALSE );
2911 emit dirEntered( d->url.dirPath() );
2912 QString fn = u.fileName();
2913 nameEdit->setText( fn );
2915 trySetSelection( TRUE, d->url, FALSE );
2917 emit dirEntered( d->url.dirPath() );
2919 d->checkForFilter = FALSE;
2923 \property QFileDialogP::showHiddenFiles
2925 \brief whether hidden files are shown in the file dialog
2927 The default is FALSE, i.e. don't show hidden files.
2930 void QFileDialogP::setShowHiddenFiles( bool s )
2932 if ( s == bShowHiddenFiles )
2935 bShowHiddenFiles = s;
2939 bool QFileDialogP::showHiddenFiles() const
2941 return bShowHiddenFiles;
2945 Rereads the current directory shown in the file dialog.
2947 The only time you will need to call this function is if the contents of
2948 the directory change and you wish to refresh the file dialog to reflect
2954 void QFileDialogP::rereadDir()
2956 if ( !QApplication::overrideCursor() )
2957 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
2958 d->pendingItems.clear();
2959 if ( d->mimeTypeTimer->isActive() )
2960 d->mimeTypeTimer->stop();
2961 d->currListChildren = d->url.listChildren();
2966 \fn void QFileDialogP::fileHighlighted( const QString& )
2968 This signal is emitted when the user highlights a file.
2970 \sa fileSelected(), filesSelected()
2974 \fn void QFileDialogP::fileSelected( const QString& )
2976 This signal is emitted when the user selects a file.
2978 \sa filesSelected(), fileHighlighted(), selectedFile()
2982 \fn void QFileDialogP::filesSelected( const QStringList& )
2984 This signal is emitted when the user selects one or more files in \e
2987 \sa fileSelected(), fileHighlighted(), selectedFiles()
2991 \fn void QFileDialogP::dirEntered( const QString& )
2993 This signal is emitted when the user enters a directory.
2999 \fn void QFileDialogP::filterSelected( const QString& )
3001 This signal is emitted when the user selects a filter.
3003 \sa selectedFilter()
3006 extern bool qt_resolve_symlinks; // defined in qapplication.cpp
3009 This is a convenience static function that returns an existing file
3010 selected by the user. If the user pressed Cancel, it returns a null
3014 QString s = QFileDialogP::getOpenFileName(
3016 "Images (*.png *.xpm *.jpg)",
3019 "Choose a file to open" );
3022 The function creates a modal file dialog called \a name, with
3023 parent, \a parent. If a parent is not 0, the dialog will be shown
3024 centered over the parent.
3026 The file dialog's working directory will be set to \a startWith. If \a
3027 startWith includes a file name, the file will be selected. The filter
3028 is set to \a filter so that only those files which match the filter
3029 are shown. The filter selected is set to \a selectedFilter. The parameters
3030 \a startWith, \a selectedFilter and \a filter may be QString::null.
3032 The dialog's caption is set to \a caption. If \a caption is not
3033 specified then a default caption will be used.
3035 Under Windows and Mac OS X, this static function will use the native
3036 file dialog and not a QFileDialogP, unless the style of the application
3037 is set to something other than the native style.
3039 Under Unix/X11, the normal behavior of the file dialog is to resolve
3040 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp,
3041 the file dialog will change to /var/tmp after entering /usr/tmp.
3042 If \a resolveSymlinks is FALSE, the file dialog will treat
3043 symlinks as regular directories.
3045 \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory()
3048 QString QFileDialogP::getOpenFileName( const QString & startWith,
3049 const QString& filter,
3050 QWidget *parent, const char* name,
3051 const QString& caption,
3052 QString *selectedFilter,
3053 bool resolveSymlinks )
3055 bool save_qt_resolve_symlinks = qt_resolve_symlinks;
3056 qt_resolve_symlinks = resolveSymlinks;
3058 QStringList filters;
3059 if ( !filter.isEmpty() )
3060 filters = makeFiltersList( filter );
3063 QString initialSelection;
3064 //### Problem with the logic here: If a startWith is given and a file
3065 // with that name exists in D->URL, the box will be opened at D->URL instead of
3066 // the last directory used ('workingDirectory').
3068 // hm... isn't that problem exactly the documented behaviour? the
3069 // documented behaviour sounds meaningful.
3070 if ( !startWith.isEmpty() ) {
3071 QUrlOperator u( startWith );
3072 if ( u.isLocalFile() && QFileInfo( u.path() ).isDir() ) {
3073 *workingDirectory = startWith;
3075 if ( u.isLocalFile() ) {
3076 QFileInfo fi( u.dirPath() );
3077 if ( fi.exists() ) {
3078 *workingDirectory = u.dirPath();
3079 initialSelection = u.fileName();
3082 *workingDirectory = u.toString();
3083 initialSelection = QString::null;//u.fileName();
3088 if ( workingDirectory->isNull() )
3089 *workingDirectory = QDir::currentDirPath();
3091 #if defined(Q_WS_WIN)
3092 if ( qApp->style().styleHint( QStyle::SH_GUIStyle ) == WindowsStyle )
3093 return winGetOpenFileName( initialSelection, filter, workingDirectory,
3094 parent, name, caption, selectedFilter );
3095 #elif defined(Q_WS_MAC)
3096 if( ( qApp->style().inherits(QMAC_DEFAULT_STYLE) ) ) {
3097 QString f = macGetOpenFileNames(filter, workingDirectory,
3098 parent, name, caption, FALSE).first();
3103 QFileDialogP *dlg = new QFileDialogP( *workingDirectory, QString::null, parent, name ? name : "qt_filedlg_gofn", TRUE );
3105 #ifndef QT_NO_WIDGET_TOPEXTRA
3106 if ( parent && parent->icon() && !parent->icon()->isNull() )
3107 dlg->setIcon( *parent->icon() );
3108 else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() )
3109 dlg->setIcon( *qApp->mainWidget()->icon() );
3111 if ( !caption.isNull() )
3112 dlg->setCaption( caption );
3114 dlg->setCaption( QFileDialogP::tr( "Open" ) );
3117 dlg->setFilters( filters );
3118 if ( selectedFilter )
3119 dlg->setFilter( *selectedFilter );
3120 dlg->setMode( QFileDialogP::ExistingFile );
3122 if ( !initialSelection.isEmpty() )
3123 dlg->setSelection( initialSelection );
3124 if ( dlg->exec() == QDialog::Accepted ) {
3125 result = dlg->selectedFile();
3126 *workingDirectory = dlg->d->url;
3127 if ( selectedFilter )
3128 *selectedFilter = dlg->selectedFilter();
3132 qt_resolve_symlinks = save_qt_resolve_symlinks;
3138 This is a convenience static function that will return a file name
3139 selected by the user. The file does not have to exist.
3141 It creates a modal file dialog called \a name, with parent, \a parent.
3142 If a parent is not 0, the dialog will be shown centered over the
3146 QString s = QFileDialogP::getSaveFileName(
3148 "Images (*.png *.xpm *.jpg)",
3151 "Choose a filename to save under" );
3154 The file dialog's working directory will be set to \a startWith. If \a
3155 startWith includes a file name, the file will be selected. The filter
3156 is set to \a filter so that only those files which match the filter
3157 are shown. The filter selected is set to \a selectedFilter. The parameters
3158 \a startWith, \a selectedFilter and \a filter may be QString::null.
3160 The dialog's caption is set to \a caption. If \a caption is not
3161 specified then a default caption will be used.
3163 Under Windows and Mac OS X, this static function will use the native
3164 file dialog and not a QFileDialogP, unless the style of the application
3165 is set to something other than the native style.
3167 Under Unix/X11, the normal behavior of the file dialog is to resolve
3168 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp,
3169 the file dialog will change to /var/tmp after entering /usr/tmp.
3170 If \a resolveSymlinks is FALSE, the file dialog will treat
3171 symlinks as regular directories.
3173 \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory()
3176 QString QFileDialogP::getSaveFileName( const QString & startWith,
3177 const QString& filter,
3178 QWidget *parent, const char* name,
3179 const QString& caption,
3180 QString *selectedFilter,
3181 bool resolveSymlinks)
3183 bool save_qt_resolve_symlinks = qt_resolve_symlinks;
3184 qt_resolve_symlinks = resolveSymlinks;
3186 QStringList filters;
3187 if ( !filter.isEmpty() )
3188 filters = makeFiltersList( filter );
3191 QString initialSelection;
3192 if ( !startWith.isEmpty() ) {
3193 QUrlOperator u( startWith );
3194 if ( u.isLocalFile() && QFileInfo( u.path() ).isDir() ) {
3195 *workingDirectory = startWith;
3197 if ( u.isLocalFile() ) {
3198 QFileInfo fi( u.dirPath() );
3199 if ( fi.exists() ) {
3200 *workingDirectory = u.dirPath();
3201 initialSelection = u.fileName();
3204 *workingDirectory = u.toString();
3205 initialSelection = QString::null;//u.fileName();
3210 if ( workingDirectory->isNull() )
3211 *workingDirectory = QDir::currentDirPath();
3213 #if defined(Q_WS_WIN)
3214 if ( qApp->style().styleHint( QStyle::SH_GUIStyle ) == WindowsStyle )
3215 return winGetSaveFileName( initialSelection, filter, workingDirectory,
3216 parent, name, caption, selectedFilter );
3217 #elif defined(Q_WS_MAC)
3218 if( ( qApp->style().inherits(QMAC_DEFAULT_STYLE) ) )
3219 return macGetSaveFileName( initialSelection, filter, workingDirectory,
3220 parent, name, caption );
3223 QFileDialogP *dlg = new QFileDialogP( *workingDirectory, QString::null, parent, name ? name : "qt_filedlg_gsfn", TRUE );
3226 #ifndef QT_NO_WIDGET_TOPEXTRA
3227 if ( parent && parent->icon() && !parent->icon()->isNull() )
3228 dlg->setIcon( *parent->icon() );
3229 else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() )
3230 dlg->setIcon( *qApp->mainWidget()->icon() );
3232 if ( !caption.isNull() )
3233 dlg->setCaption( caption );
3235 dlg->setCaption( QFileDialogP::tr( "Save As" ) );
3239 dlg->setFilters( filters );
3240 if ( selectedFilter )
3241 dlg->setFilter( *selectedFilter );
3242 dlg->setMode( QFileDialogP::AnyFile );
3243 if ( !initialSelection.isEmpty() )
3244 dlg->setSelection( initialSelection );
3245 if ( dlg->exec() == QDialog::Accepted ) {
3246 result = dlg->selectedFile();
3247 *workingDirectory = dlg->d->url;
3248 if ( selectedFilter )
3249 *selectedFilter = dlg->selectedFilter();
3253 qt_resolve_symlinks = save_qt_resolve_symlinks;
3260 Activated when the "OK" button is clicked.
3263 void QFileDialogP::okClicked()
3265 QString fn( nameEdit->text() );
3267 #if defined(Q_WS_WIN)
3268 QFileInfo fi( d->url.path() + fn );
3269 if ( fi.isSymLink() ) {
3270 nameEdit->setText( fi.readLink() );
3274 if ( fn.contains("*") ) {
3276 nameEdit->blockSignals( TRUE );
3277 nameEdit->setText( QString::fromLatin1("") );
3278 nameEdit->blockSignals( FALSE );
3282 *workingDirectory = d->url;
3283 detailViewMode = files->isVisible();
3286 if ( isDirectoryMode( d->mode ) ) {
3287 if ( d->ignoreReturn ) {
3288 d->ignoreReturn = FALSE;
3291 QUrlInfo f( d->url, nameEdit->text() );
3293 d->currentFileName = d->url;
3294 if ( d->currentFileName.right(1) != "/" )
3295 d->currentFileName += '/';
3296 if ( f.name() != "." )
3297 d->currentFileName += f.name();
3303 // if we're in multi-selection mode and something is selected,
3304 // accept it and be done.
3305 if ( mode() == ExistingFiles ) {
3306 if ( ! nameEdit->text().isEmpty() ) {
3307 QStringList sf = selectedFiles();
3309 if ( sf.count() == 1 ) {
3310 QUrlOperator u( d->url, sf[0] );
3312 isdir = u.isDir(&ok) && ok;
3315 emit filesSelected( sf );
3322 if ( mode() == AnyFile ) {
3323 QUrlOperator u( d->url, QFileDialogPrivate::encodeFileName(nameEdit->text()) );
3325 d->currentFileName = u;
3326 emit fileSelected( selectedFile() );
3332 if ( mode() == ExistingFile ) {
3333 QUrl u( d->url, QFileDialogPrivate::encodeFileName(nameEdit->text()) );
3334 if ( u.isLocalFile() ) {
3335 QFileInfo f( u.path() );
3339 QNetworkProtocol *p = QNetworkProtocol::getNetworkProtocol( d->url.protocol() );
3340 if ( p && (p->supportedOperations()&QNetworkProtocol::OpListChildren) ) {
3341 QUrlInfo ui( d->url, nameEdit->text() );
3342 if ( !ui.isValid() )
3348 // If selection is valid, return it, else try
3349 // using selection as a directory to change to.
3350 if ( !d->currentFileName.isNull() && !d->currentFileName.contains( "*" ) ) {
3351 emit fileSelected( selectedFile() );
3355 QFileDialogPrivate::File * c
3356 = (QFileDialogPrivate::File *)files->currentItem();
3357 QFileDialogPrivate::MCItem * m
3358 = (QFileDialogPrivate::MCItem *)d->moreFiles->item( d->moreFiles->currentItem() );
3359 if ( c && files->isVisible() && files->hasFocus() ||
3360 m && d->moreFiles->isVisible() && d->moreFiles->hasFocus() ) {
3361 if ( c && files->isVisible() )
3364 f = ( (QFileDialogPrivate::File*)m->i )->info;
3366 f = QUrlInfo( d->url, nameEdit->text() );
3369 setUrl( QUrlOperator( d->url, QFileDialogPrivate::encodeFileName(f.name() + "/" ) ) );
3370 d->checkForFilter = TRUE;
3371 trySetSelection( TRUE, d->url, TRUE );
3372 d->checkForFilter = FALSE;
3374 if ( !nameEdit->text().contains( "/" ) &&
3375 !nameEdit->text().contains( "\\" )
3376 #if defined(Q_OS_WIN32)
3377 && nameEdit->text()[ 1 ] != ':'
3380 addFilter( nameEdit->text() );
3381 else if ( nameEdit->text()[ 0 ] == '/' ||
3382 nameEdit->text()[ 0 ] == '\\'
3383 #if defined(Q_OS_WIN32)
3384 || nameEdit->text()[ 1 ] == ':'
3387 setDir( nameEdit->text() );
3388 else if ( nameEdit->text().left( 3 ) == "../" || nameEdit->text().left( 3 ) == "..\\" )
3389 setDir( QUrl( d->url.toString(), QFileDialogPrivate::encodeFileName(nameEdit->text() ) ).toString() );
3391 nameEdit->setText( "" );
3397 Activated when the "Filter" button is clicked.
3400 void QFileDialogP::filterClicked()
3407 Activated when the "Cancel" button is clicked.
3410 void QFileDialogP::cancelClicked()
3412 *workingDirectory = d->url;
3413 detailViewMode = files->isVisible();
3422 void QFileDialogP::resizeEvent( QResizeEvent * e )
3424 QDialog::resizeEvent( e );
3430 The only correct way to try to set currentFileName
3432 bool QFileDialogP::trySetSelection( bool isDir, const QUrlOperator &u, bool updatelined )
3434 if ( !isDir && !u.path().isEmpty() && u.path().right( 1 ) == "/" )
3436 if ( u.fileName().contains( "*") && d->checkForFilter ) {
3437 QString fn( u.fileName() );
3438 if ( fn.contains( "*" ) ) {
3440 d->currentFileName = QString::null;
3441 d->url.setFileName( QString::null );
3442 nameEdit->setText( QString::fromLatin1("") );
3448 if ( d->preview && d->preview->isVisible() ) {
3449 if ( d->infoPreviewer )
3450 d->infoPreviewer->previewUrl( u );
3451 if ( d->contentsPreviewer )
3452 d->contentsPreviewer->previewUrl( u );
3456 QString old = d->currentFileName;
3458 if ( isDirectoryMode( mode() ) ) {
3460 d->currentFileName = u;
3462 d->currentFileName = QString::null;
3463 } else if ( !isDir && mode() == ExistingFiles ) {
3464 d->currentFileName = u;
3465 } else if ( !isDir || ( mode() == AnyFile && !isDir ) ) {
3466 d->currentFileName = u;
3468 d->currentFileName = QString::null;
3470 if ( updatelined && !d->currentFileName.isEmpty() ) {
3471 // If the selection is valid, or if its a directory, allow OK.
3472 if ( !d->currentFileName.isNull() || isDir ) {
3473 if ( u.fileName() != ".." ) {
3474 QString fn = u.fileName();
3475 nameEdit->setText( fn );
3477 nameEdit->setText("");
3480 nameEdit->setText( QString::fromLatin1("") );
3483 if ( !d->currentFileName.isNull() || isDir ) {
3484 okB->setEnabled( TRUE );
3485 } else if ( !isDirectoryMode( d->mode ) ) {
3486 okB->setEnabled( FALSE );
3489 if ( d->currentFileName.length() && old != d->currentFileName )
3490 emit fileHighlighted( selectedFile() );
3492 return !d->currentFileName.isNull();
3496 /*! Make sure the minimum and maximum sizes of everything are sane.
3499 void QFileDialogP::updateGeometries()
3501 if ( !d || !d->geometryDirty )
3504 d->geometryDirty = FALSE;
3508 // we really should have a QSize::unite()
3509 #define RM r.setWidth( QMAX(r.width(),t.width()) ); \
3510 r.setHeight( QMAX(r.height(),t.height()) )
3513 r = d->pathL->sizeHint();
3514 t = d->fileL->sizeHint();
3516 t = d->typeL->sizeHint();
3518 d->pathL->setFixedSize( d->pathL->sizeHint() );
3519 d->fileL->setFixedSize( r );
3520 d->typeL->setFixedSize( r );
3522 // single-line input areas
3523 r = d->paths->sizeHint();
3524 t = nameEdit->sizeHint();
3526 t = d->types->sizeHint();
3528 r.setWidth( t.width() * 2 / 3 );
3529 t.setWidth( QWIDGETSIZE_MAX );
3530 t.setHeight( r.height() );
3531 d->paths->setMinimumSize( r );
3532 d->paths->setMaximumSize( t );
3533 nameEdit->setMinimumSize( r );
3534 nameEdit->setMaximumSize( t );
3535 d->types->setMinimumSize( r );
3536 d->types->setMaximumSize( t );
3538 // buttons on top row
3539 r = QSize( 0, d->paths->minimumSize().height() );
3540 t = QSize( 21, 20 );
3542 if ( r.height()+1 > r.width() )
3543 r.setWidth( r.height()+1 );
3545 d->goBack->setFixedSize( r );
3546 d->cdToParent->setFixedSize( r );
3547 d->newFolder->setFixedSize( r );
3548 d->mcView->setFixedSize( r );
3549 d->detailView->setFixedSize( r );
3552 if ( !d->toolButtons.isEmpty() ) {
3553 for ( b = d->toolButtons.first(); b; b = d->toolButtons.next() )
3554 b->setFixedSize( b->sizeHint().width(), r.height() );
3557 if ( d->infoPreview ) {
3558 d->previewInfo->show();
3559 d->previewInfo->setFixedSize( r );
3561 d->previewInfo->hide();
3562 d->previewInfo->setFixedSize( QSize( 0, 0 ) );
3565 if ( d->contentsPreview ) {
3566 d->previewContents->show();
3567 d->previewContents->setFixedSize( r );
3569 d->previewContents->hide();
3570 d->previewContents->setFixedSize( QSize( 0, 0 ) );
3573 // open/save, cancel
3574 r = QSize( 75, 20 );
3575 t = okB->sizeHint();
3577 t = cancelB->sizeHint();
3580 okB->setFixedSize( r );
3581 cancelB->setFixedSize( r );
3583 d->topLevelLayout->activate();
3589 /*! Updates the file name edit box to \a newItem in the file dialog
3590 when the cursor moves in the listview.
3593 void QFileDialogP::updateFileNameEdit( QListViewItem * newItem )
3598 if ( mode() == ExistingFiles ) {
3599 detailViewSelectionChanged();
3600 QUrl u = QUrl( d->url, QFileDialogPrivate::encodeFileName( ((QFileDialogPrivate::File*)files->currentItem())->info.name() ) );
3601 QFileInfo fi( u.toString( FALSE, FALSE ) );
3603 emit fileHighlighted( u.toString( FALSE, FALSE ) );
3604 } else if ( files->isSelected( newItem ) ) {
3605 QFileDialogPrivate::File * i = (QFileDialogPrivate::File *)newItem;
3606 if ( i && i->i && !i->i->isSelected() ) {
3607 d->moreFiles->blockSignals( TRUE );
3608 d->moreFiles->setSelected( i->i, TRUE );
3609 d->moreFiles->blockSignals( FALSE );
3611 // Encode the filename in case it had any special characters in it
3612 QString encFile = QFileDialogPrivate::encodeFileName( newItem->text( 0 ) );
3613 trySetSelection( i->info.isDir(), QUrlOperator( d->url, encFile ), TRUE );
3617 void QFileDialogP::detailViewSelectionChanged()
3619 if ( d->mode != ExistingFiles )
3624 QListViewItem * i = files->firstChild();
3625 d->moreFiles->blockSignals( TRUE );
3627 if ( d->moreFiles && isVisible() ) {
3628 if ( ( (QFileDialogPrivate::File *)i )->i->isSelected() != i->isSelected() )
3629 d->moreFiles->setSelected( ( (QFileDialogPrivate::File *)i )->i, i->isSelected() );
3631 if ( i->isSelected() && !( (QFileDialogPrivate::File *)i )->info.isDir() )
3632 str += QString( "\"%1\" " ).arg( i->text( 0 ) );
3633 i = i->nextSibling();
3635 d->moreFiles->blockSignals( FALSE );
3636 nameEdit->setText( str );
3637 nameEdit->setCursorPosition( str.length() );
3638 okB->setEnabled( TRUE );
3639 if ( d->preview && d->preview->isVisible() && files->currentItem() ) {
3640 QUrl u = QUrl( d->url, QFileDialogPrivate::encodeFileName( ((QFileDialogPrivate::File*)files->currentItem())->info.name() ) );
3641 if ( d->infoPreviewer )
3642 d->infoPreviewer->previewUrl( u );
3643 if ( d->contentsPreviewer )
3644 d->contentsPreviewer->previewUrl( u );
3648 void QFileDialogP::listBoxSelectionChanged()
3650 if ( d->mode != ExistingFiles )
3653 if ( d->ignoreNextRefresh ) {
3654 d->ignoreNextRefresh = FALSE;
3660 QListBoxItem * i = d->moreFiles->item( 0 );
3661 QListBoxItem * j = 0;
3663 files->blockSignals( TRUE );
3665 if ( files && isVisible() ) {
3666 if ( ( (QFileDialogPrivate::MCItem *)i )->i->isSelected() != i->isSelected() )
3667 files->setSelected( ( (QFileDialogPrivate::MCItem *)i )->i, i->isSelected() );
3669 if ( d->moreFiles->isSelected( i )
3670 && !( (QFileDialogPrivate::File*)( (QFileDialogPrivate::MCItem *)i )->i )->info.isDir() )
3672 str += QString( "\"%1\" " ).arg( i->text() );
3676 i = d->moreFiles->item( ++index );
3678 files->blockSignals( FALSE );
3679 nameEdit->setText( str );
3680 nameEdit->setCursorPosition( str.length() );
3681 okB->setEnabled( TRUE );
3682 if ( d->preview && d->preview->isVisible() && j ) {
3683 QUrl u = QUrl( d->url,
3684 QFileDialogPrivate::encodeFileName( ( (QFileDialogPrivate::File*)( (QFileDialogPrivate::MCItem*)j )->i )->info.name() ) );
3685 if ( d->infoPreviewer )
3686 d->infoPreviewer->previewUrl( u );
3687 if ( d->contentsPreviewer )
3688 d->contentsPreviewer->previewUrl( u );
3694 void QFileDialogP::updateFileNameEdit( QListBoxItem * newItem )
3698 QFileDialogPrivate::MCItem * i = (QFileDialogPrivate::MCItem *)newItem;
3699 if ( d->mode != ExistingFiles && i->i ) {
3700 i->i->listView()->setSelected( i->i, i->isSelected() );
3701 updateFileNameEdit( i->i );
3706 /*! Updates the dialog when the file name edit changes. */
3708 void QFileDialogP::fileNameEditDone()
3710 QUrlInfo f( d->url, nameEdit->text() );
3711 if ( mode() != QFileDialogP::ExistingFiles ) {
3712 QUrlOperator u( d->url, QFileDialogPrivate::encodeFileName( nameEdit->text() ) );
3713 trySetSelection( f.isDir(), u, FALSE );
3714 if ( d->preview && d->preview->isVisible() ) {
3715 if ( d->infoPreviewer )
3716 d->infoPreviewer->previewUrl( u );
3717 if ( d->contentsPreviewer )
3718 d->contentsPreviewer->previewUrl( u );
3725 /*! This private slot reacts to double-clicks in the list view. The item that
3726 was double-clicked is specified in \a newItem */
3728 void QFileDialogP::selectDirectoryOrFile( QListViewItem * newItem )
3731 *workingDirectory = d->url;
3732 detailViewMode = files->isVisible();
3738 #if defined(Q_WS_WIN)
3739 QFileInfo fi( d->url.path() + newItem->text(0) );
3740 if ( fi.isSymLink() ) {
3741 nameEdit->setText( fi.readLink() );
3747 QFileDialogPrivate::File * i = (QFileDialogPrivate::File *)newItem;
3749 QString oldName = nameEdit->text();
3750 if ( i->info.isDir() ) {
3751 setUrl( QUrlOperator( d->url, QFileDialogPrivate::encodeFileName( i->info.name() ) + "/" ) );
3752 if ( isDirectoryMode( mode() ) ) {
3753 QUrlInfo f ( d->url, QString::fromLatin1( "." ) );
3754 trySetSelection( f.isDir(), d->url, TRUE );
3756 } else if ( newItem->isSelectable() &&
3757 trySetSelection( i->info.isDir(), QUrlOperator( d->url, QFileDialogPrivate::encodeFileName( i->info.name() ) ), TRUE ) ) {
3758 if ( !isDirectoryMode( mode() ) ) {
3759 emit fileSelected( selectedFile() );
3762 } else if ( isDirectoryMode( d->mode ) ) {
3763 d->currentFileName = d->url;
3766 if ( !oldName.isEmpty() && !isDirectoryMode( mode() ) )
3767 nameEdit->setText( oldName );
3771 void QFileDialogP::selectDirectoryOrFile( QListBoxItem * newItem )
3776 QFileDialogPrivate::MCItem * i = (QFileDialogPrivate::MCItem *)newItem;
3778 i->i->listView()->setSelected( i->i, i->isSelected() );
3779 selectDirectoryOrFile( i->i );
3784 void QFileDialogP::popupContextMenu( QListViewItem *item, const QPoint &p,
3787 if ( item && d->mode == ExistingFiles )
3790 files->setCurrentItem( item );
3791 files->setSelected( item, TRUE );
3795 popupContextMenu( item ? item->text( 0 ) : QString::null, TRUE, action, p );
3797 if ( action == PA_Open )
3798 selectDirectoryOrFile( item );
3799 else if ( action == PA_Rename )
3800 files->startRename( FALSE );
3801 else if ( action == PA_Delete )
3802 deleteFile( item ? item->text( 0 ) : QString::null );
3803 else if ( action == PA_Reload )
3805 else if ( action == PA_Hidden ) {
3806 bShowHiddenFiles = !bShowHiddenFiles;
3808 } else if ( action == PA_SortName ) {
3809 sortFilesBy = (int)QDir::Name;
3810 sortAscending = TRUE;
3812 } else if ( action == PA_SortSize ) {
3813 sortFilesBy = (int)QDir::Size;
3814 sortAscending = TRUE;
3816 } else if ( action == PA_SortDate ) {
3817 sortFilesBy = (int)QDir::Time;
3818 sortAscending = TRUE;
3820 } else if ( action == PA_SortUnsorted ) {
3821 sortFilesBy = (int)QDir::Unsorted;
3822 sortAscending = TRUE;
3828 void QFileDialogP::popupContextMenu( QListBoxItem *item, const QPoint & p )
3830 if ( item && d->mode == ExistingFiles )
3834 popupContextMenu( item ? item->text() : QString::null, FALSE, action, p );
3836 if ( action == PA_Open )
3837 selectDirectoryOrFile( item );
3838 else if ( action == PA_Rename )
3839 d->moreFiles->startRename( FALSE );
3840 else if ( action == PA_Delete )
3841 deleteFile( item->text() );
3842 else if ( action == PA_Reload )
3844 else if ( action == PA_Hidden ) {
3845 bShowHiddenFiles = !bShowHiddenFiles;
3847 } else if ( action == PA_SortName ) {
3848 sortFilesBy = (int)QDir::Name;
3849 sortAscending = TRUE;
3851 } else if ( action == PA_SortSize ) {
3852 sortFilesBy = (int)QDir::Size;
3853 sortAscending = TRUE;
3855 } else if ( action == PA_SortDate ) {
3856 sortFilesBy = (int)QDir::Time;
3857 sortAscending = TRUE;
3859 } else if ( action == PA_SortUnsorted ) {
3860 sortFilesBy = (int)QDir::Unsorted;
3861 sortAscending = TRUE;
3866 void QFileDialogP::popupContextMenu( const QString &filename, bool,
3867 PopupAction &action, const QPoint &p )
3871 bool glob = filename.isEmpty();
3873 QPopupMenu m( 0, "file dialog context menu" );
3874 m.setCheckable( TRUE );
3878 if ( QUrlInfo( d->url, filename ).isDir() ) {
3879 okt = tr( "&Open" );
3881 if ( mode() == AnyFile )
3882 okt = tr( "&Save" );
3884 okt = tr( "&Open" );
3886 int ok = m.insertItem( okt );
3888 m.insertSeparator();
3889 int rename = m.insertItem( tr( "&Rename" ) );
3890 int del = m.insertItem( tr( "&Delete" ) );
3892 if ( filename.isEmpty() || !QUrlInfo( d->url, filename ).isWritable() ||
3893 filename == ".." ) {
3894 if ( filename.isEmpty() || !QUrlInfo( d->url, filename ).isReadable() )
3895 m.setItemEnabled( ok, FALSE );
3896 m.setItemEnabled( rename, FALSE );
3897 m.setItemEnabled( del, FALSE );
3900 if ( mode() == QFileDialogP::ExistingFiles )
3901 m.setItemEnabled( rename, FALSE );
3908 else if ( res == rename )
3910 else if ( res == del )
3913 int reload = m.insertItem( tr( "R&eload" ) );
3915 QPopupMenu m2( 0, "sort menu" );
3917 int sname = m2.insertItem( tr( "Sort by &Name" ) );
3918 //int stype = m2.insertItem( tr( "Sort by &Type" ) );
3919 int ssize = m2.insertItem( tr( "Sort by &Size" ) );
3920 int sdate = m2.insertItem( tr( "Sort by &Date" ) );
3921 m2.insertSeparator();
3922 int sunsorted = m2.insertItem( tr( "&Unsorted" ) );
3924 //m2.setItemEnabled( stype, FALSE );
3926 if ( sortFilesBy == (int)QDir::Name )
3927 m2.setItemChecked( sname, TRUE );
3928 else if ( sortFilesBy == (int)QDir::Size )
3929 m2.setItemChecked( ssize, TRUE );
3930 // else if ( sortFilesBy == 0x16 )
3931 // m2.setItemChecked( stype, TRUE );
3932 else if ( sortFilesBy == (int)QDir::Time )
3933 m2.setItemChecked( sdate, TRUE );
3934 else if ( sortFilesBy == (int)QDir::Unsorted )
3935 m2.setItemChecked( sunsorted, TRUE );
3937 m.insertItem( tr( "Sort" ), &m2 );
3939 m.insertSeparator();
3941 int hidden = m.insertItem( tr( "Show &hidden files" ) );
3942 m.setItemChecked( hidden, bShowHiddenFiles );
3947 if ( res == reload )
3949 else if ( res == hidden )
3951 else if ( res == sname )
3952 action = PA_SortName;
3953 // else if ( res == stype )
3954 // action = PA_SortType;
3955 else if ( res == sdate )
3956 action = PA_SortDate;
3957 else if ( res == ssize )
3958 action = PA_SortSize;
3959 else if ( res == sunsorted )
3960 action = PA_SortUnsorted;
3965 void QFileDialogP::deleteFile( const QString &filename )
3967 if ( filename.isEmpty() )
3970 QUrlInfo fi( d->url, QFileDialogPrivate::encodeFileName( filename ) );
3971 QString t = tr( "the file" );
3973 t = tr( "the directory" );
3974 if ( fi.isSymLink() )
3975 t = tr( "the symlink" );
3977 if ( QMessageBox::warning( this,
3978 tr( "Delete %1" ).arg( t ),
3979 tr( "<qt>Are you sure you wish to delete %1 \"%2\"?</qt>" )
3980 .arg( t ).arg(filename),
3981 tr( "&Yes" ), tr( "&No" ), QString::null, 1 ) == 0 )
3982 d->url.remove( QFileDialogPrivate::encodeFileName( filename ) );
3986 void QFileDialogP::fileSelected( int )
3991 void QFileDialogP::fileHighlighted( int )
3996 void QFileDialogP::dirSelected( int )
4001 void QFileDialogP::pathSelected( int )
4007 void QFileDialogP::cdUpClicked()
4009 QString oldName = nameEdit->text();
4010 setUrl( QUrlOperator( d->url, ".." ) );
4011 if ( !oldName.isEmpty() )
4012 nameEdit->setText( oldName );
4015 void QFileDialogP::newFolderClicked()
4017 QString foldername( tr( "New Folder 1" ) );
4020 QListViewItemIterator it( files );
4021 for ( ; it.current(); ++it )
4022 if ( it.current()->text( 0 ).contains( tr( "New Folder" ) ) )
4023 lst.append( it.current()->text( 0 ) );
4025 if ( !lst.count() == 0 )
4026 while ( lst.contains( foldername ) )
4027 foldername = tr( "New Folder %1" ).arg( ++i );
4029 d->url.mkdir( foldername );
4032 void QFileDialogP::createdDirectory( const QUrlInfo &info, QNetworkOperation * )
4035 if ( d->moreFiles->isVisible() ) {
4036 for ( uint i = 0; i < d->moreFiles->count(); ++i ) {
4037 if ( d->moreFiles->text( i ) == info.name() ) {
4038 d->moreFiles->setCurrentItem( i );
4039 d->moreFiles->startRename( FALSE );
4044 QListViewItem *item = files->firstChild();
4046 if ( item->text( 0 ) == info.name() ) {
4047 files->setSelected( item, TRUE );
4048 files->setCurrentItem( item );
4049 files->startRename( FALSE );
4052 item = item->nextSibling();
4059 This is a convenience static function that will return an existing directory
4060 selected by the user.
4063 QString s = QFileDialogP::getExistingDirectory(
4066 "get existing directory"
4067 "Choose a directory",
4071 This function creates a modal file dialog called \a name, with
4072 parent, \a parent. If parent is not 0, the dialog will be shown
4073 centered over the parent.
4075 The dialog's working directory is set to \a dir, and the caption is
4076 set to \a caption. Either of these may be QString::null in which case
4077 the current directory and a default caption will be used respectively.
4079 If \a dirOnly is TRUE, then only directories will be shown in
4080 the file dialog; otherwise both directories and files will be shown.
4082 Under Unix/X11, the normal behavior of the file dialog is to resolve
4083 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp,
4084 the file dialog will change to /var/tmp after entering /usr/tmp.
4085 If \a resolveSymlinks is FALSE, the file dialog will treat
4086 symlinks as regular directories.
4088 \sa getOpenFileName(), getOpenFileNames(), getSaveFileName()
4091 QString QFileDialogP::getExistingDirectory( const QString & dir,
4094 const QString& caption,
4096 bool resolveSymlinks)
4098 bool save_qt_resolve_symlinks = qt_resolve_symlinks;
4099 qt_resolve_symlinks = resolveSymlinks;
4103 if ( workingDirectory )
4104 wd = *workingDirectory;
4106 #if defined(Q_WS_WIN)
4108 if ( !dir.isEmpty() ) {
4109 QUrlOperator u( dir );
4110 if ( QFileInfo( u.path() ).isDir() )
4113 initialDir = QString::null;
4114 if ( qApp->style().styleHint( QStyle::SH_GUIStyle ) == WindowsStyle && dirOnly )
4115 return winGetExistingDirectory( initialDir, parent, name, caption );
4117 #if defined(Q_WS_MAC)
4118 if( ( qApp->style().inherits(QMAC_DEFAULT_STYLE) ) )
4119 return macGetOpenFileNames("", 0,
4120 parent, name, caption, FALSE, TRUE).first();
4123 QFileDialogP *dialog = new QFileDialogP( parent, name ? name : "qt_filedlg_ged", TRUE );
4124 #ifndef QT_NO_WIDGET_TOPEXTRA
4125 if ( !caption.isNull() )
4126 dialog->setCaption( caption );
4128 dialog->setCaption( QFileDialogP::tr("Find Directory") );
4131 dialog->setMode( dirOnly ? DirectoryOnly : Directory );
4133 dialog->d->types->clear();
4134 dialog->d->types->insertItem( QFileDialogP::tr("Directories") );
4135 dialog->d->types->setEnabled( FALSE );
4137 QString dir_( dir );
4138 dir_ = dir_.simplifyWhiteSpace();
4139 if ( dir_.isEmpty() && !wd.isEmpty() )
4141 QUrlOperator u( dir_ );
4142 if ( u.isLocalFile() ) {
4143 if ( !dir_.isEmpty() ) {
4144 QFileInfo f( u.path() );
4147 dialog->setDir( dir_ );
4150 } else if ( !wd.isEmpty() ) {
4152 QFileInfo f( tempUrl.path() );
4154 dialog->setDir( wd );
4157 QString theDir = dir_;
4158 if ( theDir.isEmpty() ) {
4159 theDir = QDir::currentDirPath();
4160 } if ( !theDir.isEmpty() ) {
4161 QUrl tempUrl( theDir );
4162 QFileInfo f( tempUrl.path() );
4165 dialog->setDir( theDir );
4170 dialog->setUrl( dir_ );
4174 dialog->setSelection( dialog->d->url.toString() );
4176 if ( dialog->exec() == QDialog::Accepted ) {
4177 result = dialog->selectedFile();
4182 if ( !result.isEmpty() && result.right( 1 ) != "/" )
4185 qt_resolve_symlinks = save_qt_resolve_symlinks;
4192 \property QFileDialogP::mode
4193 \brief the file dialog's mode
4195 The default mode is \c ExistingFile.
4198 void QFileDialogP::setMode( Mode newMode )
4200 if ( d->mode != newMode ) {
4202 QString sel = d->currentFileName;
4203 if ( isDirectoryMode( newMode ) ) {
4204 files->setMultiSelection( FALSE );
4205 d->moreFiles->setMultiSelection( FALSE );
4207 sel = QString::fromLatin1(".");
4208 d->types->setEnabled( FALSE );
4209 } else if ( newMode == ExistingFiles ) {
4210 files->setSelectionMode( QListView::Extended );
4211 d->moreFiles->setSelectionMode( QListBox::Extended );
4212 d->types->setEnabled( TRUE );
4214 files->setMultiSelection( FALSE );
4215 d->moreFiles->setMultiSelection( FALSE );
4216 d->types->setEnabled( TRUE );
4219 QUrlInfo f( d->url, "." );
4220 trySetSelection( f.isDir(), d->url, FALSE );
4224 bool changeFilters = FALSE;
4225 if ( mode() == AnyFile ) {
4227 d->fileL->setText( tr("File &name:") );
4228 if ( d->types->count() == 1 ) {
4229 d->types->setCurrentItem( 0 );
4230 if ( d->types->currentText() == "Directories" ) {
4231 changeFilters = TRUE;
4235 else if ( mode() == Directory || mode() == DirectoryOnly ) {
4237 d->fileL->setText( tr("Directory:") );
4239 d->types->insertItem( tr("Directories") );
4243 d->fileL->setText( tr("File &name:") );
4244 if ( d->types->count() == 1 ) {
4245 d->types->setCurrentItem( 0 );
4246 if ( d->types->currentText() == "Directories" ) {
4247 changeFilters = TRUE;
4252 if ( changeFilters ) {
4254 d->types->insertItem( tr("All Files (*)") );
4257 okB->setText( okt );
4260 QFileDialogP::Mode QFileDialogP::mode() const
4268 void QFileDialogP::done( int i )
4270 if ( i == QDialog::Accepted && (d->mode == ExistingFile || d->mode == ExistingFiles) ) {
4271 QStringList selection = selectedFiles();
4272 for ( uint f = 0; f < selection.count(); f++ ) {
4273 QString file = selection[f];
4274 if ( file.isNull() )
4276 if ( d->url.isLocalFile() && !QFile::exists( file ) ) {
4277 QMessageBox::information( this, tr("Error"), tr("%1\nFile not found.\nCheck path and filename.").arg( file ) );
4286 \property QFileDialogP::viewMode
4288 \brief the file dialog's view mode
4290 If you set the view mode to be \e Detail (the default), then you
4291 will see the file's details, such as the size of the file and the
4292 date the file was last modified in addition to the file's name.
4294 If you set the view mode to be \e List, then you will just
4295 see a list of the files and folders.
4297 See \l QFileDialogP::ViewMode
4301 QFileDialogP::ViewMode QFileDialogP::viewMode() const
4303 if ( detailViewMode )
4309 void QFileDialogP::setViewMode( ViewMode m )
4311 if ( m == Detail ) {
4312 detailViewMode = TRUE;
4313 d->stack->raiseWidget( files );
4314 d->detailView->setOn( TRUE );
4315 d->mcView->setOn( FALSE );
4316 } else if ( m == List ) {
4317 detailViewMode = FALSE;
4318 d->stack->raiseWidget( d->moreFiles );
4319 d->detailView->setOn( FALSE );
4320 d->mcView->setOn( TRUE );
4326 \property QFileDialogP::previewMode
4328 \brief the preview mode for the file dialog
4330 If you set the mode to be a mode other than \e NoPreview, you must
4331 use setInfoPreview() or setContentsPreview() to set the dialog's
4332 preview widget to your preview widget and enable the preview
4333 widget(s) with setInfoPreviewEnabled() or
4334 setContentsPreviewEnabled().
4336 \sa infoPreview, contentsPreview, viewMode
4339 void QFileDialogP::setPreviewMode( PreviewMode m )
4341 if ( m == NoPreview ) {
4342 d->previewInfo->setOn( FALSE );
4343 d->previewContents->setOn( FALSE );
4344 } else if ( m == Info && d->infoPreview ) {
4345 d->previewInfo->setOn( TRUE );
4346 d->previewContents->setOn( FALSE );
4347 changeMode( d->modeButtons->id( d->previewInfo ) );
4348 } else if ( m == Contents && d->contentsPreview ) {
4349 d->previewInfo->setOn( FALSE );
4350 d->previewContents->setOn( TRUE );
4351 changeMode( d->modeButtons->id( d->previewContents ) );
4354 QFileDialogP::PreviewMode QFileDialogP::previewMode() const
4356 if ( d->infoPreview && d->previewInfo->isVisible() )
4358 else if ( d->contentsPreview && d->previewContents->isVisible() )
4366 Adds the specified widgets to the bottom of the file dialog. The
4367 label \a l is placed underneath the "file name" and the "file types"
4368 labels. The widget \a w is placed underneath the file types combobox.
4369 The button \a b is placed underneath the Cancel pushbutton.
4372 MyFileDialog::MyFileDialog( QWidget* parent, const char* name ) :
4373 QFileDialogP( parent, name )
4375 QLabel* label = new QLabel( "Added widgets", this );
4376 QLineEdit* lineedit = new QLineEdit( this );
4377 QToolButton* toolbutton = new QToolButton( this );
4379 addWidgets( label, lineedit, toolbutton );
4383 If you don't want to have one of the widgets added, pass 0 in that
4386 Every time you call this function, a new row of widgets will be added
4387 to the bottom of the file dialog.
4389 \sa addToolButton(), addLeftWidget(), addRightWidget()
4392 void QFileDialogP::addWidgets( QLabel * l, QWidget * w, QPushButton * b )
4394 if ( !l && !w && !b )
4397 d->geometryDirty = TRUE;
4399 QHBoxLayout *lay = new QHBoxLayout();
4400 d->extraWidgetsLayouts.append( lay );
4401 d->topLevelLayout->addLayout( lay );
4404 l = new QLabel( this, "qt_intern_lbl" );
4405 d->extraLabels.append( l );
4406 lay->addWidget( l );
4409 w = new QWidget( this, "qt_intern_widget" );
4410 d->extraWidgets.append( w );
4411 lay->addWidget( w );
4412 lay->addSpacing( 15 );
4415 d->extraButtons.append( b );
4416 lay->addWidget( b );
4418 QWidget *wid = new QWidget( this, "qt_extrabuttons_widget" );
4419 d->extraButtons.append( wid );
4420 lay->addWidget( wid );
4427 Adds the tool button \a b to the row of tool buttons at the top of the
4428 file dialog. The button is appended to the right of
4429 this row. If \a separator is TRUE, a small space is inserted between the
4430 last button of the row and the new button \a b.
4432 \sa addWidgets(), addLeftWidget(), addRightWidget()
4435 void QFileDialogP::addToolButton( QButton *b, bool separator )
4437 if ( !b || !d->buttonLayout )
4440 d->geometryDirty = TRUE;
4442 d->toolButtons.append( b );
4444 d->buttonLayout->addSpacing( 8 );
4445 d->buttonLayout->addWidget( b );
4451 Adds the widget \a w to the left-hand side of the file dialog.
4453 \sa addRightWidget(), addWidgets(), addToolButton()
4456 void QFileDialogP::addLeftWidget( QWidget *w )
4460 d->geometryDirty = TRUE;
4462 d->leftLayout->addWidget( w );
4463 d->leftLayout->addSpacing( 5 );
4469 Adds the widget \a w to the right-hand side of the file dialog.
4471 \sa addLeftWidget(), addWidgets(), addToolButton()
4474 void QFileDialogP::addRightWidget( QWidget *w )
4478 d->geometryDirty = TRUE;
4480 d->rightLayout->addSpacing( 5 );
4481 d->rightLayout->addWidget( w );
4488 void QFileDialogP::keyPressEvent( QKeyEvent * ke )
4490 if ( !d->ignoreNextKeyPress &&
4491 ke && ( ke->key() == Key_Enter ||
4492 ke->key() == Key_Return ) ) {
4494 if ( d->paths->hasFocus() ) {
4496 if ( d->url == QUrl(d->paths->currentText()) )
4497 nameEdit->setFocus();
4498 } else if ( d->types->hasFocus() ) {
4500 // ### is there a suitable condition for this? only valid
4502 nameEdit->setFocus();
4503 } else if ( nameEdit->hasFocus() ) {
4504 if ( d->currentFileName.isNull() ) {
4505 // maybe change directory
4506 QUrlInfo i( d->url, nameEdit->text() );
4508 nameEdit->setText( QString::fromLatin1("") );
4509 setDir( QUrlOperator( d->url, QFileDialogPrivate::encodeFileName(i.name()) ) );
4512 } else if ( mode() == ExistingFiles ) {
4513 QUrlInfo i( d->url, nameEdit->text() );
4515 QListViewItem * i = files->firstChild();
4516 while ( i && nameEdit->text() != i->text( 0 ) )
4517 i = i->nextSibling();
4519 files->setSelected( i, TRUE );
4521 ke->accept(); // strangely, means to ignore that event
4524 } else if ( files->hasFocus() || d->moreFiles->hasFocus() ) {
4527 } else if ( ke->key() == Key_Escape ) {
4531 d->ignoreNextKeyPress = FALSE;
4533 if ( !ke->isAccepted() ) {
4534 QDialog::keyPressEvent( ke );
4539 /*! \class QFileIconProviderP qfiledialog.h
4541 \brief The QFileIconProviderP class provides icons for QFileDialogP to
4546 By default QFileIconProviderP is not used, but any application or
4547 library can subclass it, reimplement pixmap() to return a suitable
4548 icon, and make all QFileDialogP objects use it by calling the static
4549 function QFileDialogP::setIconProvider().
4551 It is advisable to make all the icons that QFileIconProviderP returns be
4552 the same size or at least the same width. This makes the list view
4559 /*! Constructs an empty file icon provider called \a name, with the
4563 QFileIconProviderP::QFileIconProviderP( QObject * parent, const char* name )
4564 : QObject( parent, name )
4566 // nothing necessary
4571 Returns a pointer to a pixmap that should be used to
4572 signify the file with the information \a info.
4574 If pixmap() returns 0, QFileDialogP draws the default pixmap.
4576 The default implementation returns particular icons for files, directories,
4577 link-files and link-directories. It returns a blank "icon" for other types.
4579 If you return a pixmap here, it should measure 16x16 pixels.
4582 const QPixmap * QFileIconProviderP::pixmap( const QFileInfo & info )
4584 if ( info.isSymLink() ) {
4585 if ( info.isFile() )
4586 return symLinkFileIcon;
4588 return symLinkDirIcon;
4589 } else if ( info.isDir() ) {
4590 return closedFolderIcon;
4591 } else if ( info.isFile() ) {
4594 return fifteenTransparentPixels;
4599 Sets the QFileIconProviderP used by the file dialog to \a provider.
4601 The default is that there is no QFileIconProviderP and QFileDialogP
4602 just draws a folder icon next to each directory and nothing next
4605 \sa QFileIconProviderP, iconProvider()
4608 void QFileDialogP::setIconProvider( QFileIconProviderP * provider )
4610 fileIconProvider = provider;
4615 Returns a pointer to the icon provider currently set on the file dialog.
4616 By default there is no icon provider, and this function returns 0.
4618 \sa setIconProvider(), QFileIconProviderP
4621 QFileIconProviderP * QFileDialogP::iconProvider()
4623 return fileIconProvider;
4627 #if defined(Q_WS_WIN)
4629 static QString getWindowsRegString( HKEY key, const char *subKey )
4633 DWORD bsz = sizeof(buf);
4635 int r = RegQueryValueEx( key, (LPCTSTR)qt_winTchar(subKey, TRUE), 0, 0, (LPBYTE)buf, &bsz );
4637 int r = RegQueryValueExA( key, subKey, 0, 0, (LPBYTE)buf, &bsz );
4639 if ( r == ERROR_SUCCESS ) {
4641 } else if ( r == ERROR_MORE_DATA ) {
4642 char *ptr = new char[bsz+1];
4644 r = RegQueryValueEx( key, (LPCTSTR)qt_winTchar(subKey, TRUE), 0, 0, (LPBYTE)ptr, &bsz );
4646 r = RegQueryValueExA( key, subKey, 0, 0, (LPBYTE)ptr, &bsz );
4648 if ( r == ERROR_SUCCESS )
4655 static void initPixmap( QPixmap &pm )
4657 pm.fill( Qt::white );
4660 QWindowsIconProvider::QWindowsIconProvider( QObject *parent, const char *name )
4661 : QFileIconProviderP( parent, name )
4663 pixw = GetSystemMetrics( SM_CXSMICON );
4664 pixh = GetSystemMetrics( SM_CYSMICON );
4673 // ---------- get default folder pixmap
4674 r = RegOpenKeyEx( HKEY_CLASSES_ROOT,
4675 L"folder\\DefaultIcon",
4678 // ---------- get default folder pixmap
4679 r = RegOpenKeyExA( HKEY_CLASSES_ROOT,
4680 "folder\\DefaultIcon",
4683 if ( r == ERROR_SUCCESS ) {
4684 s = getWindowsRegString( k, 0 );
4687 QStringList lst = QStringList::split( ",", s );
4690 res = (UINT)ExtractIconEx( (LPCTSTR)qt_winTchar( lst[ 0 ].simplifyWhiteSpace(), TRUE ),
4691 lst[ 1 ].simplifyWhiteSpace().toInt(),
4694 res = ExtractIconExA( lst[ 0 ].simplifyWhiteSpace().latin1(),
4695 lst[ 1 ].simplifyWhiteSpace().toInt(),
4700 defaultFolder.resize( pixw, pixh );
4701 initPixmap( defaultFolder );
4702 QPainter p( &defaultFolder );
4703 DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, NULL, DI_NORMAL );
4705 defaultFolder.setMask( defaultFolder.createHeuristicMask() );
4706 *closedFolderIcon = defaultFolder;
4709 defaultFolder = *closedFolderIcon;
4716 //------------------------------- get default file pixmap
4717 res = (UINT)ExtractIconEx( L"shell32.dll",
4720 //------------------------------- get default file pixmap
4721 res = ExtractIconExA( "shell32.dll",
4726 defaultFile.resize( pixw, pixh );
4727 initPixmap( defaultFile );
4728 QPainter p( &defaultFile );
4729 DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, NULL, DI_NORMAL );
4731 defaultFile.setMask( defaultFile.createHeuristicMask() );
4732 *fileIcon = defaultFile;
4735 defaultFile = *fileIcon;
4739 //------------------------------- get default exe pixmap
4740 res = (UINT)ExtractIconEx( L"shell32.dll",
4743 //------------------------------- get default exe pixmap
4744 res = ExtractIconExA( "shell32.dll",
4749 defaultExe.resize( pixw, pixh );
4750 initPixmap( defaultExe );
4751 QPainter p( &defaultExe );
4752 DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, NULL, DI_NORMAL );
4754 defaultExe.setMask( defaultExe.createHeuristicMask() );
4757 defaultExe = *fileIcon;
4761 QWindowsIconProvider::~QWindowsIconProvider()
4763 if ( this == fileIconProvider )
4764 fileIconProvider = 0;
4767 const QPixmap * QWindowsIconProvider::pixmap( const QFileInfo &fi )
4769 QString ext = fi.extension().upper();
4772 QMap< QString, QPixmap >::Iterator it;
4775 return &defaultFolder;
4776 } else if ( ext.lower() != ".exe" ) {
4777 it = cache.find( key );
4778 if ( it != cache.end() )
4783 int r = RegOpenKeyEx( HKEY_CLASSES_ROOT,
4784 (LPCTSTR)qt_winTchar(ext, TRUE),
4787 int r = RegOpenKeyExA( HKEY_CLASSES_ROOT,
4792 if ( r == ERROR_SUCCESS ) {
4793 s = getWindowsRegString( k, 0 );
4795 cache[ key ] = defaultFile;
4797 return &defaultFile;
4802 r = RegOpenKeyEx( HKEY_CLASSES_ROOT,
4803 (LPCTSTR)qt_winTchar( s + "\\DefaultIcon", TRUE ),
4806 r = RegOpenKeyExA( HKEY_CLASSES_ROOT,
4807 QString( s + "\\DefaultIcon" ).latin1() ,
4810 if ( r == ERROR_SUCCESS ) {
4811 s = getWindowsRegString( k2, 0 );
4813 cache[ key ] = defaultFile;
4815 return &defaultFile;
4819 QStringList lst = QStringList::split( ",", s );
4823 QString filepath = lst[ 0 ].stripWhiteSpace();
4824 if ( filepath.find("%1") != -1 ) {
4825 filepath = filepath.arg( fi.filePath() );
4826 if ( ext.lower() == ".dll" ) {
4833 res = (UINT)ExtractIconEx( (LPCTSTR)qt_winTchar(filepath, TRUE),
4834 lst[ 1 ].stripWhiteSpace().toInt(),
4837 res = ExtractIconExA( filepath.latin1(),
4838 lst[ 1 ].stripWhiteSpace().toInt(),
4843 pix.resize( pixw, pixh );
4846 DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, NULL, DI_NORMAL );
4848 pix.setMask( pix.createHeuristicMask() );
4860 res = (UINT)ExtractIconEx( (LPCTSTR)qt_winTchar(fi.absFilePath(), TRUE),
4864 res = ExtractIconExA( fi.absFilePath().latin1(),
4873 res = (UINT)ExtractIconEx( (LPCTSTR)qt_winTchar(fi.absFilePath(), TRUE),
4877 res = ExtractIconExA( fi.absFilePath().latin1(),
4884 pix.resize( pixw, pixh );
4887 DrawIconEx( p.handle(), 0, 0, si, pixw, pixh, 0, NULL, DI_NORMAL );
4889 pix.setMask( pix.createHeuristicMask() );
4908 bool QFileDialogP::eventFilter( QObject * o, QEvent * e )
4910 if ( e->type() == QEvent::KeyPress && ( (QKeyEvent*)e )->key() == Key_F5 ) {
4912 ((QKeyEvent *)e)->accept();
4914 } else if ( e->type() == QEvent::KeyPress && ( (QKeyEvent*)e )->key() == Key_F2 &&
4915 ( o == files || o == files->viewport() ) ) {
4916 if ( files->isVisible() && files->currentItem() ) {
4917 if ( mode() != QFileDialogP::ExistingFiles &&
4918 QUrlInfo( d->url, "." ).isWritable() && files->currentItem()->text( 0 ) != ".." ) {
4919 files->renameItem = files->currentItem();
4920 files->startRename( TRUE );
4923 ((QKeyEvent *)e)->accept();
4925 } else if ( e->type() == QEvent::KeyPress && ( (QKeyEvent*)e )->key() == Key_F2 &&
4926 ( o == d->moreFiles || o == d->moreFiles->viewport() ) ) {
4927 if ( d->moreFiles->isVisible() && d->moreFiles->currentItem() != -1 ) {
4928 if ( mode() != QFileDialogP::ExistingFiles &&
4929 QUrlInfo( d->url, "." ).isWritable() &&
4930 d->moreFiles->item( d->moreFiles->currentItem() )->text() != ".." ) {
4931 d->moreFiles->renameItem = d->moreFiles->item( d->moreFiles->currentItem() );
4932 d->moreFiles->startRename( TRUE );
4935 ((QKeyEvent *)e)->accept();
4937 } else if ( e->type() == QEvent::KeyPress && d->moreFiles->renaming ) {
4938 d->moreFiles->lined->setFocus();
4939 QApplication::sendEvent( d->moreFiles->lined, e );
4940 ((QKeyEvent *)e)->accept();
4942 } else if ( e->type() == QEvent::KeyPress && files->renaming ) {
4943 files->lined->setFocus();
4944 QApplication::sendEvent( files->lined, e );
4945 ((QKeyEvent *)e)->accept();
4947 } else if ( e->type() == QEvent::KeyPress &&
4948 ((QKeyEvent *)e)->key() == Key_Backspace &&
4950 o == d->moreFiles ||
4951 o == files->viewport() ||
4952 o == d->moreFiles->viewport() ) ) {
4954 ((QKeyEvent *)e)->accept();
4956 } else if ( e->type() == QEvent::KeyPress &&
4957 ((QKeyEvent *)e)->key() == Key_Delete &&
4959 o == files->viewport() ) ) {
4960 if ( files->currentItem() )
4961 deleteFile( files->currentItem()->text( 0 ) );
4962 ((QKeyEvent *)e)->accept();
4964 } else if ( e->type() == QEvent::KeyPress &&
4965 ((QKeyEvent *)e)->key() == Key_Delete &&
4966 ( o == d->moreFiles ||
4967 o == d->moreFiles->viewport() ) ) {
4968 int c = d->moreFiles->currentItem();
4970 deleteFile( d->moreFiles->item( c )->text() );
4971 ((QKeyEvent *)e)->accept();
4973 } else if ( o == files && e->type() == QEvent::FocusOut &&
4974 files->currentItem() && mode() != ExistingFiles ) {
4975 } else if ( o == files && e->type() == QEvent::KeyPress ) {
4976 QTimer::singleShot( 0, this, SLOT(fixupNameEdit()) );
4977 } else if ( o == nameEdit && e->type() == QEvent::KeyPress ) {
4978 if ( ( nameEdit->cursorPosition() == (int)nameEdit->text().length() || nameEdit->hasSelectedText() ) &&
4979 isprint(((QKeyEvent *)e)->ascii()) ) {
4980 #if defined(_WS_WIN_)
4981 QString nt( nameEdit->text().lower() );
4983 QString nt( nameEdit->text() );
4985 nt.truncate( nameEdit->cursorPosition() );
4986 nt += (char)(((QKeyEvent *)e)->ascii());
4987 QListViewItem * i = files->firstChild();
4988 #if defined(_WS_WIN_)
4989 while( i && i->text( 0 ).left(nt.length()).lower() != nt )
4991 while( i && i->text( 0 ).left(nt.length()) != nt )
4993 i = i->nextSibling();
4996 int cp = nameEdit->cursorPosition()+1;
4997 nameEdit->validateAndSet( nt, cp, cp, nt.length() );
5001 } else if ( o == nameEdit && e->type() == QEvent::FocusIn ) {
5003 } else if ( d->moreFiles->renaming && o != d->moreFiles->lined && e->type() == QEvent::FocusIn ) {
5004 d->moreFiles->lined->setFocus();
5006 } else if ( files->renaming && o != files->lined && e->type() == QEvent::FocusIn ) {
5007 files->lined->setFocus();
5009 } else if ( ( o == d->moreFiles || o == d->moreFiles->viewport() ) &&
5010 e->type() == QEvent::FocusIn ) {
5011 if ( o == d->moreFiles->viewport() && !d->moreFiles->viewport()->hasFocus() ||
5012 o == d->moreFiles && !d->moreFiles->hasFocus() )
5013 ((QWidget*)o)->setFocus();
5017 return QDialog::eventFilter( o, e );
5021 Sets the filters used in the file dialog to \a filters. Each group
5022 of filters must be separated by \c{;;} (\e two semi-colons).
5025 QString types("*.png;;*.xpm;;*.jpg");
5026 QFileDialogP fd = new QFileDialogP( this );
5027 fd->setFilters( types );
5033 void QFileDialogP::setFilters( const QString &filters )
5035 QStringList lst = makeFiltersList( filters );
5042 \a types must be a null-terminated list of strings.
5046 void QFileDialogP::setFilters( const char ** types )
5048 if ( !types || !*types )
5052 while( types && *types ) {
5053 d->types->insertItem( QString::fromLatin1(*types) );
5056 d->types->setCurrentItem( 0 );
5057 setFilter( d->types->text( 0 ) );
5061 /*! \overload void QFileDialogP::setFilters( const QStringList & )
5064 void QFileDialogP::setFilters( const QStringList & types )
5066 if ( types.count() < 1 )
5070 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it )
5071 d->types->insertItem( *it );
5072 d->types->setCurrentItem( 0 );
5073 setFilter( d->types->text( 0 ) );
5077 Adds the filter \a filter to the list of filters and makes it the
5081 QFileDialogP* fd = new QFileDialogP( this );
5082 fd->addFilter( "Images (*.png *.jpg *.xpm)" );
5086 In the above example, a file dialog is created, and the file filter "Images
5087 (*.png *.jpg *.xpm)" is added and is set as the current filter. The original
5088 filter, "All Files (*)", is still available.
5090 \sa setFilter(), setFilters()
5093 void QFileDialogP::addFilter( const QString &filter )
5095 if ( filter.isEmpty() )
5098 QRegExp r( QString::fromLatin1(qt_file_dialog_filter_reg_exp) );
5099 int index = r.search( f );
5102 for ( int i = 0; i < d->types->count(); ++i ) {
5103 QString f2( d->types->text( i ) );
5104 int index = r.search( f2 );
5108 d->types->setCurrentItem( i );
5114 d->types->insertItem( filter );
5115 d->types->setCurrentItem( d->types->count() - 1 );
5116 setFilter( d->types->text( d->types->count() - 1 ) );
5120 Since modeButtons is a top-level widget, it may be destroyed by the
5121 kernel at application exit. Notice if this happens to
5122 avoid double deletion.
5125 void QFileDialogP::modeButtonsDestroyed()
5133 This is a convenience static function that will return one or more
5134 existing files selected by the user.
5137 QStringList files = QFileDialogP::getOpenFileNames(
5138 "Images (*.png *.xpm *.jpg)",
5142 "Select one or more files to open" );
5145 This function creates a modal file dialog called \a name, with
5146 parent \a parent. If \a parent is not 0, the dialog will be shown
5147 centered over the parent.
5149 The file dialog's working directory will be set to \a dir. If \a
5150 dir includes a file name, the file will be selected. The filter
5151 is set to \a filter so that only those files which match the filter
5152 are shown. The filter selected is set to \a selectedFilter. The parameters
5153 \a dir, \a selectedFilter and \a filter may be QString::null.
5155 The dialog's caption is set to \a caption. If \a caption is not
5156 specified then a default caption will be used.
5158 Under Windows and Mac OS X, this static function will use the native
5159 file dialog and not a QFileDialogP, unless the style of the application
5160 is set to something other than the native style.
5162 Under Unix/X11, the normal behavior of the file dialog is to resolve
5163 and follow symlinks. For example, if /usr/tmp is a symlink to /var/tmp,
5164 the file dialog will change to /var/tmp after entering /usr/tmp.
5165 If \a resolveSymlinks is FALSE, the file dialog will treat
5166 symlinks as regular directories.
5168 Note that if you want to iterate over the list of files, you should
5169 iterate over a copy, e.g.
5171 QStringList list = files;
5172 QStringList::Iterator it = list.begin();
5173 while( it != list.end() ) {
5174 myProcessing( *it );
5179 \sa getOpenFileName(), getSaveFileName(), getExistingDirectory()
5182 QStringList QFileDialogP::getOpenFileNames( const QString & filter,
5186 const QString& caption,
5187 QString *selectedFilter,
5188 bool resolveSymlinks )
5190 bool save_qt_resolve_symlinks = qt_resolve_symlinks;
5191 qt_resolve_symlinks = resolveSymlinks;
5193 QStringList filters;
5194 if ( !filter.isEmpty() )
5195 filters = makeFiltersList( filter );
5199 if ( workingDirectory->isNull() )
5200 *workingDirectory = QDir::currentDirPath();
5202 if ( !dir.isEmpty() ) {
5203 // #### works only correct for local files
5204 QUrlOperator u( dir );
5205 if ( u.isLocalFile() && QFileInfo( u ).isDir() ) {
5206 *workingDirectory = dir;
5208 *workingDirectory = u.toString();
5212 #if defined(Q_WS_WIN)
5213 if ( qApp->style().styleHint( QStyle::SH_GUIStyle ) == WindowsStyle )
5214 return winGetOpenFileNames( filter, workingDirectory, parent, name, caption, selectedFilter );
5215 #elif defined(Q_WS_MAC)
5216 if( ( qApp->style().inherits(QMAC_DEFAULT_STYLE) ) )
5217 return macGetOpenFileNames(filter, workingDirectory, parent, name, caption );
5220 QFileDialogP *dlg = new QFileDialogP( *workingDirectory, QString::null, parent, name ? name : "qt_filedlg_gofns", TRUE );
5223 #ifndef QT_NO_WIDGET_TOPEXTRA
5224 if ( parent && parent->icon() && !parent->icon()->isNull() )
5225 dlg->setIcon( *parent->icon() );
5226 else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() )
5227 dlg->setIcon( *qApp->mainWidget()->icon() );
5230 dlg->setFilters( filters );
5231 if ( selectedFilter )
5232 dlg->setFilter( *selectedFilter );
5233 #ifndef QT_NO_WIDGET_TOPEXTRA
5234 if ( !caption.isNull() )
5235 dlg->setCaption( caption );
5237 dlg->setCaption( QFileDialogP::tr("Open") );
5239 dlg->setMode( QFileDialogP::ExistingFiles );
5242 if ( dlg->exec() == QDialog::Accepted ) {
5243 lst = dlg->selectedFiles();
5244 *workingDirectory = dlg->d->url;
5245 if ( selectedFilter )
5246 *selectedFilter = dlg->selectedFilter();
5250 qt_resolve_symlinks = save_qt_resolve_symlinks;
5255 /*! Updates the line edit to match the speed-key usage in QListView. */
5257 void QFileDialogP::fixupNameEdit()
5259 if ( files->currentItem() && d->mode != ExistingFiles ) {
5260 if ( ( (QFileDialogPrivate::File*)files->currentItem() )->info.isFile() )
5261 nameEdit->setText( files->currentItem()->text( 0 ) );
5266 Returns the URL of the current working directory in the file dialog.
5271 QUrl QFileDialogP::url() const
5276 static bool isRoot( const QUrl &u )
5278 #if defined(Q_OS_MAC9)
5279 QString p = QDir::convertSeparators(u.path());
5280 if(p.contains(':') == 1)
5282 #elif defined(Q_OS_UNIX)
5283 if ( u.path() == "/" )
5285 #elif defined(Q_OS_WIN32)
5286 QString p = u.path();
5287 if ( p.length() == 3 &&
5288 p.right( 2 ) == ":/" )
5290 if ( p[ 0 ] == '/' && p[ 1 ] == '/' ) {
5291 int slashes = p.contains( '/' );
5294 if ( slashes == 4 && p[ (int)p.length() - 1 ] == '/' )
5298 #if defined(Q_CC_GNU)
5299 #warning "case not covered.."
5303 if ( !u.isLocalFile() && u.path() == "/" )
5309 void QFileDialogP::urlStart( QNetworkOperation *op )
5314 if ( op->operation() == QNetworkProtocol::OpListChildren ) {
5315 if ( isRoot( d->url ) )
5316 d->cdToParent->setEnabled( FALSE );
5318 d->cdToParent->setEnabled( TRUE );
5319 d->mimeTypeTimer->stop();
5320 d->sortedList.clear();
5321 d->pendingItems.clear();
5322 d->moreFiles->clearSelection();
5323 files->clearSelection();
5324 d->moreFiles->clear();
5326 files->setSorting( -1 );
5328 QString s = d->url.toString( FALSE, FALSE );
5330 for ( int i = 0; i < d->paths->count(); ++i ) {
5331 #if defined(Q_WS_WIN)
5332 if ( d->paths->text( i ).lower() == s.lower() ) {
5334 if ( d->paths->text( i ) == s ) {
5337 d->paths->setCurrentItem( i );
5342 d->paths->insertItem( *openFolderIcon, s, -1 );
5343 d->paths->setCurrentItem( d->paths->count() - 1 );
5346 d->hadDotDot = FALSE;
5348 if ( d->goBack && d->history.last() != d->url.toString() ) {
5349 d->history.append( d->url.toString() );
5350 if ( d->history.count() > 1 )
5351 d->goBack->setEnabled( TRUE );
5356 void QFileDialogP::urlFinished( QNetworkOperation *op )
5361 if ( op->operation() == QNetworkProtocol::OpListChildren ) {
5362 if ( QApplication::overrideCursor() )
5363 QApplication::restoreOverrideCursor();
5365 if ( op->state() == QNetworkProtocol::StFailed ) {
5366 if ( d->paths->hasFocus() )
5367 d->ignoreNextKeyPress = TRUE;
5369 if ( d->progressDia ) {
5370 d->ignoreStop = TRUE;
5371 d->progressDia->close();
5372 delete d->progressDia;
5376 QMessageBox::critical( this, tr( "Error" ), op->protocolDetail() );
5378 int ecode = op->errorCode();
5379 if ( ecode == QNetworkProtocol::ErrListChildren || ecode == QNetworkProtocol::ErrParse ||
5380 ecode == QNetworkProtocol::ErrUnknownProtocol || ecode == QNetworkProtocol::ErrLoginIncorrect ||
5381 ecode == QNetworkProtocol::ErrValid || ecode == QNetworkProtocol::ErrHostNotFound ||
5382 ecode == QNetworkProtocol::ErrFileNotExisting ) {
5383 if (d->url != d->oldUrl) {
5384 QString nf = d->url.nameFilter();
5386 d->url.setNameFilter( nf );
5390 // another error happened, no need to go back to last dir
5392 } else if ( op->operation() == QNetworkProtocol::OpListChildren &&
5393 op == d->currListChildren ) {
5394 if ( !d->hadDotDot && !isRoot( d->url ) ) {
5396 #if defined(Q_WS_WIN)
5397 if ( d->url.path().left( 2 ) == "//" )
5401 QUrlInfo ui( d->url, ".." );
5404 ui.setFile( FALSE );
5405 ui.setSymLink( FALSE );
5407 QValueList<QUrlInfo> lst;
5409 insertEntry( lst, 0 );
5413 } else if ( op->operation() == QNetworkProtocol::OpGet ) {
5414 } else if ( op->operation() == QNetworkProtocol::OpPut ) {
5416 if ( d->progressDia ) {
5417 d->ignoreStop = TRUE;
5418 d->progressDia->close();
5420 delete d->progressDia;
5425 void QFileDialogP::dataTransferProgress( int bytesDone, int bytesTotal, QNetworkOperation *op )
5431 QUrl u( op->arg( 0 ) );
5432 if ( u.isLocalFile() ) {
5435 label = QString( "%1 (on %2)" );
5436 label = label.arg( u.path() ).arg( u.host() );
5439 if ( !d->progressDia ) {
5440 if ( bytesDone < bytesTotal) {
5441 d->ignoreStop = FALSE;
5442 d->progressDia = new QFDProgressDialog( this, label, bytesTotal );
5443 connect( d->progressDia, SIGNAL( cancelled() ),
5444 this, SLOT( stopCopy() ) );
5445 d->progressDia->show();
5450 if ( d->progressDia ) {
5451 if ( op->operation() == QNetworkProtocol::OpGet ) {
5452 if ( d->progressDia ) {
5453 d->progressDia->setReadProgress( bytesDone );
5455 } else if ( op->operation() == QNetworkProtocol::OpPut ) {
5456 if ( d->progressDia ) {
5457 d->progressDia->setWriteLabel( label );
5458 d->progressDia->setWriteProgress( bytesDone );
5466 void QFileDialogP::insertEntry( const QValueList<QUrlInfo> &lst, QNetworkOperation *op )
5468 if ( op && op->operation() == QNetworkProtocol::OpListChildren &&
5469 op != d->currListChildren )
5471 QValueList<QUrlInfo>::ConstIterator it = lst.begin();
5472 for ( ; it != lst.end(); ++it ) {
5473 const QUrlInfo &inf = *it;
5474 if ( d->mode == DirectoryOnly && !inf.isDir() )
5476 if ( inf.name() == ".." ) {
5477 d->hadDotDot = TRUE;
5478 if ( isRoot( d->url ) )
5480 #if defined(Q_WS_WIN)
5481 if ( d->url.path().left( 2 ) == "//" )
5484 } else if ( inf.name() == "." )
5487 #if defined(Q_WS_WIN)
5488 if ( !bShowHiddenFiles ) {
5489 if ( d->url.isLocalFile() ) {
5490 QString file = d->url.path() + inf.name();
5491 #if defined(UNICODE)
5492 if ( qWinVersion() & Qt::WV_NT_based ) {
5493 if ( GetFileAttributesW( (TCHAR*)qt_winTchar( file, TRUE ) ) & FILE_ATTRIBUTE_HIDDEN )
5499 if ( GetFileAttributesA( file.local8Bit() ) & FILE_ATTRIBUTE_HIDDEN )
5503 if ( inf.name() != ".." && inf.name()[0] == QChar('.') )
5508 if ( !bShowHiddenFiles && inf.name() != ".." ) {
5509 if ( inf.name()[ 0 ] == QChar( '.' ) )
5514 if ( !d->url.isLocalFile() ) {
5515 QFileDialogPrivate::File * i = 0;
5516 QFileDialogPrivate::MCItem *i2 = 0;
5517 i = new QFileDialogPrivate::File( d, &inf, files );
5518 i2 = new QFileDialogPrivate::MCItem( d->moreFiles, i );
5520 if ( d->mode == ExistingFiles && inf.isDir() ||
5521 ( isDirectoryMode( d->mode ) && inf.isFile() ) ) {
5522 i->setSelectable( FALSE );
5523 i2->setSelectable( FALSE );
5529 d->sortedList.append( new QUrlInfo( inf ) );
5533 void QFileDialogP::removeEntry( QNetworkOperation *op )
5539 QListViewItemIterator it( files );
5540 bool ok1 = FALSE, ok2 = FALSE;
5541 for ( i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next() ) {
5542 if ( ( (QFileDialogPrivate::File*)it.current() )->info.name() == op->arg( 0 ) ) {
5543 d->pendingItems.removeRef( (QFileDialogPrivate::File*)it.current() );
5544 delete ( (QFileDialogPrivate::File*)it.current() )->i;
5545 delete it.current();
5548 if ( i && i->name() == op->arg( 0 ) ) {
5549 d->sortedList.removeRef( i );
5550 i = d->sortedList.prev();
5558 void QFileDialogP::itemChanged( QNetworkOperation *op )
5564 QListViewItemIterator it1( files );
5565 bool ok1 = FALSE, ok2 = FALSE;
5566 // first check whether the new file replaces an existing file.
5567 for ( i = d->sortedList.first(); it1.current(); ++it1, i = d->sortedList.next() ) {
5568 if ( ( (QFileDialogPrivate::File*)it1.current() )->info.name() == op->arg( 1 ) ) {
5569 delete ( (QFileDialogPrivate::File*)it1.current() )->i;
5570 delete it1.current();
5573 if ( i && i->name() == op->arg( 1 ) ) {
5574 d->sortedList.removeRef( i );
5575 i = d->sortedList.prev();
5583 QListViewItemIterator it( files );
5586 for ( i = d->sortedList.first(); it.current(); ++it, i = d->sortedList.next() ) {
5587 if ( ( (QFileDialogPrivate::File*)it.current() )->info.name() == op->arg( 0 ) ) {
5588 ( (QFileDialogPrivate::File*)it.current() )->info.setName( op->arg( 1 ) );
5591 if ( i && i->name() == op->arg( 0 ) ) {
5592 i->setName( op->arg( 1 ) );
5603 \property QFileDialogP::infoPreview
5605 \brief whether the file dialog can provide preview information about
5606 the currently selected file
5608 The default is FALSE.
5610 bool QFileDialogP::isInfoPreviewEnabled() const
5612 return d->infoPreview;
5615 void QFileDialogP::setInfoPreviewEnabled( bool info )
5617 if ( info == d->infoPreview )
5619 d->geometryDirty = TRUE;
5620 d->infoPreview = info;
5626 \property QFileDialogP::contentsPreview
5628 \brief whether the file dialog can provide a contents preview of the
5629 currently selected file
5631 The default is FALSE.
5633 \sa setContentsPreview() setInfoPreviewEnabled()
5635 // ### improve the above documentation: how is the preview done, how can I add
5636 // support for customized preview, etc.
5638 bool QFileDialogP::isContentsPreviewEnabled() const
5640 return d->contentsPreview;
5643 void QFileDialogP::setContentsPreviewEnabled( bool contents )
5645 if ( contents == d->contentsPreview )
5647 d->geometryDirty = TRUE;
5648 d->contentsPreview = contents;
5654 Sets the widget to be used for displaying information about the file
5655 to the widget \a w and a preview of that information to the
5656 QFilePreviewP \a preview.
5658 Normally you would create a preview widget that derives from both QWidget and
5659 QFilePreviewP, so you should pass the same widget twice.
5662 class Preview : public QLabel, public QFilePreviewP
5665 Preview( QWidget *parent=0 ) : QLabel( parent ) {}
5667 void previewUrl( const QUrl &u )
5669 QString path = u.path();
5670 QPixmap pix( path );
5672 setText( "This is not a pixmap" );
5674 setText( "This is a pixmap" );
5680 int main( int argc, char** argv )
5682 Preview* p = new Preview;
5684 QFileDialogP* fd = new QFileDialogP( this );
5685 fd->setInfoPreviewEnabled( TRUE );
5686 fd->setInfoPreview( p, p );
5687 fd->setPreviewMode( QFileDialogP::Info );
5693 \sa setContentsPreview(), setInfoPreviewEnabled(), setPreviewMode()
5697 void QFileDialogP::setInfoPreview( QWidget *w, QFilePreviewP *preview )
5699 if ( !w || !preview )
5702 if ( d->infoPreviewWidget ) {
5703 d->preview->removeWidget( d->infoPreviewWidget );
5704 delete d->infoPreviewWidget;
5706 if ( d->infoPreviewer )
5707 delete d->infoPreviewer;
5708 d->infoPreviewWidget = w;
5709 d->infoPreviewer = preview;
5710 w->reparent( d->preview, 0, QPoint( 0, 0 ) );
5714 Sets the widget to be used for displaying the contents of the file
5715 to the widget \a w and a preview of those contents to the
5716 QFilePreviewP \a preview.
5718 Normally you would create a preview widget that derives from both QWidget and
5719 QFilePreviewP, so you should pass the same widget twice.
5722 class Preview : public QLabel, public QFilePreviewP
5725 Preview( QWidget *parent=0 ) : QLabel( parent ) {}
5727 void previewUrl( const QUrl &u )
5729 QString path = u.path();
5730 QPixmap pix( path );
5732 setText( "This is not a pixmap" );
5740 int main( int argc, char** argv )
5742 Preview* p = new Preview;
5744 QFileDialogP* fd = new QFileDialogP( this );
5745 fd->setContentsPreviewEnabled( TRUE );
5746 fd->setContentsPreview( p, p );
5747 fd->setPreviewMode( QFileDialogP::Contents );
5752 \sa setContentsPreviewEnabled(), setInfoPreview(), setPreviewMode()
5755 void QFileDialogP::setContentsPreview( QWidget *w, QFilePreviewP *preview )
5757 if ( !w || !preview )
5760 if ( d->contentsPreviewWidget ) {
5761 d->preview->removeWidget( d->contentsPreviewWidget );
5762 delete d->contentsPreviewWidget;
5764 if ( d->contentsPreviewer )
5765 delete d->contentsPreviewer;
5766 d->contentsPreviewWidget = w;
5767 d->contentsPreviewer = preview;
5768 w->reparent( d->preview, 0, QPoint( 0, 0 ) );
5772 Re-sorts the displayed directory.
5777 void QFileDialogP::resortDir()
5779 d->mimeTypeTimer->stop();
5780 d->pendingItems.clear();
5782 QFileDialogPrivate::File *item = 0;
5783 QFileDialogPrivate::MCItem *item2 = 0;
5785 d->sortedList.sort();
5787 if ( files->childCount() > 0 || d->moreFiles->count() > 0 ) {
5788 d->moreFiles->clear();
5791 files->setSorting( -1 );
5794 QUrlInfo *i = sortAscending ? d->sortedList.first() : d->sortedList.last();
5795 for ( ; i; i = sortAscending ? d->sortedList.next() : d->sortedList.prev() ) {
5796 item = new QFileDialogPrivate::File( d, i, files );
5797 item2 = new QFileDialogPrivate::MCItem( d->moreFiles, item, item2 );
5799 d->pendingItems.append( item );
5800 if ( d->mode == ExistingFiles && item->info.isDir() ||
5801 ( isDirectoryMode( d->mode ) && item->info.isFile() ) ) {
5802 item->setSelectable( FALSE );
5803 item2->setSelectable( FALSE );
5807 // ##### As the QFileIconProviderP only support QFileInfo and no
5808 // QUrlInfo it can be only used for local files at the moment. In
5809 // 3.0 we have to change the API of QFileIconProviderP to work on
5810 // QUrlInfo so that also remote filesystems can be show mime-type
5812 if ( d->url.isLocalFile() )
5813 d->mimeTypeTimer->start( 0 );
5817 Stops the current copy operation.
5820 void QFileDialogP::stopCopy()
5822 if ( d->ignoreStop )
5825 d->url.blockSignals( TRUE );
5827 if ( d->progressDia ) {
5828 d->ignoreStop = TRUE;
5829 QTimer::singleShot( 100, this, SLOT( removeProgressDia() ) );
5831 d->url.blockSignals( FALSE );
5838 void QFileDialogP::removeProgressDia()
5840 if ( d->progressDia )
5841 delete d->progressDia;
5849 void QFileDialogP::doMimeTypeLookup()
5851 if ( !iconProvider() ) {
5852 d->pendingItems.clear();
5853 d->mimeTypeTimer->stop();
5857 d->mimeTypeTimer->stop();
5858 if ( d->pendingItems.count() == 0 ) {
5863 QFileDialogPrivate::File *item = d->pendingItems.first();
5866 if ( d->url.isLocalFile() ) {
5867 fi.setFile( QUrl( d->url.path(), QFileDialogPrivate::encodeFileName( item->info.name() ) ).path( FALSE ) );
5869 fi.setFile( item->info.name() ); // #####
5870 const QPixmap *p = iconProvider()->pixmap( fi );
5871 if ( p && p != item->pixmap( 0 ) &&
5872 ( !item->pixmap( 0 ) || p->serialNumber() != item->pixmap( 0 )->serialNumber() ) &&
5873 p != fifteenTransparentPixels ) {
5874 item->hasMimePixmap = TRUE;
5876 // evil hack to avoid much too much repaints!
5877 qApp->processEvents();
5878 files->setUpdatesEnabled( FALSE );
5879 files->viewport()->setUpdatesEnabled( FALSE );
5880 if ( item != d->pendingItems.first() )
5882 item->setPixmap( 0, *p );
5883 qApp->processEvents();
5884 files->setUpdatesEnabled( TRUE );
5885 files->viewport()->setUpdatesEnabled( TRUE );
5887 if ( files->isVisible() ) {
5888 QRect ir( files->itemRect( item ) );
5889 if ( ir != QRect( 0, 0, -1, -1 ) ) {
5893 QRect ir( d->moreFiles->itemRect( item->i ) );
5894 if ( ir != QRect( 0, 0, -1, -1 ) ) {
5899 if ( d->pendingItems.count() )
5900 d->pendingItems.removeFirst();
5903 if ( d->moreFiles->isVisible() ) {
5904 d->moreFiles->viewport()->repaint( r, FALSE );
5906 files->viewport()->repaint( r, FALSE );
5909 if ( d->pendingItems.count() )
5910 d->mimeTypeTimer->start( 0 );
5911 else if ( d->moreFiles->isVisible() )
5912 d->moreFiles->triggerUpdate( TRUE );
5916 If \a b is TRUE then all the files in the current directory are selected;
5917 otherwise, they are deselected.
5920 void QFileDialogP::selectAll( bool b )
5922 if ( d->mode != ExistingFiles )
5924 d->moreFiles->selectAll( b );
5925 files->selectAll( b );
5928 void QFileDialogP::goBack()
5930 if ( !d->goBack || !d->goBack->isEnabled() )
5932 d->history.remove( d->history.last() );
5933 if ( d->history.count() < 2 )
5934 d->goBack->setEnabled( FALSE );
5935 setUrl( d->history.last() );
5938 // a class with wonderfully inflexible flexibility. why doesn't it
5939 // just subclass QWidget in the first place? 'you have to derive your
5940 // preview widget from QWidget and from this class' indeed.
5943 \class QFilePreviewP qfiledialog.h
5945 \brief The QFilePreviewP class provides file previewing in QFileDialogP.
5947 This class is an abstract base class which is used to implement
5948 widgets that can display a preview of a file in a QFileDialogP.
5950 You must derive the preview widget from both QWidget and from this
5951 class. Then you must reimplement this class's previewUrl() function,
5952 which is called by the file dialog if the preview of a file
5953 (specified as a URL) should be shown.
5955 See also QFileDialog::setPreviewMode(), QFileDialogP::setContentsPreview(),
5956 QFileDialogP::setInfoPreview(), QFileDialogP::setInfoPreviewEnabled(),
5957 QFileDialogP::setContentsPreviewEnabled().
5959 For an example of a preview widget see qt/examples/qdir/qdir.cpp.
5963 Constructs the QFilePreviewP.
5966 QFilePreviewP::QFilePreviewP()
5971 \fn void QFilePreviewP::previewUrl( const QUrl &url )
5973 This function is called by QFileDialogP if a preview
5974 for the \a url should be shown. Reimplement this
5975 function to provide file previewing.