Fallback to another file dialog implementation when XDP is inaccessible
Fixes: QTBUG-98988 Change-Id: Idca1ab4cae0e9eabebc599f3c8efa136a7973918 Reviewed-by: Jan Grulich <jgrulich@redhat.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit fb981a0954119ed0dfa4a402fdef78e7257ffc96)
This commit is contained in:
parent
96bf7b01f6
commit
c5883aeb88
@ -69,15 +69,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile
|
|||||||
class QXdgDesktopPortalFileDialogPrivate
|
class QXdgDesktopPortalFileDialogPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
|
QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
|
||||||
: nativeFileDialog(nativeFileDialog)
|
: nativeFileDialog(nativeFileDialog)
|
||||||
|
, fileChooserPortalVersion(fileChooserPortalVersion)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
WId winId = 0;
|
QEventLoop loop;
|
||||||
bool directoryMode = false;
|
|
||||||
bool modal = false;
|
|
||||||
bool multipleFiles = false;
|
|
||||||
bool saveFile = false;
|
|
||||||
QString acceptLabel;
|
QString acceptLabel;
|
||||||
QString directory;
|
QString directory;
|
||||||
QString title;
|
QString title;
|
||||||
@ -89,11 +86,16 @@ public:
|
|||||||
QString selectedNameFilter;
|
QString selectedNameFilter;
|
||||||
QStringList selectedFiles;
|
QStringList selectedFiles;
|
||||||
std::unique_ptr<QPlatformFileDialogHelper> nativeFileDialog;
|
std::unique_ptr<QPlatformFileDialogHelper> nativeFileDialog;
|
||||||
|
uint fileChooserPortalVersion = 0;
|
||||||
|
bool failedToOpen = false;
|
||||||
|
bool directoryMode = false;
|
||||||
|
bool multipleFiles = false;
|
||||||
|
bool saveFile = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
|
QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
|
||||||
: QPlatformFileDialogHelper()
|
: QPlatformFileDialogHelper()
|
||||||
, d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
|
, d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
|
||||||
{
|
{
|
||||||
Q_D(QXdgDesktopPortalFileDialog);
|
Q_D(QXdgDesktopPortalFileDialog);
|
||||||
|
|
||||||
@ -101,6 +103,9 @@ QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelp
|
|||||||
connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
|
connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
|
||||||
connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
|
connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->loop.connect(this, SIGNAL(accept()), SLOT(quit()));
|
||||||
|
d->loop.connect(this, SIGNAL(reject()), SLOT(quit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
|
QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
|
||||||
@ -144,7 +149,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
|
|||||||
setDirectory(options()->initialDirectory());
|
setDirectory(options()->initialDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXdgDesktopPortalFileDialog::openPortal()
|
void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
|
||||||
{
|
{
|
||||||
Q_D(QXdgDesktopPortalFileDialog);
|
Q_D(QXdgDesktopPortalFileDialog);
|
||||||
|
|
||||||
@ -152,13 +157,13 @@ void QXdgDesktopPortalFileDialog::openPortal()
|
|||||||
"/org/freedesktop/portal/desktop"_L1,
|
"/org/freedesktop/portal/desktop"_L1,
|
||||||
"org.freedesktop.portal.FileChooser"_L1,
|
"org.freedesktop.portal.FileChooser"_L1,
|
||||||
d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
|
d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
|
||||||
QString parentWindowId = "x11:"_L1 + QString::number(d->winId, 16);
|
QString parentWindowId = "x11:"_L1 + QString::number(parent ? parent->winId() : 0, 16);
|
||||||
|
|
||||||
QVariantMap options;
|
QVariantMap options;
|
||||||
if (!d->acceptLabel.isEmpty())
|
if (!d->acceptLabel.isEmpty())
|
||||||
options.insert("accept_label"_L1, d->acceptLabel);
|
options.insert("accept_label"_L1, d->acceptLabel);
|
||||||
|
|
||||||
options.insert("modal"_L1, d->modal);
|
options.insert("modal"_L1, windowModality != Qt::NonModal);
|
||||||
options.insert("multiple"_L1, d->multipleFiles);
|
options.insert("multiple"_L1, d->multipleFiles);
|
||||||
options.insert("directory"_L1, d->directoryMode);
|
options.insert("directory"_L1, d->directoryMode);
|
||||||
|
|
||||||
@ -261,10 +266,18 @@ void QXdgDesktopPortalFileDialog::openPortal()
|
|||||||
|
|
||||||
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
|
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
|
||||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
|
||||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
|
connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher *watcher) {
|
||||||
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
|
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
|
||||||
if (reply.isError()) {
|
// Any error means the dialog is not shown and we need to fallback
|
||||||
Q_EMIT reject();
|
d->failedToOpen = reply.isError();
|
||||||
|
if (d->failedToOpen) {
|
||||||
|
if (d->nativeFileDialog) {
|
||||||
|
d->nativeFileDialog->show(windowFlags, windowModality, parent);
|
||||||
|
if (d->loop.isRunning())
|
||||||
|
d->nativeFileDialog->exec();
|
||||||
|
} else {
|
||||||
|
Q_EMIT reject();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
QDBusConnection::sessionBus().connect(nullptr,
|
QDBusConnection::sessionBus().connect(nullptr,
|
||||||
reply.value().path(),
|
reply.value().path(),
|
||||||
@ -381,10 +394,7 @@ void QXdgDesktopPortalFileDialog::exec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
|
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
|
||||||
QEventLoop loop;
|
d->loop.exec();
|
||||||
loop.connect(this, SIGNAL(accept()), SLOT(quit()));
|
|
||||||
loop.connect(this, SIGNAL(reject()), SLOT(quit()));
|
|
||||||
loop.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXdgDesktopPortalFileDialog::hide()
|
void QXdgDesktopPortalFileDialog::hide()
|
||||||
@ -401,13 +411,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
|
|||||||
|
|
||||||
initializeDialog();
|
initializeDialog();
|
||||||
|
|
||||||
d->modal = windowModality != Qt::NonModal;
|
if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
|
||||||
d->winId = parent ? parent->winId() : 0;
|
|
||||||
|
|
||||||
if (d->nativeFileDialog && useNativeFileDialog())
|
|
||||||
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
|
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
|
||||||
|
|
||||||
openPortal();
|
openPortal(windowFlags, windowModality, parent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -437,13 +444,20 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QXdgDesktopPortalFileDialog::useNativeFileDialog() const
|
bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const
|
||||||
{
|
{
|
||||||
if (options()->fileMode() == QFileDialogOptions::Directory)
|
Q_D(const QXdgDesktopPortalFileDialog);
|
||||||
return true;
|
|
||||||
else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
|
if (d->failedToOpen && fallbackType != OpenFallback)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (d->fileChooserPortalVersion < 3) {
|
||||||
|
if (options()->fileMode() == QFileDialogOptions::Directory)
|
||||||
|
return true;
|
||||||
|
else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
|
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
|
||||||
public:
|
public:
|
||||||
|
enum FallbackType {
|
||||||
|
GenericFallback,
|
||||||
|
OpenFallback
|
||||||
|
};
|
||||||
|
|
||||||
enum ConditionType : uint {
|
enum ConditionType : uint {
|
||||||
GlobalPattern = 0,
|
GlobalPattern = 0,
|
||||||
MimeType = 1
|
MimeType = 1
|
||||||
@ -33,7 +38,7 @@ public:
|
|||||||
};
|
};
|
||||||
typedef QList<Filter> FilterList;
|
typedef QList<Filter> FilterList;
|
||||||
|
|
||||||
QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
|
QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
|
||||||
~QXdgDesktopPortalFileDialog();
|
~QXdgDesktopPortalFileDialog();
|
||||||
|
|
||||||
bool defaultNameFilterDisables() const override;
|
bool defaultNameFilterDisables() const override;
|
||||||
@ -56,8 +61,8 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeDialog();
|
void initializeDialog();
|
||||||
void openPortal();
|
void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
|
||||||
bool useNativeFileDialog() const;
|
bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
|
||||||
|
|
||||||
QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
|
QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
|
||||||
};
|
};
|
||||||
|
@ -166,11 +166,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
|
|||||||
{
|
{
|
||||||
Q_D(const QXdgDesktopPortalTheme);
|
Q_D(const QXdgDesktopPortalTheme);
|
||||||
|
|
||||||
if (type == FileDialog) {
|
if (type == FileDialog && d->fileChooserPortalVersion) {
|
||||||
// Older versions of FileChooser portal don't support opening directories, therefore we fallback
|
// Older versions of FileChooser portal don't support opening directories, therefore we fallback
|
||||||
// to native file dialog opened inside the sandbox to open a directory.
|
// to native file dialog opened inside the sandbox to open a directory.
|
||||||
if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
|
if (d->baseTheme->usePlatformNativeDialog(type))
|
||||||
return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
|
return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
|
||||||
|
d->fileChooserPortalVersion);
|
||||||
|
|
||||||
return new QXdgDesktopPortalFileDialog;
|
return new QXdgDesktopPortalFileDialog;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user