From 37ca2224eca671200a2710f57f970d2993e62aa5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 21 Aug 2013 10:08:50 +0200 Subject: [PATCH] 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 785bc64f8e743ac269f15cbe7fecba93d3d507ac for QColorDialog. Task-number: QTBUG-33039 Change-Id: Ia1aa7ec1f43b47006b9ebd377aed15c958538a17 Reviewed-by: Friedemann Kleint --- .../windows/qwindowsdialoghelpers.cpp | 4 +- src/widgets/dialogs/qfiledialog.cpp | 266 +++++++++++++----- src/widgets/dialogs/qfiledialog_p.h | 6 +- .../dialogs/qfiledialog/tst_qfiledialog.cpp | 17 ++ 4 files changed, 212 insertions(+), 81 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 0ecbf44194..0bf6838d9e 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -578,8 +578,8 @@ bool QWindowsDialogHelperBase::show(Qt::WindowFlags, m_ownerWindow = 0; } if (QWindowsContext::verboseDialogs) - qDebug("%s modal=%d native=%p parent=%p" , - __FUNCTION__, modal, m_nativeDialog.data(), m_ownerWindow); + qDebug("%s modal=%d modal supported? %d native=%p parent=%p" , + __FUNCTION__, modal, supportsNonModalDialog(parent), m_nativeDialog.data(), m_ownerWindow); if (!modal && !supportsNonModalDialog(parent)) return false; // Was it changed in-between? if (!ensureNativeDialog()) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index b688dfb0a4..383e3ab3f4 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -379,7 +379,6 @@ QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f) { Q_D(QFileDialog); d->init(); - d->lineEdit()->selectAll(); } /*! @@ -397,7 +396,6 @@ QFileDialog::QFileDialog(QWidget *parent, { Q_D(QFileDialog); d->init(directory, filter, caption); - d->lineEdit()->selectAll(); } /*! @@ -411,7 +409,6 @@ QFileDialog::QFileDialog(const QFileDialogArgs &args) setFileMode(args.mode); setOptions(args.options); selectFile(args.selection); - d->lineEdit()->selectAll(); } /*! @@ -443,7 +440,8 @@ QFileDialog::~QFileDialog() void QFileDialog::setSidebarUrls(const QList &urls) { 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 &urls) QList QFileDialog::sidebarUrls() const { Q_D(const QFileDialog); - return d->qFileDialogUi->sidebar->urls(); + return (d->nativeDialogInUse ? QList() : d->qFileDialogUi->sidebar->urls()); } static const qint32 QFileDialogMagic = 0xbe; @@ -474,11 +472,19 @@ QByteArray QFileDialog::saveState() const stream << qint32(QFileDialogMagic); stream << qint32(version); - stream << d->qFileDialogUi->splitter->saveState(); - stream << d->qFileDialogUi->sidebar->urls(); + if (d->usingWidgets()) { + stream << d->qFileDialogUi->splitter->saveState(); + stream << d->qFileDialogUi->sidebar->urls(); + } else { + stream << QByteArray(); + stream << QList(); + } stream << history(); stream << *lastVisitedDir(); - stream << d->qFileDialogUi->treeView->header()->saveState(); + if (d->usingWidgets()) + stream << d->qFileDialogUi->treeView->header()->saveState(); + else + stream << QByteArray(); stream << qint32(viewMode()); return data; } @@ -520,6 +526,12 @@ bool QFileDialog::restoreState(const QByteArray &state) >> headerData >> viewMode; + setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir()); + setViewMode(static_cast(viewMode)); + + if (!d->usingWidgets()) + return true; + if (!d->qFileDialogUi->splitter->restoreState(splitterState)) return false; QList list = d->qFileDialogUi->splitter->sizes(); @@ -533,7 +545,6 @@ bool QFileDialog::restoreState(const QByteArray &state) while (history.count() > 5) history.pop_front(); setHistory(history); - setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir()); QHeaderView *headerView = d->qFileDialogUi->treeView->header(); if (!headerView->restoreState(headerData)) return false; @@ -548,7 +559,6 @@ bool QFileDialog::restoreState(const QByteArray &state) for (int i = 1; i < total; ++i) actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i)); - setViewMode(ViewMode(viewMode)); 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(filterSelected(QString)), d, SIGNAL(filterSelected(QString))); static_cast(h)->setOptions(options); + nativeDialogInUse = true; } void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *) { Q_Q(QFileDialog); options->setWindowTitle(q->windowTitle()); - options->setViewMode(static_cast(q->viewMode())); options->setHistory(q->history()); - options->setSidebarUrls(qFileDialogUi->sidebar->urls()); + if (usingWidgets()) + options->setSidebarUrls(qFileDialogUi->sidebar->urls()); const QDir directory = q->directory(); options->setInitialDirectory(directory.exists() ? QUrl::fromLocalFile(directory.absolutePath()) : @@ -644,9 +655,17 @@ void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir) *lastVisitedDir() = dir; } +void QFileDialogPrivate::updateLookInLabel() +{ + if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn)) + setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn)); +} + 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()) { case QFileDialog::DirectoryOnly: 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) { 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() { Q_Q(QFileDialog); /* WIDGETS */ if (defaultFileTypes) q->setNameFilter(QFileDialog::tr("All Files (*)")); + if (nativeDialogInUse) + return; QList actions = qFileDialogUi->treeView->header()->actions(); QAbstractItemModel *abstractModel = model; @@ -708,7 +741,10 @@ void QFileDialogPrivate::retranslateStrings() showHiddenAction->setText(QFileDialog::tr("Show &hidden files")); newFolderAction->setText(QFileDialog::tr("&New Folder")); qFileDialogUi->retranslateUi(q); + updateLookInLabel(); updateFileNameLabel(); + updateFileTypeLabel(); + updateCancelButtonText(); } void QFileDialogPrivate::emitFilesSelected(const QStringList &files) @@ -734,6 +770,11 @@ bool QFileDialogPrivate::canBeNativeDialog() return (staticName == dynamicName); } +bool QFileDialogPrivate::usingWidgets() const +{ + return !nativeDialogInUse && qFileDialogUi; +} + /*! \since 4.5 Sets the given \a option to be enabled if \a on is true; otherwise, @@ -784,29 +825,36 @@ void QFileDialog::setOptions(Options options) return; d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options))); - if (changed & DontResolveSymlinks) - d->model->setResolveSymlinks(!(options & DontResolveSymlinks)); - 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 ((options & DontUseNativeDialog) && !d->usingWidgets()) + d->createWidgets(); + + if (d->usingWidgets()) { + if (changed & DontResolveSymlinks) + d->model->setResolveSymlinks(!(options & DontResolveSymlinks)); + 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) setNameFilters(d->options->nameFilters()); if (changed & ShowDirsOnly) 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 @@ -858,21 +906,25 @@ void QFileDialog::setVisible(bool visible) // updates the state correctly, but skips showing the non-native version: setAttribute(Qt::WA_DontShowOnScreen); #ifndef QT_NO_FSCOMPLETER - //So the completer don't try to complete and therefore to show a popup - d->completer->setModel(0); + // So the completer doesn't try to complete and therefore show a popup + if (!d->nativeDialogInUse) + d->completer->setModel(0); #endif } else { + d->createWidgets(); setAttribute(Qt::WA_DontShowOnScreen, false); #ifndef QT_NO_FSCOMPLETER - if (d->proxyModel != 0) - d->completer->setModel(d->proxyModel); - else - d->completer->setModel(d->model); + if (!d->nativeDialogInUse) { + if (d->proxyModel != 0) + d->completer->setModel(d->proxyModel); + else + d->completer->setModel(d->model); + } #endif } } - if (!d->nativeDialogInUse) + if (d->usingWidgets()) d->qFileDialogUi->fileNameEdit->setFocus(); QDialog::setVisible(visible); @@ -914,24 +966,27 @@ void QFileDialog::setDirectory(const QString &directory) d->setLastVisitedDirectory(newDirectory); - if (d->nativeDialogInUse){ + d->options->setInitialDirectory(QUrl::fromLocalFile(directory)); + if (!d->usingWidgets()) { d->setDirectory_sys(QUrl::fromLocalFile(newDirectory)); return; } if (d->rootPath() == newDirectory) return; QModelIndex root = d->model->setRootPath(newDirectory); - d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled); - if (root != d->rootIndex()) { + if (!d->nativeDialogInUse) { + d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled); + if (root != d->rootIndex()) { #ifndef QT_NO_FSCOMPLETER - if (directory.endsWith(QLatin1Char('/'))) - d->completer->setCompletionPrefix(newDirectory); - else - d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/')); + if (directory.endsWith(QLatin1Char('/'))) + d->completer->setCompletionPrefix(newDirectory); + else + d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/')); #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()) return; - if (d->nativeDialogInUse){ + if (!d->usingWidgets()) { d->selectFile_sys(QUrl::fromLocalFile(filename)); + QList i; + i << QUrl(filename); + d->options->setInitiallySelectedFiles(i); return; } @@ -1141,7 +1199,7 @@ QList QFileDialogPrivate::userSelectedFiles() const { QList files; - if (nativeDialogInUse) + if (!usingWidgets()) return addDefaultSuffixToUrls(selectedFiles_sys()); foreach (const QModelIndex &index, qFileDialogUi->listView->selectionModel()->selectedRows()) @@ -1339,6 +1397,9 @@ void QFileDialog::setNameFilters(const QStringList &filters) } d->options->setNameFilters(cleanedFilters); + if (!d->usingWidgets()) + return; + d->qFileDialogUi->fileTypeCombo->clear(); if (cleanedFilters.isEmpty()) return; @@ -1373,7 +1434,7 @@ QStringList QFileDialog::nameFilters() const void QFileDialog::selectNameFilter(const QString &filter) { Q_D(QFileDialog); - if (d->nativeDialogInUse) { + if (!d->usingWidgets()) { d->selectNameFilter_sys(filter); return; } @@ -1401,7 +1462,7 @@ void QFileDialog::selectNameFilter(const QString &filter) QString QFileDialog::selectedNameFilter() const { Q_D(const QFileDialog); - if (d->nativeDialogInUse) + if (!d->usingWidgets()) return d->selectedNameFilter_sys(); return d->qFileDialogUi->fileTypeCombo->currentText(); @@ -1417,7 +1478,9 @@ QString QFileDialog::selectedNameFilter() const QDir::Filters QFileDialog::filter() const { 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) { Q_D(QFileDialog); - d->model->setFilter(filters); d->options->setFilter(filters); - if (d->nativeDialogInUse){ + if (!d->usingWidgets()) { d->setFilter_sys(); return; } + d->model->setFilter(filters); d->showHiddenAction->setChecked((filters & QDir::Hidden)); } @@ -1523,6 +1586,9 @@ void QFileDialog::selectMimeTypeFilter(const QString &filter) void QFileDialog::setViewMode(QFileDialog::ViewMode mode) { Q_D(QFileDialog); + d->options->setViewMode(static_cast(mode)); + if (!d->usingWidgets()) + return; if (mode == Detail) d->_q_showDetailsView(); else @@ -1532,6 +1598,8 @@ void QFileDialog::setViewMode(QFileDialog::ViewMode mode) QFileDialog::ViewMode QFileDialog::viewMode() const { Q_D(const QFileDialog); + if (!d->usingWidgets()) + return QFileDialog::List; 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); d->options->setFileMode(static_cast(mode)); - d->retranslateWindowTitle(); // keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete) setOption(ShowDirsOnly, mode == DirectoryOnly); + if (!d->usingWidgets()) + return; + + d->retranslateWindowTitle(); + // set selection mode and behavior QAbstractItemView::SelectionMode selectionMode; if (mode == QFileDialog::ExistingFiles) @@ -1577,11 +1649,6 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode) } d->updateFileNameLabel(); d->updateOkButtonText(); - if (d->nativeDialogInUse){ - d->setFilter_sys(); - return; - } - d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly)); d->_q_updateOkButton(); } @@ -1606,6 +1673,13 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode) { Q_D(QFileDialog); d->options->setAcceptMode(static_cast(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); d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel); d->qFileDialogUi->buttonBox->button(button)->setEnabled(false); @@ -1614,10 +1688,6 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode) d->qFileDialogUi->lookInCombo->setEditable(false); } 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) { Q_D(QFileDialog); - d->qFileDialogUi->lookInCombo->setHistory(paths); + if (d->usingWidgets()) + d->qFileDialogUi->lookInCombo->setHistory(paths); } void QFileDialogComboBox::setHistory(const QStringList &paths) @@ -1800,6 +1871,8 @@ void QFileDialogComboBox::setHistory(const QStringList &paths) QStringList QFileDialog::history() const { Q_D(const QFileDialog); + if (!d->usingWidgets()) + return QStringList(); QStringList currentHistory = d->qFileDialogUi->lookInCombo->history(); //On windows the popup display the "C:\", convert to nativeSeparators QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString()); @@ -1826,6 +1899,8 @@ QStringList QFileDialog::history() const void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate) { Q_D(QFileDialog); + if (!d->usingWidgets()) + return; d->qFileDialogUi->listView->setItemDelegate(delegate); d->qFileDialogUi->treeView->setItemDelegate(delegate); } @@ -1836,6 +1911,8 @@ void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate) QAbstractItemDelegate *QFileDialog::itemDelegate() const { Q_D(const QFileDialog); + if (!d->usingWidgets()) + return 0; return d->qFileDialogUi->listView->itemDelegate(); } @@ -1845,6 +1922,8 @@ QAbstractItemDelegate *QFileDialog::itemDelegate() const void QFileDialog::setIconProvider(QFileIconProvider *provider) { Q_D(QFileDialog); + if (!d->usingWidgets()) + return; d->model->setIconProvider(provider); //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()); @@ -1861,6 +1940,8 @@ QFileIconProvider *QFileDialog::iconProvider() const void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text) { + if (!qFileDialogUi) + return; switch (label) { case QFileDialog::LookIn: qFileDialogUi->lookInLabel->setText(text); @@ -1903,8 +1984,10 @@ void QFileDialog::setLabelText(DialogLabel label, const QString &text) */ QString QFileDialog::labelText(DialogLabel label) const { - QPushButton *button; Q_D(const QFileDialog); + if (!d->usingWidgets()) + return d->options->labelText(static_cast(label)); + QPushButton *button; switch (label) { case LookIn: return d->qFileDialogUi->lookInLabel->text(); @@ -2518,7 +2601,7 @@ void QFileDialog::accept() QStringList files = selectedFiles(); if (files.isEmpty()) return; - if (d->nativeDialogInUse){ + if (!d->usingWidgets()) { d->emitFilesSelected(files); QDialog::accept(); return; @@ -2631,16 +2714,19 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte q->setWindowTitle(caption); } - createWidgets(); - createMenuActions(); - retranslateStrings(); + q->setAcceptMode(QFileDialog::AcceptOpen); + nativeDialogInUse = (canBeNativeDialog() && platformFileDialogHelper() != 0); + if (!nativeDialogInUse) + createWidgets(); q->setFileMode(QFileDialog::AnyFile); + if (!nameFilter.isEmpty()) + q->setNameFilter(nameFilter); + q->setDirectory(workingDirectory(directory)); + q->selectFile(initialSelection(directory)); #ifndef QT_NO_SETTINGS QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); settings.beginGroup(QLatin1String("Qt")); - if (!directory.isEmpty()) - setLastVisitedDirectory(workingDirectory(directory)); q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray()); #endif @@ -2650,14 +2736,7 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte qFileDialogUi->fileTypeLabel->setVisible(false); qFileDialogUi->sidebar->hide(); #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()); } @@ -2668,6 +2747,8 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte */ void QFileDialogPrivate::createWidgets() { + if (qFileDialogUi) + return; Q_Q(QFileDialog); model = new QFileSystemModel(q); options->setFilter(model->filter()); @@ -2676,6 +2757,8 @@ void QFileDialogPrivate::createWidgets() model->setNameFilterDisables(helper->defaultNameFilterDisables()); else model->setNameFilterDisables(false); + if (nativeDialogInUse) + deletePlatformHelper(); model->d_func()->disableRecursiveSort = true; QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,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); createToolButtons(); + createMenuActions(); + + // Initial widget states from options + q->setFileMode(static_cast(options->fileMode())); + q->setAcceptMode(static_cast(options->acceptMode())); + q->setViewMode(static_cast(options->viewMode())); + q->setOptions(static_cast(static_cast(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) @@ -2814,6 +2922,8 @@ void QFileDialogPrivate::_q_showHeader(QAction *action) void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel) { Q_D(QFileDialog); + if (!d->usingWidgets()) + return; if ((!proxyModel && !d->proxyModel) || (proxyModel == d->proxyModel)) return; diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index e5a558bb91..36336bdbf6 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -135,8 +135,11 @@ public: QList addDefaultSuffixToUrls(const QList &urlsToFix) const; bool removeDirectory(const QString &path); void setLabelTextControl(QFileDialog::DialogLabel label, const QString &text); + inline void updateLookInLabel(); inline void updateFileNameLabel(); + inline void updateFileTypeLabel(); void updateOkButtonText(bool saveAsOnFolder = false); + void updateCancelButtonText(); inline QModelIndex mapToSource(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 // used instead. bool canBeNativeDialog(); + inline bool usingWidgets() const; void setDirectory_sys(const QUrl &directory); QUrl directory_sys() const; @@ -347,7 +351,7 @@ inline QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) c } inline QString QFileDialogPrivate::rootPath() const { - return model->rootPath(); + return (model ? model->rootPath() : QStringLiteral("/")); } inline void QFileDialogPrivate::setDirectory_sys(const QUrl &directory) diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index 81b69f6b89..8bad4bb176 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -66,6 +66,8 @@ #include #include #endif +#include +#include #include #include @@ -145,6 +147,7 @@ private slots: void clearLineEdit(); void enableChooseButton(); void hooks(); + void widgetlessNativeDialog(); #ifdef Q_OS_UNIX #ifdef QT_BUILD_INTERNAL void tildeExpansion_data(); @@ -1396,6 +1399,20 @@ void tst_QFiledialog::hooks() 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("qt_filesystem_model"); + QVERIFY(!model); + QPushButton *button = fd.findChild(); + QVERIFY(!button); +} + #ifdef Q_OS_UNIX #ifdef QT_BUILD_INTERNAL void tst_QFiledialog::tildeExpansion_data()