aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-08-21 12:15:06 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-09-14 10:09:03 +0000
commit4730221dbce520e6884cd07346ba89c80ec2c466 (patch)
tree0fab1d1ab5afd70c95496538b7aba1152b71058a /src
parent658b0f610a71fab8c103b913d2cfd11c3c7c6bef (diff)
Fix FileDialog::selectedNameFilter review findings
FileDialog::nameFilters contains an array of name filter strings that combine the name and extensions. For example: - "Text files (*.txt)" - "HTML files (*.html *.htm)" When dealing with multiple name filters, it is quite clumsy to use a string type of 'selectedNameFilter' which is one of the above full file name filter string values. Make it possible to read/write the index of the selected name filter, and provide the filter's name and extensions separately. Change-Id: Ie416cc4ab3dcde93c10769b6f7ac44915307f194 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/imports/platform/plugins.qmltypes26
-rw-r--r--src/imports/platform/qquickplatformdialog.cpp6
-rw-r--r--src/imports/platform/qquickplatformdialog_p.h1
-rw-r--r--src/imports/platform/qquickplatformfiledialog.cpp183
-rw-r--r--src/imports/platform/qquickplatformfiledialog_p.h46
-rw-r--r--src/imports/platform/qtlabsplatformplugin.cpp1
6 files changed, 242 insertions, 21 deletions
diff --git a/src/imports/platform/plugins.qmltypes b/src/imports/platform/plugins.qmltypes
index 2bee7276..01d8eb94 100644
--- a/src/imports/platform/plugins.qmltypes
+++ b/src/imports/platform/plugins.qmltypes
@@ -130,12 +130,36 @@ Module {
Property { name: "folder"; type: "QUrl" }
Property { name: "options"; type: "QFileDialogOptions::FileDialogOptions" }
Property { name: "nameFilters"; type: "QStringList" }
- Property { name: "selectedNameFilter"; type: "string" }
+ Property {
+ name: "selectedNameFilter"
+ type: "QQuickPlatformFileNameFilter"
+ isReadonly: true
+ isPointer: true
+ }
Property { name: "defaultSuffix"; type: "string" }
Property { name: "acceptLabel"; type: "string" }
Property { name: "rejectLabel"; type: "string" }
}
Component {
+ name: "QQuickPlatformFileNameFilter"
+ prototype: "QObject"
+ Property { name: "index"; type: "int" }
+ Property { name: "name"; type: "string"; isReadonly: true }
+ Property { name: "extensions"; type: "QStringList"; isReadonly: true }
+ Signal {
+ name: "indexChanged"
+ Parameter { name: "index"; type: "int" }
+ }
+ Signal {
+ name: "nameChanged"
+ Parameter { name: "name"; type: "string" }
+ }
+ Signal {
+ name: "extensionsChanged"
+ Parameter { name: "extensions"; type: "QStringList" }
+ }
+ }
+ Component {
name: "QQuickPlatformFolderDialog"
defaultProperty: "data"
prototype: "QQuickPlatformDialog"
diff --git a/src/imports/platform/qquickplatformdialog.cpp b/src/imports/platform/qquickplatformdialog.cpp
index dee4335d..95bc6426 100644
--- a/src/imports/platform/qquickplatformdialog.cpp
+++ b/src/imports/platform/qquickplatformdialog.cpp
@@ -283,6 +283,7 @@ void QQuickPlatformDialog::close()
if (!m_handle || !m_visible)
return;
+ onHide(m_handle);
m_handle->hide();
m_visible = false;
emit visibleChanged();
@@ -385,6 +386,11 @@ void QQuickPlatformDialog::onShow(QPlatformDialogHelper *dialog)
Q_UNUSED(dialog);
}
+void QQuickPlatformDialog::onHide(QPlatformDialogHelper *dialog)
+{
+ Q_UNUSED(dialog);
+}
+
QWindow *QQuickPlatformDialog::findParentWindow() const
{
QObject *obj = parent();
diff --git a/src/imports/platform/qquickplatformdialog_p.h b/src/imports/platform/qquickplatformdialog_p.h
index 2a5caee7..a9797c1d 100644
--- a/src/imports/platform/qquickplatformdialog_p.h
+++ b/src/imports/platform/qquickplatformdialog_p.h
@@ -129,6 +129,7 @@ protected:
virtual bool useNativeDialog() const;
virtual void onCreate(QPlatformDialogHelper *dialog);
virtual void onShow(QPlatformDialogHelper *dialog);
+ virtual void onHide(QPlatformDialogHelper *dialog);
QWindow *findParentWindow() const;
diff --git a/src/imports/platform/qquickplatformfiledialog.cpp b/src/imports/platform/qquickplatformfiledialog.cpp
index 9da774d4..6a0f4e13 100644
--- a/src/imports/platform/qquickplatformfiledialog.cpp
+++ b/src/imports/platform/qquickplatformfiledialog.cpp
@@ -36,6 +36,8 @@
#include "qquickplatformfiledialog_p.h"
+#include <QtCore/qvector.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -97,7 +99,8 @@ QT_BEGIN_NAMESPACE
QQuickPlatformFileDialog::QQuickPlatformFileDialog(QObject *parent)
: QQuickPlatformDialog(QPlatformTheme::FileDialog, parent),
m_fileMode(OpenFile),
- m_options(QFileDialogOptions::create())
+ m_options(QFileDialogOptions::create()),
+ m_selectedNameFilter(nullptr)
{
m_options->setFileMode(QFileDialogOptions::ExistingFile);
m_options->setAcceptMode(QFileDialogOptions::AcceptOpen);
@@ -335,6 +338,12 @@ void QQuickPlatformFileDialog::setNameFilters(const QStringList &filters)
return;
m_options->setNameFilters(filters);
+ if (m_selectedNameFilter) {
+ int index = m_selectedNameFilter->index();
+ if (index < 0 || index >= filters.count())
+ index = 0;
+ m_selectedNameFilter->update(filters.value(index));
+ }
emit nameFiltersChanged();
}
@@ -344,24 +353,57 @@ void QQuickPlatformFileDialog::resetNameFilters()
}
/*!
- \qmlproperty string Qt.labs.platform::FileDialog::selectedNameFilter
+ \qmlpropertygroup Qt.labs.platform::FileDialog::selectedNameFilter
+ \qmlproperty int Qt.labs.platform::FileDialog::selectedNameFilter.index
+ \qmlproperty string Qt.labs.platform::FileDialog::selectedNameFilter.name
+ \qmlproperty list<string> Qt.labs.platform::FileDialog::selectedNameFilter.extensions
+
+ These properties hold the currently selected name filter.
+
+ \table
+ \header
+ \li Name
+ \li Description
+ \row
+ \li \b index : int
+ \li This property determines which \l {nameFilters}{name filter} is selected.
+ The specified filter is selected when the dialog is opened. The value is
+ updated when the user selects another filter.
+ \row
+ \li [read-only] \b name : string
+ \li This property holds the name of the selected filter. In the
+ example below, the name of the first filter is \c {"Text files"}
+ and the second is \c {"HTML files"}.
+ \row
+ \li [read-only] \b extensions : list<string>
+ \li This property holds the list of extensions of the selected filter.
+ In the example below, the list of extensions of the first filter is
+ \c {["txt"]} and the second is \c {["html", "htm"]}.
+ \endtable
- This property holds the currently selected name filter.
+ \code
+ FileDialog {
+ id: fileDialog
+ selectedNameFilter.index: 1
+ nameFilters: ["Text files (*.txt)", "HTML files (*.html *.htm)"]
+ }
+
+ MyDocument {
+ id: document
+ fileType: fileDialog.selectedNameFilter.extensions[0]
+ }
+ \endcode
\sa nameFilters
*/
-QString QQuickPlatformFileDialog::selectedNameFilter() const
+QQuickPlatformFileNameFilter *QQuickPlatformFileDialog::selectedNameFilter() const
{
- if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle()))
- return fileDialog->selectedNameFilter();
- return m_options->initiallySelectedNameFilter();
-}
-
-void QQuickPlatformFileDialog::setSelectedNameFilter(const QString &filter)
-{
- if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle()))
- fileDialog->selectNameFilter(filter);
- m_options->setInitiallySelectedNameFilter(filter);
+ if (!m_selectedNameFilter) {
+ QQuickPlatformFileDialog *that = const_cast<QQuickPlatformFileDialog *>(this);
+ m_selectedNameFilter = new QQuickPlatformFileNameFilter(that);
+ m_selectedNameFilter->setOptions(m_options);
+ }
+ return m_selectedNameFilter;
}
/*!
@@ -468,7 +510,6 @@ void QQuickPlatformFileDialog::onCreate(QPlatformDialogHelper *dialog)
connect(fileDialog, &QPlatformFileDialogHelper::currentChanged, this, &QQuickPlatformFileDialog::currentFileChanged);
connect(fileDialog, &QPlatformFileDialogHelper::currentChanged, this, &QQuickPlatformFileDialog::currentFilesChanged);
connect(fileDialog, &QPlatformFileDialogHelper::directoryEntered, this, &QQuickPlatformFileDialog::folderChanged);
- connect(fileDialog, &QPlatformFileDialogHelper::filterSelected, this, &QQuickPlatformFileDialog::selectedNameFilterChanged);
fileDialog->setOptions(m_options);
}
}
@@ -476,8 +517,24 @@ void QQuickPlatformFileDialog::onCreate(QPlatformDialogHelper *dialog)
void QQuickPlatformFileDialog::onShow(QPlatformDialogHelper *dialog)
{
m_options->setWindowTitle(title());
- if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog))
+ if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog)) {
fileDialog->setOptions(m_options);
+ if (m_selectedNameFilter) {
+ const int index = m_selectedNameFilter->index();
+ const QString filter = m_options->nameFilters().value(index);
+ m_options->setInitiallySelectedNameFilter(filter);
+ fileDialog->selectNameFilter(filter);
+ connect(fileDialog, &QPlatformFileDialogHelper::filterSelected, m_selectedNameFilter, &QQuickPlatformFileNameFilter::update);
+ }
+ }
+}
+
+void QQuickPlatformFileDialog::onHide(QPlatformDialogHelper *dialog)
+{
+ if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog)) {
+ if (m_selectedNameFilter)
+ disconnect(fileDialog, &QPlatformFileDialogHelper::filterSelected, m_selectedNameFilter, &QQuickPlatformFileNameFilter::update);
+ }
}
void QQuickPlatformFileDialog::accept()
@@ -506,4 +563,98 @@ QList<QUrl> QQuickPlatformFileDialog::addDefaultSuffixes(const QList<QUrl> &file
return urls;
}
+QQuickPlatformFileNameFilter::QQuickPlatformFileNameFilter(QObject *parent)
+ : QObject(parent), m_index(-1)
+{
+}
+
+int QQuickPlatformFileNameFilter::index() const
+{
+ return m_index;
+}
+
+void QQuickPlatformFileNameFilter::setIndex(int index)
+{
+ if (m_index == index)
+ return;
+
+ m_index = index;
+ emit indexChanged(index);
+}
+
+QString QQuickPlatformFileNameFilter::name() const
+{
+ return m_name;
+}
+
+QStringList QQuickPlatformFileNameFilter::extensions() const
+{
+ return m_extensions;
+}
+
+QSharedPointer<QFileDialogOptions> QQuickPlatformFileNameFilter::options() const
+{
+ return m_options;
+}
+
+void QQuickPlatformFileNameFilter::setOptions(const QSharedPointer<QFileDialogOptions> &options)
+{
+ m_options = options;
+}
+
+static QString extractName(const QString &filter)
+{
+ return filter.left(filter.indexOf(QLatin1Char('(')) - 1);
+}
+
+static QString extractExtension(const QString &filter)
+{
+ return filter.mid(filter.indexOf(QLatin1Char('.')) + 1);
+}
+
+static QStringList extractExtensions(const QString &filter)
+{
+ QStringList extensions;
+ const int from = filter.indexOf(QLatin1Char('('));
+ const int to = filter.lastIndexOf(QLatin1Char(')')) - 1;
+ if (from >= 0 && from < to) {
+ const QStringRef ref = filter.midRef(from + 1, to - from);
+ const QVector<QStringRef> exts = ref.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (const QStringRef &ref : exts)
+ extensions += extractExtension(ref.toString());
+ }
+
+ return extensions;
+}
+
+void QQuickPlatformFileNameFilter::update(const QString &filter)
+{
+ const QStringList filters = nameFilters();
+
+ const int oldIndex = m_index;
+ const QString oldName = m_name;
+ const QStringList oldExtensions = m_extensions;
+
+ m_index = filters.indexOf(filter);
+ m_name = extractName(filter);
+ m_extensions = extractExtensions(filter);
+
+ if (oldIndex != m_index)
+ emit indexChanged(m_index);
+ if (oldName != m_name)
+ emit nameChanged(m_name);
+ if (oldExtensions != m_extensions)
+ emit extensionsChanged(m_extensions);
+}
+
+QStringList QQuickPlatformFileNameFilter::nameFilters() const
+{
+ return m_options ? m_options->nameFilters() : QStringList();
+}
+
+QString QQuickPlatformFileNameFilter::nameFilter(int index) const
+{
+ return m_options ? m_options->nameFilters().value(index) : QString();
+}
+
QT_END_NAMESPACE
diff --git a/src/imports/platform/qquickplatformfiledialog_p.h b/src/imports/platform/qquickplatformfiledialog_p.h
index a4c61c54..51f88d46 100644
--- a/src/imports/platform/qquickplatformfiledialog_p.h
+++ b/src/imports/platform/qquickplatformfiledialog_p.h
@@ -54,6 +54,8 @@
QT_BEGIN_NAMESPACE
+class QQuickPlatformFileNameFilter;
+
class QQuickPlatformFileDialog : public QQuickPlatformDialog
{
Q_OBJECT
@@ -65,7 +67,7 @@ class QQuickPlatformFileDialog : public QQuickPlatformDialog
Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged FINAL)
Q_PROPERTY(QFileDialogOptions::FileDialogOptions options READ options WRITE setOptions RESET resetOptions NOTIFY optionsChanged FINAL)
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters RESET resetNameFilters NOTIFY nameFiltersChanged FINAL)
- Q_PROPERTY(QString selectedNameFilter READ selectedNameFilter WRITE setSelectedNameFilter NOTIFY selectedNameFilterChanged FINAL)
+ Q_PROPERTY(QQuickPlatformFileNameFilter *selectedNameFilter READ selectedNameFilter CONSTANT)
Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix RESET resetDefaultSuffix NOTIFY defaultSuffixChanged FINAL)
Q_PROPERTY(QString acceptLabel READ acceptLabel WRITE setAcceptLabel RESET resetAcceptLabel NOTIFY acceptLabelChanged FINAL)
Q_PROPERTY(QString rejectLabel READ rejectLabel WRITE setRejectLabel RESET resetRejectLabel NOTIFY rejectLabelChanged FINAL)
@@ -107,8 +109,7 @@ public:
void setNameFilters(const QStringList &filters);
void resetNameFilters();
- QString selectedNameFilter() const;
- void setSelectedNameFilter(const QString &filter);
+ QQuickPlatformFileNameFilter *selectedNameFilter() const;
QString defaultSuffix() const;
void setDefaultSuffix(const QString &suffix);
@@ -131,7 +132,6 @@ Q_SIGNALS:
void folderChanged();
void optionsChanged();
void nameFiltersChanged();
- void selectedNameFilterChanged();
void defaultSuffixChanged();
void acceptLabelChanged();
void rejectLabelChanged();
@@ -140,6 +140,7 @@ protected:
bool useNativeDialog() const override;
void onCreate(QPlatformDialogHelper *dialog) override;
void onShow(QPlatformDialogHelper *dialog) override;
+ void onHide(QPlatformDialogHelper *dialog) override;
void accept() override;
private:
@@ -149,6 +150,43 @@ private:
FileMode m_fileMode;
QList<QUrl> m_files;
QSharedPointer<QFileDialogOptions> m_options;
+ mutable QQuickPlatformFileNameFilter *m_selectedNameFilter;
+};
+
+class QQuickPlatformFileNameFilter : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged FINAL)
+ Q_PROPERTY(QString name READ name NOTIFY nameChanged FINAL)
+ Q_PROPERTY(QStringList extensions READ extensions NOTIFY extensionsChanged FINAL)
+
+public:
+ explicit QQuickPlatformFileNameFilter(QObject *parent = nullptr);
+
+ int index() const;
+ void setIndex(int index);
+
+ QString name() const;
+ QStringList extensions() const;
+
+ QSharedPointer<QFileDialogOptions> options() const;
+ void setOptions(const QSharedPointer<QFileDialogOptions> &options);
+
+ void update(const QString &filter);
+
+Q_SIGNALS:
+ void indexChanged(int index);
+ void nameChanged(const QString &name);
+ void extensionsChanged(const QStringList &extensions);
+
+private:
+ QStringList nameFilters() const;
+ QString nameFilter(int index) const;
+
+ int m_index;
+ QString m_name;
+ QStringList m_extensions;
+ QSharedPointer<QFileDialogOptions> m_options;
};
QT_END_NAMESPACE
diff --git a/src/imports/platform/qtlabsplatformplugin.cpp b/src/imports/platform/qtlabsplatformplugin.cpp
index 1762e267..f73b04e8 100644
--- a/src/imports/platform/qtlabsplatformplugin.cpp
+++ b/src/imports/platform/qtlabsplatformplugin.cpp
@@ -91,6 +91,7 @@ void QtLabsPlatformPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<QQuickPlatformDialog>(uri, 1, 0, "Dialog", QQuickPlatformDialog::tr("Dialog is an abstract base class"));
qmlRegisterType<QQuickPlatformColorDialog>(uri, 1, 0, "ColorDialog");
qmlRegisterType<QQuickPlatformFileDialog>(uri, 1, 0, "FileDialog");
+ qmlRegisterType<QQuickPlatformFileNameFilter>();
qmlRegisterType<QQuickPlatformFolderDialog>(uri, 1, 0, "FolderDialog");
qmlRegisterType<QQuickPlatformFontDialog>(uri, 1, 0, "FontDialog");
qmlRegisterType<QQuickPlatformMessageDialog>(uri, 1, 0, "MessageDialog");