FileUtils:: Support non-native filedialog

Change-Id: I71797a31c58f0870a95ac396404721b004741115
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-10-12 11:59:51 +02:00
parent e8eaf7809b
commit 34fbf6261a
2 changed files with 119 additions and 75 deletions

View File

@@ -476,6 +476,72 @@ static QWidget *dialogParent(QWidget *parent)
return parent ? parent : s_dialogParentGetter ? s_dialogParentGetter() : nullptr; return parent ? parent : s_dialogParentGetter ? s_dialogParentGetter() : nullptr;
} }
FilePath qUrlToFilePath(const QUrl &url)
{
if (url.isLocalFile())
return FilePath::fromString(url.toLocalFile());
return FilePath::fromUrl(url);
}
QUrl filePathToQUrl(const FilePath &filePath)
{
return QUrl::fromLocalFile(filePath.toFSPathString());
}
void prepareNonNativeDialog(QFileDialog &dialog)
{
// Checking QFileDialog::itemDelegate() seems to be the only way to determine
// whether the dialog is native or not.
if (dialog.itemDelegate()) {
QList<QUrl> sideBarUrls;
for (const FilePath &path : FSEngine::registeredDeviceRoots()) {
if (path.exists())
sideBarUrls.append(filePathToQUrl(path));
}
dialog.setSidebarUrls(sideBarUrls);
dialog.setIconProvider(Utils::FileIconProvider::iconProvider());
}
}
FilePaths getFilePaths(QWidget *parent,
const QString &caption,
const FilePath &dir,
const QString &filter,
QString *selectedFilter,
QFileDialog::Options options,
const QStringList &supportedSchemes,
const bool forceNonNativeDialog,
QFileDialog::FileMode fileMode,
QFileDialog::AcceptMode acceptMode)
{
QFileDialog dialog(parent, caption, dir.toFSPathString(), filter);
dialog.setFileMode(fileMode);
if (forceNonNativeDialog)
options.setFlag(QFileDialog::DontUseNativeDialog);
dialog.setOptions(options);
prepareNonNativeDialog(dialog);
dialog.setSupportedSchemes(supportedSchemes);
dialog.setAcceptMode(acceptMode);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
if (dialog.exec() == QDialog::Accepted) {
if (selectedFilter)
*selectedFilter = dialog.selectedNameFilter();
return Utils::transform(dialog.selectedUrls(), &qUrlToFilePath);
}
return {};
}
FilePath firstOrEmpty(const FilePaths &filePaths)
{
return filePaths.isEmpty() ? FilePath() : filePaths.first();
}
FilePath FileUtils::getOpenFilePath(QWidget *parent, FilePath FileUtils::getOpenFilePath(QWidget *parent,
const QString &caption, const QString &caption,
const FilePath &dir, const FilePath &dir,
@@ -484,19 +550,24 @@ FilePath FileUtils::getOpenFilePath(QWidget *parent,
QFileDialog::Options options, QFileDialog::Options options,
bool fromDeviceIfShiftIsPressed) bool fromDeviceIfShiftIsPressed)
{ {
bool forceNonNativeDialog = dir.needsDevice();
#ifdef QT_GUI_LIB #ifdef QT_GUI_LIB
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) { if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
return getOpenFilePathFromDevice(parent, caption, dir, filter, selectedFilter, options); forceNonNativeDialog = true;
} }
#endif #endif
const QString result = QFileDialog::getOpenFileName(dialogParent(parent), const QStringList schemes = QStringList(QStringLiteral("file"));
caption, return firstOrEmpty(getFilePaths(dialogParent(parent),
dir.toString(), caption,
filter, dir,
selectedFilter, filter,
options); selectedFilter,
return FilePath::fromString(result); options,
schemes,
forceNonNativeDialog,
QFileDialog::ExistingFile,
QFileDialog::AcceptOpen));
} }
FilePath FileUtils::getSaveFilePath(QWidget *parent, FilePath FileUtils::getSaveFilePath(QWidget *parent,
@@ -506,13 +577,19 @@ FilePath FileUtils::getSaveFilePath(QWidget *parent,
QString *selectedFilter, QString *selectedFilter,
QFileDialog::Options options) QFileDialog::Options options)
{ {
const QString result = QFileDialog::getSaveFileName(dialogParent(parent), bool forceNonNativeDialog = dir.needsDevice();
caption,
dir.toString(), const QStringList schemes = QStringList(QStringLiteral("file"));
filter, return firstOrEmpty(getFilePaths(dialogParent(parent),
selectedFilter, caption,
options); dir,
return FilePath::fromString(result); filter,
selectedFilter,
options,
schemes,
forceNonNativeDialog,
QFileDialog::AnyFile,
QFileDialog::AcceptSave));
} }
FilePath FileUtils::getExistingDirectory(QWidget *parent, FilePath FileUtils::getExistingDirectory(QWidget *parent,
@@ -520,11 +597,19 @@ FilePath FileUtils::getExistingDirectory(QWidget *parent,
const FilePath &dir, const FilePath &dir,
QFileDialog::Options options) QFileDialog::Options options)
{ {
const QString result = QFileDialog::getExistingDirectory(dialogParent(parent), bool forceNonNativeDialog = dir.needsDevice();
caption,
dir.toString(), const QStringList schemes = QStringList(QStringLiteral("file"));
options); return firstOrEmpty(getFilePaths(dialogParent(parent),
return FilePath::fromString(result); caption,
dir,
{},
nullptr,
options,
schemes,
forceNonNativeDialog,
QFileDialog::Directory,
QFileDialog::AcceptOpen));
} }
FilePaths FileUtils::getOpenFilePaths(QWidget *parent, FilePaths FileUtils::getOpenFilePaths(QWidget *parent,
@@ -534,54 +619,19 @@ FilePaths FileUtils::getOpenFilePaths(QWidget *parent,
QString *selectedFilter, QString *selectedFilter,
QFileDialog::Options options) QFileDialog::Options options)
{ {
const QStringList result = QFileDialog::getOpenFileNames(dialogParent(parent), bool forceNonNativeDialog = dir.needsDevice();
caption,
dir.toString(),
filter,
selectedFilter,
options);
return FileUtils::toFilePathList(result);
}
FilePath FileUtils::getOpenFilePathFromDevice(QWidget *parent, const QStringList schemes = QStringList(QStringLiteral("file"));
const QString &caption, return getFilePaths(dialogParent(parent),
const FilePath &dir, caption,
const QString &filter, dir,
QString *selectedFilter, filter,
QFileDialog::Options options) selectedFilter,
{ options,
QFileDialog dialog(parent); schemes,
dialog.setOptions(options | QFileDialog::DontUseNativeDialog); forceNonNativeDialog,
dialog.setWindowTitle(caption); QFileDialog::ExistingFiles,
dialog.setDirectory(dir.toString()); QFileDialog::AcceptOpen);
dialog.setNameFilter(filter);
QList<QUrl> sideBarUrls = Utils::transform(Utils::filtered(FSEngine::registeredDeviceRoots(),
[](const auto &filePath) {
return filePath.exists();
}),
[](const auto &filePath) {
return QUrl::fromLocalFile(
filePath.toFSPathString());
});
dialog.setSidebarUrls(sideBarUrls);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setIconProvider(Utils::FileIconProvider::iconProvider());
if (dialog.exec()) {
FilePaths filePaths = Utils::transform(dialog.selectedFiles(), [](const auto &path) {
return FilePath::fromString(path);
});
if (selectedFilter) {
*selectedFilter = dialog.selectedNameFilter();
}
return filePaths.first();
}
return {};
} }
#endif // QT_WIDGETS_LIB #endif // QT_WIDGETS_LIB
@@ -716,7 +766,8 @@ static bool iterateWithFindHelper(
// Remove the first line, it is always the directory we are searching in. // Remove the first line, it is always the directory we are searching in.
// as long as we do not specify "mindepth > 0" // as long as we do not specify "mindepth > 0"
entries.pop_front(); if (entries.size() > 0)
entries.pop_front();
for (const QString &entry : entries) { for (const QString &entry : entries) {
if (!callBack(entry)) if (!callBack(entry))
break; break;

View File

@@ -126,13 +126,6 @@ public:
const QString &filter = {}, const QString &filter = {},
QString *selectedFilter = nullptr, QString *selectedFilter = nullptr,
QFileDialog::Options options = {}); QFileDialog::Options options = {});
static FilePath getOpenFilePathFromDevice(QWidget *parent,
const QString &caption,
const FilePath &dir = {},
const QString &filter = {},
QString *selectedFilter = nullptr,
QFileDialog::Options options = {});
#endif #endif
}; };