QFileDialog: don't create widgets if the platform dialog will be used

This is a performance and memory optimization which also fixes bugs
that are related to creating widgets, file system models etc.
despite using platform native dialogs.  Similar to
785bc64f8e for QColorDialog.

Task-number: QTBUG-33039
Change-Id: Ia1aa7ec1f43b47006b9ebd377aed15c958538a17
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
Shawn Rutledge 2013-08-21 10:08:50 +02:00 committed by The Qt Project
parent 5c301f4121
commit 37ca2224ec
4 changed files with 212 additions and 81 deletions

View File

@ -578,8 +578,8 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
m_ownerWindow = 0; m_ownerWindow = 0;
} }
if (QWindowsContext::verboseDialogs) if (QWindowsContext::verboseDialogs)
qDebug("%s modal=%d native=%p parent=%p" , qDebug("%s modal=%d modal supported? %d native=%p parent=%p" ,
__FUNCTION__, modal, m_nativeDialog.data(), m_ownerWindow); __FUNCTION__, modal, supportsNonModalDialog(parent), m_nativeDialog.data(), m_ownerWindow);
if (!modal && !supportsNonModalDialog(parent)) if (!modal && !supportsNonModalDialog(parent))
return false; // Was it changed in-between? return false; // Was it changed in-between?
if (!ensureNativeDialog()) if (!ensureNativeDialog())

View File

@ -379,7 +379,6 @@ QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->init(); d->init();
d->lineEdit()->selectAll();
} }
/*! /*!
@ -397,7 +396,6 @@ QFileDialog::QFileDialog(QWidget *parent,
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->init(directory, filter, caption); d->init(directory, filter, caption);
d->lineEdit()->selectAll();
} }
/*! /*!
@ -411,7 +409,6 @@ QFileDialog::QFileDialog(const QFileDialogArgs &args)
setFileMode(args.mode); setFileMode(args.mode);
setOptions(args.options); setOptions(args.options);
selectFile(args.selection); selectFile(args.selection);
d->lineEdit()->selectAll();
} }
/*! /*!
@ -443,7 +440,8 @@ QFileDialog::~QFileDialog()
void QFileDialog::setSidebarUrls(const QList<QUrl> &urls) void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->qFileDialogUi->sidebar->setUrls(urls); if (!d->nativeDialogInUse)
d->qFileDialogUi->sidebar->setUrls(urls);
} }
/*! /*!
@ -453,7 +451,7 @@ void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
QList<QUrl> QFileDialog::sidebarUrls() const QList<QUrl> QFileDialog::sidebarUrls() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
return d->qFileDialogUi->sidebar->urls(); return (d->nativeDialogInUse ? QList<QUrl>() : d->qFileDialogUi->sidebar->urls());
} }
static const qint32 QFileDialogMagic = 0xbe; static const qint32 QFileDialogMagic = 0xbe;
@ -474,11 +472,19 @@ QByteArray QFileDialog::saveState() const
stream << qint32(QFileDialogMagic); stream << qint32(QFileDialogMagic);
stream << qint32(version); stream << qint32(version);
stream << d->qFileDialogUi->splitter->saveState(); if (d->usingWidgets()) {
stream << d->qFileDialogUi->sidebar->urls(); stream << d->qFileDialogUi->splitter->saveState();
stream << d->qFileDialogUi->sidebar->urls();
} else {
stream << QByteArray();
stream << QList<QUrl>();
}
stream << history(); stream << history();
stream << *lastVisitedDir(); stream << *lastVisitedDir();
stream << d->qFileDialogUi->treeView->header()->saveState(); if (d->usingWidgets())
stream << d->qFileDialogUi->treeView->header()->saveState();
else
stream << QByteArray();
stream << qint32(viewMode()); stream << qint32(viewMode());
return data; return data;
} }
@ -520,6 +526,12 @@ bool QFileDialog::restoreState(const QByteArray &state)
>> headerData >> headerData
>> viewMode; >> viewMode;
setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));
if (!d->usingWidgets())
return true;
if (!d->qFileDialogUi->splitter->restoreState(splitterState)) if (!d->qFileDialogUi->splitter->restoreState(splitterState))
return false; return false;
QList<int> list = d->qFileDialogUi->splitter->sizes(); QList<int> list = d->qFileDialogUi->splitter->sizes();
@ -533,7 +545,6 @@ bool QFileDialog::restoreState(const QByteArray &state)
while (history.count() > 5) while (history.count() > 5)
history.pop_front(); history.pop_front();
setHistory(history); setHistory(history);
setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
QHeaderView *headerView = d->qFileDialogUi->treeView->header(); QHeaderView *headerView = d->qFileDialogUi->treeView->header();
if (!headerView->restoreState(headerData)) if (!headerView->restoreState(headerData))
return false; return false;
@ -548,7 +559,6 @@ bool QFileDialog::restoreState(const QByteArray &state)
for (int i = 1; i < total; ++i) for (int i = 1; i < total; ++i)
actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i)); actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
setViewMode(ViewMode(viewMode));
return true; return true;
} }
@ -595,15 +605,16 @@ void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl))); QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl)));
QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString))); QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
static_cast<QPlatformFileDialogHelper *>(h)->setOptions(options); static_cast<QPlatformFileDialogHelper *>(h)->setOptions(options);
nativeDialogInUse = true;
} }
void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *) void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
{ {
Q_Q(QFileDialog); Q_Q(QFileDialog);
options->setWindowTitle(q->windowTitle()); options->setWindowTitle(q->windowTitle());
options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(q->viewMode()));
options->setHistory(q->history()); options->setHistory(q->history());
options->setSidebarUrls(qFileDialogUi->sidebar->urls()); if (usingWidgets())
options->setSidebarUrls(qFileDialogUi->sidebar->urls());
const QDir directory = q->directory(); const QDir directory = q->directory();
options->setInitialDirectory(directory.exists() ? options->setInitialDirectory(directory.exists() ?
QUrl::fromLocalFile(directory.absolutePath()) : QUrl::fromLocalFile(directory.absolutePath()) :
@ -644,9 +655,17 @@ void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
*lastVisitedDir() = dir; *lastVisitedDir() = dir;
} }
void QFileDialogPrivate::updateLookInLabel()
{
if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))
setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));
}
void QFileDialogPrivate::updateFileNameLabel() void QFileDialogPrivate::updateFileNameLabel()
{ {
if (!options->isLabelExplicitlySet(QFileDialogOptions::FileName)) { if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
} else {
switch (q_func()->fileMode()) { switch (q_func()->fileMode()) {
case QFileDialog::DirectoryOnly: case QFileDialog::DirectoryOnly:
case QFileDialog::Directory: case QFileDialog::Directory:
@ -659,6 +678,12 @@ void QFileDialogPrivate::updateFileNameLabel()
} }
} }
void QFileDialogPrivate::updateFileTypeLabel()
{
if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))
setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));
}
void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder) void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)
{ {
Q_Q(QFileDialog); Q_Q(QFileDialog);
@ -684,12 +709,20 @@ void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)
} }
} }
void QFileDialogPrivate::updateCancelButtonText()
{
if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))
setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));
}
void QFileDialogPrivate::retranslateStrings() void QFileDialogPrivate::retranslateStrings()
{ {
Q_Q(QFileDialog); Q_Q(QFileDialog);
/* WIDGETS */ /* WIDGETS */
if (defaultFileTypes) if (defaultFileTypes)
q->setNameFilter(QFileDialog::tr("All Files (*)")); q->setNameFilter(QFileDialog::tr("All Files (*)"));
if (nativeDialogInUse)
return;
QList<QAction*> actions = qFileDialogUi->treeView->header()->actions(); QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
QAbstractItemModel *abstractModel = model; QAbstractItemModel *abstractModel = model;
@ -708,7 +741,10 @@ void QFileDialogPrivate::retranslateStrings()
showHiddenAction->setText(QFileDialog::tr("Show &hidden files")); showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
newFolderAction->setText(QFileDialog::tr("&New Folder")); newFolderAction->setText(QFileDialog::tr("&New Folder"));
qFileDialogUi->retranslateUi(q); qFileDialogUi->retranslateUi(q);
updateLookInLabel();
updateFileNameLabel(); updateFileNameLabel();
updateFileTypeLabel();
updateCancelButtonText();
} }
void QFileDialogPrivate::emitFilesSelected(const QStringList &files) void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
@ -734,6 +770,11 @@ bool QFileDialogPrivate::canBeNativeDialog()
return (staticName == dynamicName); return (staticName == dynamicName);
} }
bool QFileDialogPrivate::usingWidgets() const
{
return !nativeDialogInUse && qFileDialogUi;
}
/*! /*!
\since 4.5 \since 4.5
Sets the given \a option to be enabled if \a on is true; otherwise, Sets the given \a option to be enabled if \a on is true; otherwise,
@ -784,29 +825,36 @@ void QFileDialog::setOptions(Options options)
return; return;
d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options))); d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));
if (changed & DontResolveSymlinks)
d->model->setResolveSymlinks(!(options & DontResolveSymlinks)); if ((options & DontUseNativeDialog) && !d->usingWidgets())
if (changed & ReadOnly) { d->createWidgets();
bool ro = (options & ReadOnly);
d->model->setReadOnly(ro); if (d->usingWidgets()) {
d->qFileDialogUi->newFolderButton->setEnabled(!ro); if (changed & DontResolveSymlinks)
d->renameAction->setEnabled(!ro); d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
d->deleteAction->setEnabled(!ro); if (changed & ReadOnly) {
bool ro = (options & ReadOnly);
d->model->setReadOnly(ro);
d->qFileDialogUi->newFolderButton->setEnabled(!ro);
d->renameAction->setEnabled(!ro);
d->deleteAction->setEnabled(!ro);
}
if (changed & DontUseCustomDirectoryIcons) {
QFileIconProvider::Options providerOptions = iconProvider()->options();
if (options & DontUseCustomDirectoryIcons)
providerOptions |= QFileIconProvider::DontUseCustomDirectoryIcons;
else
providerOptions &= ~QFileIconProvider::DontUseCustomDirectoryIcons;
iconProvider()->setOptions(providerOptions);
}
} }
if (changed & HideNameFilterDetails) if (changed & HideNameFilterDetails)
setNameFilters(d->options->nameFilters()); setNameFilters(d->options->nameFilters());
if (changed & ShowDirsOnly) if (changed & ShowDirsOnly)
setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files); setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
if (changed & DontUseCustomDirectoryIcons) {
QFileIconProvider::Options providerOptions = iconProvider()->options();
if (options & DontUseCustomDirectoryIcons)
providerOptions |= QFileIconProvider::DontUseCustomDirectoryIcons;
else
providerOptions &= ~QFileIconProvider::DontUseCustomDirectoryIcons;
iconProvider()->setOptions(providerOptions);
}
} }
QFileDialog::Options QFileDialog::options() const QFileDialog::Options QFileDialog::options() const
@ -858,21 +906,25 @@ void QFileDialog::setVisible(bool visible)
// updates the state correctly, but skips showing the non-native version: // updates the state correctly, but skips showing the non-native version:
setAttribute(Qt::WA_DontShowOnScreen); setAttribute(Qt::WA_DontShowOnScreen);
#ifndef QT_NO_FSCOMPLETER #ifndef QT_NO_FSCOMPLETER
//So the completer don't try to complete and therefore to show a popup // So the completer doesn't try to complete and therefore show a popup
d->completer->setModel(0); if (!d->nativeDialogInUse)
d->completer->setModel(0);
#endif #endif
} else { } else {
d->createWidgets();
setAttribute(Qt::WA_DontShowOnScreen, false); setAttribute(Qt::WA_DontShowOnScreen, false);
#ifndef QT_NO_FSCOMPLETER #ifndef QT_NO_FSCOMPLETER
if (d->proxyModel != 0) if (!d->nativeDialogInUse) {
d->completer->setModel(d->proxyModel); if (d->proxyModel != 0)
else d->completer->setModel(d->proxyModel);
d->completer->setModel(d->model); else
d->completer->setModel(d->model);
}
#endif #endif
} }
} }
if (!d->nativeDialogInUse) if (d->usingWidgets())
d->qFileDialogUi->fileNameEdit->setFocus(); d->qFileDialogUi->fileNameEdit->setFocus();
QDialog::setVisible(visible); QDialog::setVisible(visible);
@ -914,24 +966,27 @@ void QFileDialog::setDirectory(const QString &directory)
d->setLastVisitedDirectory(newDirectory); d->setLastVisitedDirectory(newDirectory);
if (d->nativeDialogInUse){ d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
if (!d->usingWidgets()) {
d->setDirectory_sys(QUrl::fromLocalFile(newDirectory)); d->setDirectory_sys(QUrl::fromLocalFile(newDirectory));
return; return;
} }
if (d->rootPath() == newDirectory) if (d->rootPath() == newDirectory)
return; return;
QModelIndex root = d->model->setRootPath(newDirectory); QModelIndex root = d->model->setRootPath(newDirectory);
d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled); if (!d->nativeDialogInUse) {
if (root != d->rootIndex()) { d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
if (root != d->rootIndex()) {
#ifndef QT_NO_FSCOMPLETER #ifndef QT_NO_FSCOMPLETER
if (directory.endsWith(QLatin1Char('/'))) if (directory.endsWith(QLatin1Char('/')))
d->completer->setCompletionPrefix(newDirectory); d->completer->setCompletionPrefix(newDirectory);
else else
d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/')); d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/'));
#endif #endif
d->setRootIndex(root); d->setRootIndex(root);
}
d->qFileDialogUi->listView->selectionModel()->clear();
} }
d->qFileDialogUi->listView->selectionModel()->clear();
} }
/*! /*!
@ -989,8 +1044,11 @@ void QFileDialog::selectFile(const QString &filename)
if (filename.isEmpty()) if (filename.isEmpty())
return; return;
if (d->nativeDialogInUse){ if (!d->usingWidgets()) {
d->selectFile_sys(QUrl::fromLocalFile(filename)); d->selectFile_sys(QUrl::fromLocalFile(filename));
QList<QUrl> i;
i << QUrl(filename);
d->options->setInitiallySelectedFiles(i);
return; return;
} }
@ -1141,7 +1199,7 @@ QList<QUrl> QFileDialogPrivate::userSelectedFiles() const
{ {
QList<QUrl> files; QList<QUrl> files;
if (nativeDialogInUse) if (!usingWidgets())
return addDefaultSuffixToUrls(selectedFiles_sys()); return addDefaultSuffixToUrls(selectedFiles_sys());
foreach (const QModelIndex &index, qFileDialogUi->listView->selectionModel()->selectedRows()) foreach (const QModelIndex &index, qFileDialogUi->listView->selectionModel()->selectedRows())
@ -1339,6 +1397,9 @@ void QFileDialog::setNameFilters(const QStringList &filters)
} }
d->options->setNameFilters(cleanedFilters); d->options->setNameFilters(cleanedFilters);
if (!d->usingWidgets())
return;
d->qFileDialogUi->fileTypeCombo->clear(); d->qFileDialogUi->fileTypeCombo->clear();
if (cleanedFilters.isEmpty()) if (cleanedFilters.isEmpty())
return; return;
@ -1373,7 +1434,7 @@ QStringList QFileDialog::nameFilters() const
void QFileDialog::selectNameFilter(const QString &filter) void QFileDialog::selectNameFilter(const QString &filter)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
if (d->nativeDialogInUse) { if (!d->usingWidgets()) {
d->selectNameFilter_sys(filter); d->selectNameFilter_sys(filter);
return; return;
} }
@ -1401,7 +1462,7 @@ void QFileDialog::selectNameFilter(const QString &filter)
QString QFileDialog::selectedNameFilter() const QString QFileDialog::selectedNameFilter() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
if (d->nativeDialogInUse) if (!d->usingWidgets())
return d->selectedNameFilter_sys(); return d->selectedNameFilter_sys();
return d->qFileDialogUi->fileTypeCombo->currentText(); return d->qFileDialogUi->fileTypeCombo->currentText();
@ -1417,7 +1478,9 @@ QString QFileDialog::selectedNameFilter() const
QDir::Filters QFileDialog::filter() const QDir::Filters QFileDialog::filter() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
return d->model->filter(); if (d->usingWidgets())
return d->model->filter();
return d->options->filter();
} }
/*! /*!
@ -1432,13 +1495,13 @@ QDir::Filters QFileDialog::filter() const
void QFileDialog::setFilter(QDir::Filters filters) void QFileDialog::setFilter(QDir::Filters filters)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->model->setFilter(filters);
d->options->setFilter(filters); d->options->setFilter(filters);
if (d->nativeDialogInUse){ if (!d->usingWidgets()) {
d->setFilter_sys(); d->setFilter_sys();
return; return;
} }
d->model->setFilter(filters);
d->showHiddenAction->setChecked((filters & QDir::Hidden)); d->showHiddenAction->setChecked((filters & QDir::Hidden));
} }
@ -1523,6 +1586,9 @@ void QFileDialog::selectMimeTypeFilter(const QString &filter)
void QFileDialog::setViewMode(QFileDialog::ViewMode mode) void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->options->setViewMode(static_cast<QFileDialogOptions::ViewMode>(mode));
if (!d->usingWidgets())
return;
if (mode == Detail) if (mode == Detail)
d->_q_showDetailsView(); d->_q_showDetailsView();
else else
@ -1532,6 +1598,8 @@ void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
QFileDialog::ViewMode QFileDialog::viewMode() const QFileDialog::ViewMode QFileDialog::viewMode() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
if (!d->usingWidgets())
return QFileDialog::List;
return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail); return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
} }
@ -1554,11 +1622,15 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode)); d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));
d->retranslateWindowTitle();
// keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete) // keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete)
setOption(ShowDirsOnly, mode == DirectoryOnly); setOption(ShowDirsOnly, mode == DirectoryOnly);
if (!d->usingWidgets())
return;
d->retranslateWindowTitle();
// set selection mode and behavior // set selection mode and behavior
QAbstractItemView::SelectionMode selectionMode; QAbstractItemView::SelectionMode selectionMode;
if (mode == QFileDialog::ExistingFiles) if (mode == QFileDialog::ExistingFiles)
@ -1577,11 +1649,6 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode)
} }
d->updateFileNameLabel(); d->updateFileNameLabel();
d->updateOkButtonText(); d->updateOkButtonText();
if (d->nativeDialogInUse){
d->setFilter_sys();
return;
}
d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly)); d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
d->_q_updateOkButton(); d->_q_updateOkButton();
} }
@ -1606,6 +1673,13 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode)); d->options->setAcceptMode(static_cast<QFileDialogOptions::AcceptMode>(mode));
// clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
setAttribute(Qt::WA_DontShowOnScreen, false);
if (!d->usingWidgets()) {
// we need to recreate the native dialog when changing the AcceptMode
d->deletePlatformHelper();
return;
}
QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save); QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel); d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
d->qFileDialogUi->buttonBox->button(button)->setEnabled(false); d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
@ -1614,10 +1688,6 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
d->qFileDialogUi->lookInCombo->setEditable(false); d->qFileDialogUi->lookInCombo->setEditable(false);
} }
d->retranslateWindowTitle(); d->retranslateWindowTitle();
// we need to recreate the native dialog when changing the AcceptMode
d->deletePlatformHelper();
// clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
setAttribute(Qt::WA_DontShowOnScreen, false);
} }
/* /*
@ -1778,7 +1848,8 @@ QString QFileDialog::defaultSuffix() const
void QFileDialog::setHistory(const QStringList &paths) void QFileDialog::setHistory(const QStringList &paths)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
d->qFileDialogUi->lookInCombo->setHistory(paths); if (d->usingWidgets())
d->qFileDialogUi->lookInCombo->setHistory(paths);
} }
void QFileDialogComboBox::setHistory(const QStringList &paths) void QFileDialogComboBox::setHistory(const QStringList &paths)
@ -1800,6 +1871,8 @@ void QFileDialogComboBox::setHistory(const QStringList &paths)
QStringList QFileDialog::history() const QStringList QFileDialog::history() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
if (!d->usingWidgets())
return QStringList();
QStringList currentHistory = d->qFileDialogUi->lookInCombo->history(); QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
//On windows the popup display the "C:\", convert to nativeSeparators //On windows the popup display the "C:\", convert to nativeSeparators
QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString()); QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
@ -1826,6 +1899,8 @@ QStringList QFileDialog::history() const
void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate) void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
if (!d->usingWidgets())
return;
d->qFileDialogUi->listView->setItemDelegate(delegate); d->qFileDialogUi->listView->setItemDelegate(delegate);
d->qFileDialogUi->treeView->setItemDelegate(delegate); d->qFileDialogUi->treeView->setItemDelegate(delegate);
} }
@ -1836,6 +1911,8 @@ void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
QAbstractItemDelegate *QFileDialog::itemDelegate() const QAbstractItemDelegate *QFileDialog::itemDelegate() const
{ {
Q_D(const QFileDialog); Q_D(const QFileDialog);
if (!d->usingWidgets())
return 0;
return d->qFileDialogUi->listView->itemDelegate(); return d->qFileDialogUi->listView->itemDelegate();
} }
@ -1845,6 +1922,8 @@ QAbstractItemDelegate *QFileDialog::itemDelegate() const
void QFileDialog::setIconProvider(QFileIconProvider *provider) void QFileDialog::setIconProvider(QFileIconProvider *provider)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
if (!d->usingWidgets())
return;
d->model->setIconProvider(provider); d->model->setIconProvider(provider);
//It forces the refresh of all entries in the side bar, then we can get new icons //It forces the refresh of all entries in the side bar, then we can get new icons
d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls()); d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
@ -1861,6 +1940,8 @@ QFileIconProvider *QFileDialog::iconProvider() const
void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text) void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)
{ {
if (!qFileDialogUi)
return;
switch (label) { switch (label) {
case QFileDialog::LookIn: case QFileDialog::LookIn:
qFileDialogUi->lookInLabel->setText(text); qFileDialogUi->lookInLabel->setText(text);
@ -1903,8 +1984,10 @@ void QFileDialog::setLabelText(DialogLabel label, const QString &text)
*/ */
QString QFileDialog::labelText(DialogLabel label) const QString QFileDialog::labelText(DialogLabel label) const
{ {
QPushButton *button;
Q_D(const QFileDialog); Q_D(const QFileDialog);
if (!d->usingWidgets())
return d->options->labelText(static_cast<QFileDialogOptions::DialogLabel>(label));
QPushButton *button;
switch (label) { switch (label) {
case LookIn: case LookIn:
return d->qFileDialogUi->lookInLabel->text(); return d->qFileDialogUi->lookInLabel->text();
@ -2518,7 +2601,7 @@ void QFileDialog::accept()
QStringList files = selectedFiles(); QStringList files = selectedFiles();
if (files.isEmpty()) if (files.isEmpty())
return; return;
if (d->nativeDialogInUse){ if (!d->usingWidgets()) {
d->emitFilesSelected(files); d->emitFilesSelected(files);
QDialog::accept(); QDialog::accept();
return; return;
@ -2631,16 +2714,19 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte
q->setWindowTitle(caption); q->setWindowTitle(caption);
} }
createWidgets(); q->setAcceptMode(QFileDialog::AcceptOpen);
createMenuActions(); nativeDialogInUse = (canBeNativeDialog() && platformFileDialogHelper() != 0);
retranslateStrings(); if (!nativeDialogInUse)
createWidgets();
q->setFileMode(QFileDialog::AnyFile); q->setFileMode(QFileDialog::AnyFile);
if (!nameFilter.isEmpty())
q->setNameFilter(nameFilter);
q->setDirectory(workingDirectory(directory));
q->selectFile(initialSelection(directory));
#ifndef QT_NO_SETTINGS #ifndef QT_NO_SETTINGS
QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
settings.beginGroup(QLatin1String("Qt")); settings.beginGroup(QLatin1String("Qt"));
if (!directory.isEmpty())
setLastVisitedDirectory(workingDirectory(directory));
q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray()); q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
#endif #endif
@ -2650,14 +2736,7 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte
qFileDialogUi->fileTypeLabel->setVisible(false); qFileDialogUi->fileTypeLabel->setVisible(false);
qFileDialogUi->sidebar->hide(); qFileDialogUi->sidebar->hide();
#endif #endif
// Default case
if (!nameFilter.isEmpty())
q->setNameFilter(nameFilter);
q->setAcceptMode(QFileDialog::AcceptOpen);
q->setDirectory(workingDirectory(directory));
q->selectFile(initialSelection(directory));
_q_updateOkButton();
q->resize(q->sizeHint()); q->resize(q->sizeHint());
} }
@ -2668,6 +2747,8 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte
*/ */
void QFileDialogPrivate::createWidgets() void QFileDialogPrivate::createWidgets()
{ {
if (qFileDialogUi)
return;
Q_Q(QFileDialog); Q_Q(QFileDialog);
model = new QFileSystemModel(q); model = new QFileSystemModel(q);
options->setFilter(model->filter()); options->setFilter(model->filter());
@ -2676,6 +2757,8 @@ void QFileDialogPrivate::createWidgets()
model->setNameFilterDisables(helper->defaultNameFilterDisables()); model->setNameFilterDisables(helper->defaultNameFilterDisables());
else else
model->setNameFilterDisables(false); model->setNameFilterDisables(false);
if (nativeDialogInUse)
deletePlatformHelper();
model->d_func()->disableRecursiveSort = true; model->d_func()->disableRecursiveSort = true;
QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,QString))); QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,QString)));
QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)), QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)),
@ -2789,6 +2872,31 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding); qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
createToolButtons(); createToolButtons();
createMenuActions();
// Initial widget states from options
q->setFileMode(static_cast<QFileDialog::FileMode>(options->fileMode()));
q->setAcceptMode(static_cast<QFileDialog::AcceptMode>(options->acceptMode()));
q->setViewMode(static_cast<QFileDialog::ViewMode>(options->viewMode()));
q->setOptions(static_cast<QFileDialog::Options>(static_cast<int>(options->options())));
if (!options->sidebarUrls().isEmpty())
q->setSidebarUrls(options->sidebarUrls());
q->setDirectoryUrl(options->initialDirectory());
if (!options->mimeTypeFilters().isEmpty())
q->setMimeTypeFilters(options->mimeTypeFilters());
else if (!options->nameFilters().isEmpty())
q->setNameFilters(options->nameFilters());
q->selectNameFilter(options->initiallySelectedNameFilter());
q->setDefaultSuffix(options->defaultSuffix());
q->setHistory(options->history());
if (options->initiallySelectedFiles().count() == 1)
q->selectFile(options->initiallySelectedFiles().first().fileName());
foreach (QUrl url, options->initiallySelectedFiles())
q->selectUrl(url);
lineEdit()->selectAll();
_q_updateOkButton();
retranslateStrings();
q->resize(q->sizeHint());
} }
void QFileDialogPrivate::_q_showHeader(QAction *action) void QFileDialogPrivate::_q_showHeader(QAction *action)
@ -2814,6 +2922,8 @@ void QFileDialogPrivate::_q_showHeader(QAction *action)
void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel) void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
{ {
Q_D(QFileDialog); Q_D(QFileDialog);
if (!d->usingWidgets())
return;
if ((!proxyModel && !d->proxyModel) if ((!proxyModel && !d->proxyModel)
|| (proxyModel == d->proxyModel)) || (proxyModel == d->proxyModel))
return; return;

View File

@ -135,8 +135,11 @@ public:
QList<QUrl> addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const; QList<QUrl> addDefaultSuffixToUrls(const QList<QUrl> &urlsToFix) const;
bool removeDirectory(const QString &path); bool removeDirectory(const QString &path);
void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text); void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text);
inline void updateLookInLabel();
inline void updateFileNameLabel(); inline void updateFileNameLabel();
inline void updateFileTypeLabel();
void updateOkButtonText(bool saveAsOnFolder = false); void updateOkButtonText(bool saveAsOnFolder = false);
void updateCancelButtonText();
inline QModelIndex mapToSource(const QModelIndex &index) const; inline QModelIndex mapToSource(const QModelIndex &index) const;
inline QModelIndex mapFromSource(const QModelIndex &index) const; inline QModelIndex mapFromSource(const QModelIndex &index) const;
@ -249,6 +252,7 @@ public:
// dialog. Returning false means that a non-native dialog must be // dialog. Returning false means that a non-native dialog must be
// used instead. // used instead.
bool canBeNativeDialog(); bool canBeNativeDialog();
inline bool usingWidgets() const;
void setDirectory_sys(const QUrl &directory); void setDirectory_sys(const QUrl &directory);
QUrl directory_sys() const; QUrl directory_sys() const;
@ -347,7 +351,7 @@ inline QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) c
} }
inline QString QFileDialogPrivate::rootPath() const { inline QString QFileDialogPrivate::rootPath() const {
return model->rootPath(); return (model ? model->rootPath() : QStringLiteral("/"));
} }
inline void QFileDialogPrivate::setDirectory_sys(const QUrl &directory) inline void QFileDialogPrivate::setDirectory_sys(const QUrl &directory)

View File

@ -66,6 +66,8 @@
#include <private/qfilesystemmodel_p.h> #include <private/qfilesystemmodel_p.h>
#include <private/qfiledialog_p.h> #include <private/qfiledialog_p.h>
#endif #endif
#include <private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
#include <QFileDialog> #include <QFileDialog>
#include <QFileSystemModel> #include <QFileSystemModel>
@ -145,6 +147,7 @@ private slots:
void clearLineEdit(); void clearLineEdit();
void enableChooseButton(); void enableChooseButton();
void hooks(); void hooks();
void widgetlessNativeDialog();
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL
void tildeExpansion_data(); void tildeExpansion_data();
@ -1396,6 +1399,20 @@ void tst_QFiledialog::hooks()
QCOMPARE(QFileDialog::getSaveFileUrl(), QUrl("http://saveUrl")); QCOMPARE(QFileDialog::getSaveFileUrl(), QUrl("http://saveUrl"));
} }
void tst_QFiledialog::widgetlessNativeDialog()
{
if (!QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog))
QSKIP("This platform always uses widgets to realize its QFileDialog, instead of the native file dialog.");
QFileDialog fd;
fd.setWindowModality(Qt::ApplicationModal);
fd.show();
QTRY_VERIFY(fd.isVisible());
QFileSystemModel *model = fd.findChild<QFileSystemModel*>("qt_filesystem_model");
QVERIFY(!model);
QPushButton *button = fd.findChild<QPushButton*>();
QVERIFY(!button);
}
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL
void tst_QFiledialog::tildeExpansion_data() void tst_QFiledialog::tildeExpansion_data()