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
|
||||
{
|
||||
public:
|
||||
QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
|
||||
QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
|
||||
: nativeFileDialog(nativeFileDialog)
|
||||
, fileChooserPortalVersion(fileChooserPortalVersion)
|
||||
{ }
|
||||
|
||||
WId winId = 0;
|
||||
bool directoryMode = false;
|
||||
bool modal = false;
|
||||
bool multipleFiles = false;
|
||||
bool saveFile = false;
|
||||
QEventLoop loop;
|
||||
QString acceptLabel;
|
||||
QString directory;
|
||||
QString title;
|
||||
@ -89,11 +86,16 @@ public:
|
||||
QString selectedNameFilter;
|
||||
QStringList selectedFiles;
|
||||
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()
|
||||
, d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
|
||||
, d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
|
||||
{
|
||||
Q_D(QXdgDesktopPortalFileDialog);
|
||||
|
||||
@ -101,6 +103,9 @@ QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelp
|
||||
connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
|
||||
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()
|
||||
@ -144,7 +149,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
|
||||
setDirectory(options()->initialDirectory());
|
||||
}
|
||||
|
||||
void QXdgDesktopPortalFileDialog::openPortal()
|
||||
void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
|
||||
{
|
||||
Q_D(QXdgDesktopPortalFileDialog);
|
||||
|
||||
@ -152,13 +157,13 @@ void QXdgDesktopPortalFileDialog::openPortal()
|
||||
"/org/freedesktop/portal/desktop"_L1,
|
||||
"org.freedesktop.portal.FileChooser"_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;
|
||||
if (!d->acceptLabel.isEmpty())
|
||||
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("directory"_L1, d->directoryMode);
|
||||
|
||||
@ -261,10 +266,18 @@ void QXdgDesktopPortalFileDialog::openPortal()
|
||||
|
||||
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher *watcher) {
|
||||
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
|
||||
if (reply.isError()) {
|
||||
Q_EMIT reject();
|
||||
// Any error means the dialog is not shown and we need to fallback
|
||||
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 {
|
||||
QDBusConnection::sessionBus().connect(nullptr,
|
||||
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
|
||||
QEventLoop loop;
|
||||
loop.connect(this, SIGNAL(accept()), SLOT(quit()));
|
||||
loop.connect(this, SIGNAL(reject()), SLOT(quit()));
|
||||
loop.exec();
|
||||
d->loop.exec();
|
||||
}
|
||||
|
||||
void QXdgDesktopPortalFileDialog::hide()
|
||||
@ -401,13 +411,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
|
||||
|
||||
initializeDialog();
|
||||
|
||||
d->modal = windowModality != Qt::NonModal;
|
||||
d->winId = parent ? parent->winId() : 0;
|
||||
|
||||
if (d->nativeFileDialog && useNativeFileDialog())
|
||||
if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
|
||||
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
|
||||
|
||||
openPortal();
|
||||
openPortal(windowFlags, windowModality, parent);
|
||||
|
||||
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)
|
||||
return true;
|
||||
else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
|
||||
Q_D(const QXdgDesktopPortalFileDialog);
|
||||
|
||||
if (d->failedToOpen && fallbackType != OpenFallback)
|
||||
return true;
|
||||
|
||||
if (d->fileChooserPortalVersion < 3) {
|
||||
if (options()->fileMode() == QFileDialogOptions::Directory)
|
||||
return true;
|
||||
else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
|
||||
public:
|
||||
enum FallbackType {
|
||||
GenericFallback,
|
||||
OpenFallback
|
||||
};
|
||||
|
||||
enum ConditionType : uint {
|
||||
GlobalPattern = 0,
|
||||
MimeType = 1
|
||||
@ -33,7 +38,7 @@ public:
|
||||
};
|
||||
typedef QList<Filter> FilterList;
|
||||
|
||||
QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
|
||||
QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
|
||||
~QXdgDesktopPortalFileDialog();
|
||||
|
||||
bool defaultNameFilterDisables() const override;
|
||||
@ -56,8 +61,8 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
void initializeDialog();
|
||||
void openPortal();
|
||||
bool useNativeFileDialog() const;
|
||||
void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
|
||||
bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
|
||||
|
||||
QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
|
||||
};
|
||||
|
@ -166,11 +166,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
|
||||
{
|
||||
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
|
||||
// to native file dialog opened inside the sandbox to open a directory.
|
||||
if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
|
||||
return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
|
||||
if (d->baseTheme->usePlatformNativeDialog(type))
|
||||
return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
|
||||
d->fileChooserPortalVersion);
|
||||
|
||||
return new QXdgDesktopPortalFileDialog;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user