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 <frederik.gladhorn@digia.com>
This commit is contained in:
David Faure 2013-08-27 14:10:45 +02:00 committed by The Qt Project
parent 468b539935
commit ee9b9d9fd9
7 changed files with 135 additions and 5 deletions

View File

@ -359,6 +359,7 @@ public:
QDir::Filters filters; QDir::Filters filters;
QList<QUrl> sidebarUrls; QList<QUrl> sidebarUrls;
QStringList nameFilters; QStringList nameFilters;
QStringList mimeTypeFilters;
QString defaultSuffix; QString defaultSuffix;
QStringList history; QStringList history;
QUrl initialDirectory; QUrl initialDirectory;
@ -477,6 +478,16 @@ QStringList QFileDialogOptions::nameFilters() const
return d->nameFilters; 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) void QFileDialogOptions::setDefaultSuffix(const QString &suffix)
{ {
d->defaultSuffix = suffix; d->defaultSuffix = suffix;

View File

@ -265,6 +265,9 @@ public:
void setNameFilters(const QStringList &filters); void setNameFilters(const QStringList &filters);
QStringList nameFilters() const; QStringList nameFilters() const;
void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
void setDefaultSuffix(const QString &suffix); void setDefaultSuffix(const QString &suffix);
QString defaultSuffix() const; QString defaultSuffix() const;

View File

@ -57,6 +57,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <qsettings.h> #include <qsettings.h>
#include <qdebug.h> #include <qdebug.h>
#include <qmimedatabase.h>
#include <qapplication.h> #include <qapplication.h>
#include <qstylepainter.h> #include <qstylepainter.h>
#if !defined(Q_OS_WINCE) #if !defined(Q_OS_WINCE)
@ -1441,6 +1442,75 @@ void QFileDialog::setFilter(QDir::Filters filters)
d->showHiddenAction->setChecked((filters & QDir::Hidden)); 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 \property QFileDialog::viewMode
\brief the way files and directories are displayed in the dialog \brief the way files and directories are displayed in the dialog

View File

@ -124,6 +124,10 @@ public:
void selectNameFilter(const QString &filter); void selectNameFilter(const QString &filter);
QString selectedNameFilter() const; QString selectedNameFilter() const;
void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
void selectMimeTypeFilter(const QString &filter);
QDir::Filters filter() const; QDir::Filters filter() const;
void setFilter(QDir::Filters filters); void setFilter(QDir::Filters filters);

View File

@ -129,3 +129,14 @@ QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
QFileDialog::ShowDirsOnly QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks); | QFileDialog::DontResolveSymlinks);
//! [12] //! [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]

View File

@ -162,6 +162,7 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
, m_defaultSuffix(new QLineEdit(this)) , m_defaultSuffix(new QLineEdit(this))
, m_directory(new QLineEdit(this)) , m_directory(new QLineEdit(this))
, m_selectedFileName(new QLineEdit(this)) , m_selectedFileName(new QLineEdit(this))
, m_useMimeTypeFilters(new QCheckBox(this))
, m_nameFilters(new QPlainTextEdit) , m_nameFilters(new QPlainTextEdit)
, m_selectedNameFilter(new QLineEdit(this)) , m_selectedNameFilter(new QLineEdit(this))
, m_deleteNonModalDialogButton(0) , m_deleteNonModalDialogButton(0)
@ -183,10 +184,11 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
// Files // Files
QGroupBox *filesGroupBox = new QGroupBox(tr("Files / Filters")); 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("Default Suffix:"), m_defaultSuffix);
filesLayout->addRow(tr("Directory:"), m_directory); filesLayout->addRow(tr("Directory:"), m_directory);
filesLayout->addRow(tr("Selected file:"), m_selectedFileName); filesLayout->addRow(tr("Selected file:"), m_selectedFileName);
filesLayout->addRow(tr("Use mime type filters:"), m_useMimeTypeFilters);
m_nameFilters->setMaximumHeight(80); m_nameFilters->setMaximumHeight(80);
filesLayout->addRow(tr("Name filters:"), m_nameFilters); filesLayout->addRow(tr("Name filters:"), m_nameFilters);
filesLayout->addRow(tr("Selected name filter:"), m_selectedNameFilter); filesLayout->addRow(tr("Selected name filter:"), m_selectedNameFilter);
@ -236,6 +238,8 @@ FileDialogPanel::FileDialogPanel(QWidget *parent)
gridLayout->addWidget(labelsGroupBox, 1, 0); gridLayout->addWidget(labelsGroupBox, 1, 0);
gridLayout->addWidget(buttonsGroupBox, 1, 1); gridLayout->addWidget(buttonsGroupBox, 1, 1);
connect(m_useMimeTypeFilters, SIGNAL(toggled(bool)), this, SLOT(useMimeTypeFilters(bool)));
enableDeleteModalDialogButton(); enableDeleteModalDialogButton();
enableDeleteNonModalDialogButton(); enableDeleteNonModalDialogButton();
restoreDefaults(); restoreDefaults();
@ -461,7 +465,8 @@ void FileDialogPanel::restoreDefaults()
m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons)); m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons));
m_directory->setText(QDir::homePath()); m_directory->setText(QDir::homePath());
m_defaultSuffix->setText(QLatin1String("txt")); 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_selectedFileName->setText(QString());
m_selectedNameFilter->setText(QString()); m_selectedNameFilter->setText(QString());
foreach (LabelLineEdit *l, m_labelLineEdits) foreach (LabelLineEdit *l, m_labelLineEdits)
@ -481,14 +486,36 @@ void FileDialogPanel::applySettings(QFileDialog *d) const
const QString file = m_selectedFileName->text().trimmed(); const QString file = m_selectedFileName->text().trimmed();
if (!file.isEmpty()) if (!file.isEmpty())
d->selectFile(file); d->selectFile(file);
d->setNameFilters(m_nameFilters->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts));
const QString filter = m_selectedNameFilter->text().trimmed(); const QString filter = m_selectedNameFilter->text().trimmed();
if (!filter.isEmpty()) const QStringList filters = m_nameFilters->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts);
d->selectNameFilter(filter); 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) foreach (LabelLineEdit *l, m_labelLineEdits)
l->apply(d); l->apply(d);
} }
void FileDialogPanel::useMimeTypeFilters(bool b)
{
QWidget *textEdit = filesLayout->labelForField(m_nameFilters);
if (QLabel *label = qobject_cast<QLabel *>(textEdit))
label->setText(b ? tr("Mime type filters:") : tr("Name filters:"));
QWidget *w = filesLayout->labelForField(m_selectedNameFilter);
if (QLabel *label = qobject_cast<QLabel *>(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() void FileDialogPanel::accepted()
{ {
const QFileDialog *d = qobject_cast<const QFileDialog *>(sender()); const QFileDialog *d = qobject_cast<const QFileDialog *>(sender());

View File

@ -52,6 +52,7 @@ class QCheckBox;
class QComboBox; class QComboBox;
class QLineEdit; class QLineEdit;
class QPlainTextEdit; class QPlainTextEdit;
class QFormLayout;
QT_END_NAMESPACE QT_END_NAMESPACE
class LabelLineEdit; class LabelLineEdit;
@ -82,6 +83,7 @@ public slots:
private slots: private slots:
void enableDeleteNonModalDialogButton(); void enableDeleteNonModalDialogButton();
void enableDeleteModalDialogButton(); void enableDeleteModalDialogButton();
void useMimeTypeFilters(bool);
private: private:
QString filterString() const; QString filterString() const;
@ -89,6 +91,7 @@ private:
QStringList allowedSchemes() const; QStringList allowedSchemes() const;
void applySettings(QFileDialog *d) const; void applySettings(QFileDialog *d) const;
QFormLayout *filesLayout;
QCheckBox *m_readOnly; QCheckBox *m_readOnly;
QCheckBox *m_confirmOverWrite; QCheckBox *m_confirmOverWrite;
QCheckBox *m_nameFilterDetailsVisible; QCheckBox *m_nameFilterDetailsVisible;
@ -103,6 +106,7 @@ private:
QLineEdit *m_directory; QLineEdit *m_directory;
QLineEdit *m_selectedFileName; QLineEdit *m_selectedFileName;
QList<LabelLineEdit *> m_labelLineEdits; QList<LabelLineEdit *> m_labelLineEdits;
QCheckBox *m_useMimeTypeFilters;
QPlainTextEdit *m_nameFilters; QPlainTextEdit *m_nameFilters;
QLineEdit *m_selectedNameFilter; QLineEdit *m_selectedNameFilter;
QPushButton *m_deleteNonModalDialogButton; QPushButton *m_deleteNonModalDialogButton;