From ee9b9d9fd9a714f97ed8f7e26404c2f113588e9c Mon Sep 17 00:00:00 2001 From: David Faure Date: Tue, 27 Aug 2013 14:10:45 +0200 Subject: QFileDialog: add MIME Type filters Currently just a convenience method for setNameFilters(), it uses QMimeType to create a name filter from the glob patterns and description defined in each MIME type. In the longer term, this API could be used to do proper mimetype-based filtering using QMimeDatabase::mimeTypeForFile() in the builtin QFileDialog (aka "not native"), instead of only looking at globs via the name filters. Change-Id: I0edccf5f30c514481b47cd100d743d1ed7a24024 Reviewed-by: Frederik Gladhorn --- src/gui/kernel/qplatformdialoghelper.cpp | 11 ++++ src/gui/kernel/qplatformdialoghelper.h | 3 + src/widgets/dialogs/qfiledialog.cpp | 70 ++++++++++++++++++++++ src/widgets/dialogs/qfiledialog.h | 4 ++ .../snippets/code/src_gui_dialogs_qfiledialog.cpp | 11 ++++ tests/manual/dialogs/filedialogpanel.cpp | 37 ++++++++++-- tests/manual/dialogs/filedialogpanel.h | 4 ++ 7 files changed, 135 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index d9e9c4b17c..404700292c 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -359,6 +359,7 @@ public: QDir::Filters filters; QList sidebarUrls; QStringList nameFilters; + QStringList mimeTypeFilters; QString defaultSuffix; QStringList history; QUrl initialDirectory; @@ -477,6 +478,16 @@ QStringList QFileDialogOptions::nameFilters() const return d->nameFilters; } +void QFileDialogOptions::setMimeTypeFilters(const QStringList &filters) +{ + d->mimeTypeFilters = filters; +} + +QStringList QFileDialogOptions::mimeTypeFilters() const +{ + return d->mimeTypeFilters; +} + void QFileDialogOptions::setDefaultSuffix(const QString &suffix) { d->defaultSuffix = suffix; diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 6d7d52ccb1..5269416ffd 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -265,6 +265,9 @@ public: void setNameFilters(const QStringList &filters); QStringList nameFilters() const; + void setMimeTypeFilters(const QStringList &filters); + QStringList mimeTypeFilters() const; + void setDefaultSuffix(const QString &suffix); QString defaultSuffix() const; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 9c4b99253a..62cec34b2b 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #if !defined(Q_OS_WINCE) @@ -1441,6 +1442,75 @@ void QFileDialog::setFilter(QDir::Filters filters) d->showHiddenAction->setChecked((filters & QDir::Hidden)); } +static QString nameFilterForMime(const QString &mimeType) +{ + QMimeDatabase db; + QMimeType mime(db.mimeTypeForName(mimeType)); + if (mime.isValid()) { + if (mime.isDefault()) { + return QFileDialog::tr("All files (*)"); + } else { + const QString patterns = mime.globPatterns().join(QLatin1Char(' ')); + return mime.comment() + QStringLiteral(" (") + patterns + QLatin1Char(')'); + } + } + return QString(); +} + +/*! + \since 5.2 + + Sets the \a filters used in the file dialog, from a list of MIME types. + + Convenience method for setNameFilters(). + Uses QMimeType to create a name filter from the glob patterns and description + defined in each MIME type. + + Use application/octet-stream for the "All files (*)" filter, since that + is the base MIME type for all files. + + Calling setMimeTypeFilters overrides any previously set name filters, + and changes the return value of nameFilters(). + + \snippet code/src_gui_dialogs_qfiledialog.cpp 13 +*/ +void QFileDialog::setMimeTypeFilters(const QStringList &filters) +{ + Q_D(QFileDialog); + QStringList nameFilters; + foreach (const QString &mimeType, filters) { + const QString text = nameFilterForMime(mimeType); + if (!text.isEmpty()) + nameFilters.append(text); + } + setNameFilters(nameFilters); + d->options->setMimeTypeFilters(filters); +} + +/*! + \since 5.2 + + Returns the MIME type filters that are in operation on this file + dialog. +*/ +QStringList QFileDialog::mimeTypeFilters() const +{ + return d_func()->options->mimeTypeFilters(); +} + +/*! + \since 5.2 + + Sets the current MIME type \a filter. + +*/ +void QFileDialog::selectMimeTypeFilter(const QString &filter) +{ + const QString text = nameFilterForMime(filter); + if (!text.isEmpty()) + selectNameFilter(text); +} + /*! \property QFileDialog::viewMode \brief the way files and directories are displayed in the dialog diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 5413a42ea9..404e16cde1 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -124,6 +124,10 @@ public: void selectNameFilter(const QString &filter); QString selectedNameFilter() const; + void setMimeTypeFilters(const QStringList &filters); + QStringList mimeTypeFilters() const; + void selectMimeTypeFilter(const QString &filter); + QDir::Filters filter() const; void setFilter(QDir::Filters filters); diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp index a253c09d8b..f0010b6f25 100644 --- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp +++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp @@ -129,3 +129,14 @@ QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); //! [12] + +//! [13] +QStringList mimeTypeFilters; +mimeTypeFilters << "image/jpeg" // will show "JPEG image (*.jpeg *.jpg *.jpe) + << "image/png" // will show "PNG image (*.png)" + << "application/octet-stream"; // will show "All files (*)" + +QFileDialog dialog(this); +dialog.setMimeTypeFilters(mimeTypeFilters); +dialog.exec(); +//! [13] diff --git a/tests/manual/dialogs/filedialogpanel.cpp b/tests/manual/dialogs/filedialogpanel.cpp index 000d755cef..e234835cdb 100644 --- a/tests/manual/dialogs/filedialogpanel.cpp +++ b/tests/manual/dialogs/filedialogpanel.cpp @@ -162,6 +162,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) , m_defaultSuffix(new QLineEdit(this)) , m_directory(new QLineEdit(this)) , m_selectedFileName(new QLineEdit(this)) + , m_useMimeTypeFilters(new QCheckBox(this)) , m_nameFilters(new QPlainTextEdit) , m_selectedNameFilter(new QLineEdit(this)) , m_deleteNonModalDialogButton(0) @@ -183,10 +184,11 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) // Files QGroupBox *filesGroupBox = new QGroupBox(tr("Files / Filters")); - QFormLayout *filesLayout = new QFormLayout(filesGroupBox); + filesLayout = new QFormLayout(filesGroupBox); filesLayout->addRow(tr("Default Suffix:"), m_defaultSuffix); filesLayout->addRow(tr("Directory:"), m_directory); filesLayout->addRow(tr("Selected file:"), m_selectedFileName); + filesLayout->addRow(tr("Use mime type filters:"), m_useMimeTypeFilters); m_nameFilters->setMaximumHeight(80); filesLayout->addRow(tr("Name filters:"), m_nameFilters); filesLayout->addRow(tr("Selected name filter:"), m_selectedNameFilter); @@ -236,6 +238,8 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) gridLayout->addWidget(labelsGroupBox, 1, 0); gridLayout->addWidget(buttonsGroupBox, 1, 1); + connect(m_useMimeTypeFilters, SIGNAL(toggled(bool)), this, SLOT(useMimeTypeFilters(bool))); + enableDeleteModalDialogButton(); enableDeleteNonModalDialogButton(); restoreDefaults(); @@ -461,7 +465,8 @@ void FileDialogPanel::restoreDefaults() m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons)); m_directory->setText(QDir::homePath()); m_defaultSuffix->setText(QLatin1String("txt")); - m_nameFilters->setPlainText(QLatin1String("Any files (*)\nImage files (*.png *.xpm *.jpg)\nText files (*.txt)")); + m_useMimeTypeFilters->setChecked(false); + useMimeTypeFilters(false); m_selectedFileName->setText(QString()); m_selectedNameFilter->setText(QString()); foreach (LabelLineEdit *l, m_labelLineEdits) @@ -481,14 +486,36 @@ void FileDialogPanel::applySettings(QFileDialog *d) const const QString file = m_selectedFileName->text().trimmed(); if (!file.isEmpty()) d->selectFile(file); - d->setNameFilters(m_nameFilters->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts)); const QString filter = m_selectedNameFilter->text().trimmed(); - if (!filter.isEmpty()) - d->selectNameFilter(filter); + const QStringList filters = m_nameFilters->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts); + if (!m_useMimeTypeFilters->isChecked()) { + d->setNameFilters(filters); + if (!filter.isEmpty()) + d->selectNameFilter(filter); + } else { + d->setMimeTypeFilters(filters); + if (!filter.isEmpty()) + d->selectMimeTypeFilter(filter); + } foreach (LabelLineEdit *l, m_labelLineEdits) l->apply(d); } +void FileDialogPanel::useMimeTypeFilters(bool b) +{ + QWidget *textEdit = filesLayout->labelForField(m_nameFilters); + if (QLabel *label = qobject_cast(textEdit)) + label->setText(b ? tr("Mime type filters:") : tr("Name filters:")); + QWidget *w = filesLayout->labelForField(m_selectedNameFilter); + if (QLabel *label = qobject_cast(w)) + label->setText(b ? tr("Selected mime type filter:") : tr("Selected name filter:")); + + if (b) + m_nameFilters->setPlainText(QLatin1String("image/jpeg\nimage/png\ntext/plain\napplication/octet-stream")); + else + m_nameFilters->setPlainText(QLatin1String("Any files (*)\nImage files (*.png *.xpm *.jpg)\nText files (*.txt)")); +} + void FileDialogPanel::accepted() { const QFileDialog *d = qobject_cast(sender()); diff --git a/tests/manual/dialogs/filedialogpanel.h b/tests/manual/dialogs/filedialogpanel.h index 2e1d5d4de9..1e86e0f18e 100644 --- a/tests/manual/dialogs/filedialogpanel.h +++ b/tests/manual/dialogs/filedialogpanel.h @@ -52,6 +52,7 @@ class QCheckBox; class QComboBox; class QLineEdit; class QPlainTextEdit; +class QFormLayout; QT_END_NAMESPACE class LabelLineEdit; @@ -82,6 +83,7 @@ public slots: private slots: void enableDeleteNonModalDialogButton(); void enableDeleteModalDialogButton(); + void useMimeTypeFilters(bool); private: QString filterString() const; @@ -89,6 +91,7 @@ private: QStringList allowedSchemes() const; void applySettings(QFileDialog *d) const; + QFormLayout *filesLayout; QCheckBox *m_readOnly; QCheckBox *m_confirmOverWrite; QCheckBox *m_nameFilterDetailsVisible; @@ -103,6 +106,7 @@ private: QLineEdit *m_directory; QLineEdit *m_selectedFileName; QList m_labelLineEdits; + QCheckBox *m_useMimeTypeFilters; QPlainTextEdit *m_nameFilters; QLineEdit *m_selectedNameFilter; QPushButton *m_deleteNonModalDialogButton; -- cgit v1.2.3