diff --git a/src/access.cpp b/src/access.cpp
index 194415d..e467a1f 100644
--- a/src/access.cpp
+++ b/src/access.cpp
@@ -1,86 +1,86 @@
/*
* Copyright © 2017 Red Hat, Inc
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "access.h"
#include "accessdialog.h"
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeAccess, "xdg-desktop-portal-kde-access")
-Access::Access(QObject *parent)
- : QObject(parent)
+AccessPortal::AccessPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-Access::~Access()
+AccessPortal::~AccessPortal()
{
}
-uint Access::accessDialog(const QDBusObjectPath &handle,
+uint AccessPortal::AccessDialog(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QString &subtitle,
const QString &body,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdeAccess) << "AccessDialog called with parameters:";
qCDebug(XdgDesktopPortalKdeAccess) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeAccess) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeAccess) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeAccess) << " title: " << title;
qCDebug(XdgDesktopPortalKdeAccess) << " subtitle: " << subtitle;
qCDebug(XdgDesktopPortalKdeAccess) << " body: " << body;
qCDebug(XdgDesktopPortalKdeAccess) << " options: " << options;
- AccessDialog *accessDialog = new AccessDialog();
+ auto accessDialog = new ::AccessDialog();
accessDialog->setBody(body);
accessDialog->setTitle(title);
accessDialog->setSubtitle(subtitle);
if (options.contains(QLatin1String("modal"))) {
accessDialog->setModal(options.value(QLatin1String("modal")).toBool());
}
if (options.contains(QLatin1String("deny_label"))) {
accessDialog->setRejectLabel(options.value(QLatin1String("deny_label")).toString());
}
if (options.contains(QLatin1String("grant_label"))) {
accessDialog->setAcceptLabel(options.value(QLatin1String("grant_label")).toString());
}
if (options.contains(QLatin1String("icon"))) {
accessDialog->setIcon(options.value(QLatin1String("icon")).toString());
}
// TODO choices
if (accessDialog->exec()) {
accessDialog->deleteLater();
return 0;
}
accessDialog->deleteLater();
return 1;
}
diff --git a/src/access.h b/src/access.h
index 65ffd38..a13dd32 100644
--- a/src/access.h
+++ b/src/access.h
@@ -1,47 +1,47 @@
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_ACCESS_H
#define XDG_DESKTOP_PORTAL_KDE_ACCESS_H
-#include
+#include
#include
-class Access : public QObject
+class AccessPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Access")
public:
- Access(QObject *parent = nullptr);
- ~Access();
+ AccessPortal(QObject *parent);
+ ~AccessPortal();
public Q_SLOTS:
- uint accessDialog(const QDBusObjectPath &handle,
+ uint AccessDialog(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QString &subtitle,
const QString &body,
const QVariantMap &options,
QVariantMap &results);
};
#endif // XDG_DESKTOP_PORTAL_KDE_ACCESS_H
diff --git a/src/appchooser.cpp b/src/appchooser.cpp
index a5c9b9a..0494166 100644
--- a/src/appchooser.cpp
+++ b/src/appchooser.cpp
@@ -1,73 +1,73 @@
/*
* Copyright © 2016 Red Hat, Inc
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "appchooser.h"
#include "appchooserdialog.h"
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeAppChooser, "xdg-desktop-portal-kde-app-chooser")
-AppChooser::AppChooser(QObject *parent)
- : QObject(parent)
+AppChooserPortal::AppChooserPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-AppChooser::~AppChooser()
+AppChooserPortal::~AppChooserPortal()
{
}
-uint AppChooser::chooseApplication(const QDBusObjectPath &handle,
+uint AppChooserPortal::ChooseApplication(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QStringList &choices,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdeAppChooser) << "ChooseApplication called with parameters:";
qCDebug(XdgDesktopPortalKdeAppChooser) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeAppChooser) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeAppChooser) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeAppChooser) << " choices: " << choices;
qCDebug(XdgDesktopPortalKdeAppChooser) << " options: " << options;
QString latestChoice;
if (options.contains(QLatin1String("last_choice"))) {
latestChoice = options.value(QLatin1String("last_choice")).toString();
}
AppChooserDialog *appDialog = new AppChooserDialog(choices);
if (!latestChoice.isEmpty()) {
appDialog->setSelectedApplication(latestChoice);
}
if (appDialog->exec()) {
results.insert(QLatin1String("choice"), appDialog->selectedApplication());
appDialog->deleteLater();
return 0;
}
appDialog->deleteLater();
return 1;
}
diff --git a/src/appchooser.h b/src/appchooser.h
index a6fe5b9..f4ef223 100644
--- a/src/appchooser.h
+++ b/src/appchooser.h
@@ -1,45 +1,45 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H
#define XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H
-#include
+#include
#include
-class AppChooser : public QObject
+class AppChooserPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.AppChooser")
public:
- AppChooser(QObject *parent = nullptr);
- ~AppChooser();
+ AppChooserPortal(QObject *parent);
+ ~AppChooserPortal();
public Q_SLOTS:
- uint chooseApplication(const QDBusObjectPath &handle,
+ uint ChooseApplication(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QStringList &choices,
const QVariantMap &options,
QVariantMap &results);
};
#endif // XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H
diff --git a/src/desktopportal.cpp b/src/desktopportal.cpp
index 51a12c1..49881c9 100644
--- a/src/desktopportal.cpp
+++ b/src/desktopportal.cpp
@@ -1,338 +1,45 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "desktopportal.h"
#include
#include
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeDesktopPortal, "xdg-desktop-portal-kde-desktop-portal")
DesktopPortal::DesktopPortal(QObject *parent)
- : QDBusVirtualObject(parent)
- , m_access(new Access())
- , m_appChooser(new AppChooser())
- , m_email(new Email())
- , m_fileChooser(new FileChooser())
- , m_inhibit(new Inhibit())
- , m_notification(new Notification())
- , m_print(new Print())
+ : QObject(parent)
+ , m_access(new AccessPortal(this))
+ , m_appChooser(new AppChooserPortal(this))
+ , m_email(new EmailPortal(this))
+ , m_fileChooser(new FileChooserPortal(this))
+ , m_inhibit(new InhibitPortal(this))
+ , m_notification(new NotificationPortal(this))
+ , m_print(new PrintPortal(this))
{
}
DesktopPortal::~DesktopPortal()
{
- delete m_access;
- delete m_appChooser;
- delete m_email;
- delete m_fileChooser;
- delete m_inhibit;
- delete m_notification;
- delete m_print;
-}
-
-bool DesktopPortal::handleMessage(const QDBusMessage &message, const QDBusConnection &connection)
-{
- /* Check to make sure we're getting properties on our interface */
- if (message.type() != QDBusMessage::MessageType::MethodCallMessage) {
- return false;
- }
-
- qCDebug(XdgDesktopPortalKdeDesktopPortal) << message.interface();
- qCDebug(XdgDesktopPortalKdeDesktopPortal) << message.member();
- qCDebug(XdgDesktopPortalKdeDesktopPortal) << message.path();
-
- QList arguments;
- if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Access")) {
- if (message.member() == QLatin1String("AccessDialog")) {
- QVariantMap results;
- QVariantMap options;
-
- QDBusArgument dbusArgument = message.arguments().at(6).value();
- dbusArgument >> options;
-
- uint response = m_access->accessDialog(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toString(), // title
- message.arguments().at(4).toString(), // subtitle
- message.arguments().at(5).toString(), // body
- options, // options
- results);
- arguments << response;
- arguments << results;
- }
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.AppChooser")) {
- if (message.member() == QLatin1String("ChooseApplication")) {
- QVariantMap results;
- QVariantMap choices;
-
- QDBusArgument dbusArgument = message.arguments().at(4).value();
- dbusArgument >> choices;
-
- uint response = m_appChooser->chooseApplication(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toStringList(), // choices
- choices, // options
- results);
- arguments << response;
- arguments << results;
- }
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Email")) {
- uint response = 2;
- QVariantMap results;
- QVariantMap options;
-
- QDBusArgument dbusArgument = message.arguments().at(3).value();
- dbusArgument >> options;
-
- if (message.member() == QLatin1String("ComposeEmail")) {
- response = m_email->composeEmail(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- options, // options
- results);
- }
-
- arguments << response;
- arguments << results;
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.FileChooser")) {
- uint response = 2;
- QVariantMap results;
- QVariantMap choices;
-
- QDBusArgument dbusArgument = message.arguments().at(4).value();
- dbusArgument >> choices;
-
- if (message.member() == QLatin1String("OpenFile")) {
- response = m_fileChooser->openFile(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toString(), // title
- choices, // options
- results);
- } else if (message.member() == QLatin1String("SaveFile")) {
- response = m_fileChooser->saveFile(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toString(), // title
- choices, // options
- results);
- }
-
- arguments << response;
- arguments << results;
-
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Inhibit")) {
- if (message.member() == QLatin1String("Inhibit")) {
- QVariantMap options;
-
- QDBusArgument dbusArgument = message.arguments().at(4).value();
- dbusArgument >> options;
-
- m_inhibit->inhibit(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // window
- message.arguments().at(3).toUInt(), // flags
- options); // options
- }
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Notification")) {
- if (message.member() == QLatin1String("AddNotification")) {
- QVariantMap notificationParams;
-
- QDBusArgument dbusArgument = message.arguments().at(2).value();
- dbusArgument >> notificationParams;
-
- m_notification->addNotification(message.arguments().at(0).toString(), // app_id
- message.arguments().at(1).toString(), // id
- notificationParams); // notification
- } else if (message.member() == QLatin1String("RemoveNotification")) {
- m_notification->removeNotification(message.arguments().at(0).toString(), // app_id
- message.arguments().at(1).toString()); // id
- }
- } else if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Print")) {
- uint response = 2;
- QVariantMap results;
-
- if (message.member() == QLatin1String("Print")) {
- QVariantMap options;
-
- QDBusArgument dbusArgument = message.arguments().at(5).value();
- dbusArgument >> options;
-
- response = m_print->print(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toString(), // title
- qvariant_cast(message.arguments().at(4)), // fd
- options, // options
- results);
- } else if (message.member() == QLatin1String("PreparePrint")) {
- QVariantMap settings;
- QVariantMap pageSetup;
- QVariantMap options;
-
- QDBusArgument dbusArgument = message.arguments().at(4).value();
- dbusArgument >> settings;
-
- QDBusArgument dbusArgument1 = message.arguments().at(5).value();
- dbusArgument1 >> pageSetup;
-
- QDBusArgument dbusArgument2 = message.arguments().at(6).value();
- dbusArgument2 >> options;
-
- response = m_print->preparePrint(qvariant_cast(message.arguments().at(0)), // handle
- message.arguments().at(1).toString(), // app_id
- message.arguments().at(2).toString(), // parent_window
- message.arguments().at(3).toString(), // title
- settings, // settings
- pageSetup, // page_setup
- options, // options
- results);
- }
-
- arguments << response;
- arguments << results;
- }
-
- QDBusMessage reply = message.createReply();
- reply.setArguments(arguments);
- return connection.send(reply);
-}
-
-QString DesktopPortal::introspect(const QString &path) const
-{
- QString nodes;
-
- if (path == QLatin1String("/org/freedesktop/portal/desktop/") || path == QLatin1String("/org/freedesktop/portal/desktop")) {
- nodes = QStringLiteral(
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- ""
- ""
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- " "
- "");
- }
-
- qCDebug(XdgDesktopPortalKdeDesktopPortal) << nodes;
-
- return nodes;
}
diff --git a/src/desktopportal.h b/src/desktopportal.h
index 0da9504..0fe1b4c 100644
--- a/src/desktopportal.h
+++ b/src/desktopportal.h
@@ -1,55 +1,53 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H
#define XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H
#include
#include
#include "access.h"
#include "appchooser.h"
#include "email.h"
#include "filechooser.h"
#include "inhibit.h"
#include "notification.h"
#include "print.h"
-class DesktopPortal : public QDBusVirtualObject
+class DesktopPortal : public QObject
{
Q_OBJECT
public:
explicit DesktopPortal(QObject *parent = nullptr);
~DesktopPortal();
- bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) Q_DECL_OVERRIDE;
- QString introspect(const QString &path) const Q_DECL_OVERRIDE;
private:
- Access *m_access;
- AppChooser *m_appChooser;
- Email *m_email;
- FileChooser *m_fileChooser;
- Inhibit *m_inhibit;
- Notification *m_notification;
- Print *m_print;
+ AccessPortal *m_access;
+ AppChooserPortal *m_appChooser;
+ EmailPortal *m_email;
+ FileChooserPortal *m_fileChooser;
+ InhibitPortal *m_inhibit;
+ NotificationPortal *m_notification;
+ PrintPortal *m_print;
};
#endif // XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H
diff --git a/src/email.cpp b/src/email.cpp
index 95b39ea..5918247 100644
--- a/src/email.cpp
+++ b/src/email.cpp
@@ -1,56 +1,56 @@
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "email.h"
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeEmail, "xdg-desktop-portal-kde-email")
-Email::Email(QObject *parent)
- : QObject(parent)
+EmailPortal::EmailPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-Email::~Email()
+EmailPortal::~EmailPortal()
{
}
-uint Email::composeEmail(const QDBusObjectPath &handle, const QString &app_id, const QString &window, const QVariantMap &options, QVariantMap &results)
+uint EmailPortal::ComposeEmail(const QDBusObjectPath &handle, const QString &app_id, const QString &window, const QVariantMap &options, QVariantMap &results)
{
Q_UNUSED(results)
qCDebug(XdgDesktopPortalKdeEmail) << "ComposeEmail called with parameters:";
qCDebug(XdgDesktopPortalKdeEmail) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeEmail) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeEmail) << " window: " << window;
qCDebug(XdgDesktopPortalKdeEmail) << " options: " << options;
// TODO attachements
const QString mailtoUrl = QStringLiteral("mailto:%1?subject=%2&body=%3").arg(options.value(QLatin1String("address")).toString())
.arg(options.value(QLatin1String("subject")).toString())
.arg(options.value(QLatin1String("body")).toString());
qCDebug(XdgDesktopPortalKdeEmail) << "Mailto url: " << mailtoUrl;
return QDesktopServices::openUrl(QUrl(mailtoUrl));
}
diff --git a/src/email.h b/src/email.h
index dd6e81b..1c0e3a6 100644
--- a/src/email.h
+++ b/src/email.h
@@ -1,44 +1,44 @@
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_EMAIL_H
#define XDG_DESKTOP_PORTAL_KDE_EMAIL_H
-#include
+#include
#include
-class Email : public QObject
+class EmailPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Email")
public:
- Email(QObject *parent = 0);
- ~Email();
+ EmailPortal(QObject *parent);
+ ~EmailPortal();
public Q_SLOTS:
- uint composeEmail(const QDBusObjectPath &handle,
+ uint ComposeEmail(const QDBusObjectPath &handle,
const QString &app_id,
const QString &window,
const QVariantMap &options,
QVariantMap &results);
};
#endif // XDG_DESKTOP_PORTAL_KDE_EMAIL_H
diff --git a/src/filechooser.cpp b/src/filechooser.cpp
index cb4b27b..0938705 100644
--- a/src/filechooser.cpp
+++ b/src/filechooser.cpp
@@ -1,291 +1,291 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "filechooser.h"
#include
#include
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeFileChooser, "xdg-desktop-portal-kde-file-chooser")
// Keep in sync with qflatpakfiledialog from flatpak-platform-plugin
-Q_DECLARE_METATYPE(FileChooser::Filter);
-Q_DECLARE_METATYPE(FileChooser::Filters);
-Q_DECLARE_METATYPE(FileChooser::FilterList);
-Q_DECLARE_METATYPE(FileChooser::FilterListList);
+Q_DECLARE_METATYPE(FileChooserPortal::Filter);
+Q_DECLARE_METATYPE(FileChooserPortal::Filters);
+Q_DECLARE_METATYPE(FileChooserPortal::FilterList);
+Q_DECLARE_METATYPE(FileChooserPortal::FilterListList);
-QDBusArgument &operator << (QDBusArgument &arg, const FileChooser::Filter &filter)
+QDBusArgument &operator << (QDBusArgument &arg, const FileChooserPortal::Filter &filter)
{
arg.beginStructure();
arg << filter.type << filter.filterString;
arg.endStructure();
return arg;
}
-const QDBusArgument &operator >> (const QDBusArgument &arg, FileChooser::Filter &filter)
+const QDBusArgument &operator >> (const QDBusArgument &arg, FileChooserPortal::Filter &filter)
{
uint type;
QString filterString;
arg.beginStructure();
arg >> type >> filterString;
filter.type = type;
filter.filterString = filterString;
arg.endStructure();
return arg;
}
-QDBusArgument &operator << (QDBusArgument &arg, const FileChooser::FilterList &filterList)
+QDBusArgument &operator << (QDBusArgument &arg, const FileChooserPortal::FilterList &filterList)
{
arg.beginStructure();
arg << filterList.userVisibleName << filterList.filters;
arg.endStructure();
return arg;
}
-const QDBusArgument &operator >> (const QDBusArgument &arg, FileChooser::FilterList &filterList)
+const QDBusArgument &operator >> (const QDBusArgument &arg, FileChooserPortal::FilterList &filterList)
{
QString userVisibleName;
- FileChooser::Filters filters;
+ FileChooserPortal::Filters filters;
arg.beginStructure();
arg >> userVisibleName >> filters;
filterList.userVisibleName = userVisibleName;
filterList.filters = filters;
arg.endStructure();
return arg;
}
-FileChooser::FileChooser(QObject *parent)
- : QObject(parent)
+FileChooserPortal::FileChooserPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
qDBusRegisterMetaType();
qDBusRegisterMetaType();
qDBusRegisterMetaType();
qDBusRegisterMetaType();
}
-FileChooser::~FileChooser()
+FileChooserPortal::~FileChooserPortal()
{
}
-uint FileChooser::openFile(const QDBusObjectPath &handle,
+uint FileChooserPortal::OpenFile(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &options,
QVariantMap &results)
{
Q_UNUSED(app_id);
qCDebug(XdgDesktopPortalKdeFileChooser) << "OpenFile called with parameters:";
qCDebug(XdgDesktopPortalKdeFileChooser) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeFileChooser) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeFileChooser) << " title: " << title;
qCDebug(XdgDesktopPortalKdeFileChooser) << " options: " << options;
bool modalDialog = true;
bool multipleFiles = false;
QString acceptLabel;
QStringList nameFilters;
QStringList mimeTypeFilters;
/* TODO
* choices a(ssa(ss)s)
* List of serialized combo boxes to add to the file chooser.
*
* For each element, the first string is an ID that will be returned with the response, te second string is a user-visible label.
* The a(ss) is the list of choices, each being a is an ID and a user-visible label. The final string is the initial selection,
* or "", to let the portal decide which choice will be initially selected. None of the strings, except for the initial selection, should be empty.
*
* As a special case, passing an empty array for the list of choices indicates a boolean choice that is typically displayed as a check button, using "true" and "false" as the choices.
* Example: [('encoding', 'Encoding', [('utf8', 'Unicode (UTF-8)'), ('latin15', 'Western')], 'latin15'), ('reencode', 'Reencode', [], 'false')]
*/
if (options.contains(QLatin1String("accept_label"))) {
acceptLabel = options.value(QLatin1String("accept_label")).toString();
}
if (options.contains(QLatin1String("modal"))) {
modalDialog = options.value(QLatin1String("modal")).toBool();
}
if (options.contains(QLatin1String("multiple"))) {
multipleFiles = options.value(QLatin1String("multiple")).toBool();
}
if (options.contains(QLatin1String("filters"))) {
FilterListList filterListList = qdbus_cast(options.value(QLatin1String("filters")));
Q_FOREACH (const FilterList &filterList, filterListList) {
QStringList filterStrings;
Q_FOREACH (const Filter &filterStruct, filterList.filters) {
if (filterStruct.type == 0) {
filterStrings << filterStruct.filterString;
} else {
mimeTypeFilters << filterStruct.filterString;
}
}
if (!filterStrings.isEmpty()) {
nameFilters << QString("%1 (%2)").arg(filterList.userVisibleName).arg(filterStrings.join(QLatin1String(" ")));
}
}
}
QFileDialog *fileDialog = new QFileDialog();
fileDialog->setWindowTitle(title);
fileDialog->setModal(modalDialog);
fileDialog->setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
fileDialog->setLabelText(QFileDialog::Accept, !acceptLabel.isEmpty() ? acceptLabel : i18n("Open"));
if (!nameFilters.isEmpty()) {
fileDialog->setNameFilters(nameFilters);
}
if (!mimeTypeFilters.isEmpty()) {
fileDialog->setMimeTypeFilters(mimeTypeFilters);
}
if (fileDialog->exec() == QDialog::Accepted) {
QStringList files;
Q_FOREACH (const QString &filename, fileDialog->selectedFiles()) {
QUrl url = QUrl::fromLocalFile(filename);
files << url.toDisplayString();
}
results.insert(QLatin1String("uris"), files);
fileDialog->deleteLater();
return 0;
}
fileDialog->deleteLater();
return 1;
}
-uint FileChooser::saveFile(const QDBusObjectPath &handle,
+uint FileChooserPortal::SaveFile(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &options,
QVariantMap &results)
{
Q_UNUSED(app_id);
qCDebug(XdgDesktopPortalKdeFileChooser) << "SaveFile called with parameters:";
qCDebug(XdgDesktopPortalKdeFileChooser) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeFileChooser) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeFileChooser) << " title: " << title;
qCDebug(XdgDesktopPortalKdeFileChooser) << " options: " << options;
bool modalDialog = true;
QString acceptLabel;
QString currentName;
QString currentFolder;
QString currentFile;
QStringList nameFilters;
QStringList mimeTypeFilters;
// TODO parse options - choices
if (options.contains(QLatin1String("modal"))) {
modalDialog = options.value(QLatin1String("modal")).toBool();
}
if (options.contains(QLatin1String("accept_label"))) {
acceptLabel = options.value(QLatin1String("accept_label")).toString();
}
if (options.contains(QLatin1String("current_name"))) {
currentName = options.value(QLatin1String("current_name")).toString();
}
if (options.contains(QLatin1String("current_folder"))) {
currentFolder = options.value(QLatin1String("current_folder")).toByteArray();
}
if (options.contains(QLatin1String("current_file"))) {
currentFile = options.value(QLatin1String("current_file")).toByteArray();
}
if (options.contains(QLatin1String("filters"))) {
FilterListList filterListList = qdbus_cast(options.value(QLatin1String("filters")));
Q_FOREACH (const FilterList &filterList, filterListList) {
QStringList filterStrings;
Q_FOREACH (const Filter &filterStruct, filterList.filters) {
if (filterStruct.type == 0) {
filterStrings << filterStruct.filterString;
} else {
mimeTypeFilters << filterStruct.filterString;
}
}
if (!filterStrings.isEmpty()) {
nameFilters << QString("%1 (%2)").arg(filterList.userVisibleName).arg(filterStrings.join(QLatin1String(" ")));
}
}
}
QFileDialog *fileDialog = new QFileDialog();
fileDialog->setWindowTitle(title);
fileDialog->setModal(modalDialog);
fileDialog->setAcceptMode(QFileDialog::AcceptSave);
// TODO: Looks Qt doesn't have API for this
// if (!currentName.isEmpty()) {
// fileDialog->selectFile(currentName);
// }
if (!currentFolder.isEmpty()) {
fileDialog->setDirectoryUrl(QUrl(currentFolder));
}
if (!currentFile.isEmpty()) {
fileDialog->selectFile(currentFile);
}
if (!acceptLabel.isEmpty()) {
fileDialog->setLabelText(QFileDialog::Accept, acceptLabel);
}
if (!nameFilters.isEmpty()) {
fileDialog->setNameFilters(nameFilters);
}
if (!mimeTypeFilters.isEmpty()) {
fileDialog->setMimeTypeFilters(mimeTypeFilters);
}
if (fileDialog->exec() == QDialog::Accepted) {
QStringList files;
Q_FOREACH (const QString &filename, fileDialog->selectedFiles()) {
QUrl url = QUrl::fromLocalFile(filename);
files << url.toDisplayString();
}
results.insert(QLatin1String("uris"), files);
fileDialog->deleteLater();
return 0;
}
fileDialog->deleteLater();
return 1;
}
diff --git a/src/filechooser.h b/src/filechooser.h
index eef1b1d..88f78ce 100644
--- a/src/filechooser.h
+++ b/src/filechooser.h
@@ -1,65 +1,65 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_FILECHOOSER_H
#define XDG_DESKTOP_PORTAL_KDE_FILECHOOSER_H
#include
#include
-#include
+#include
-class FileChooser : public QObject
+class FileChooserPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.FileChooser")
public:
// Keep in sync with qflatpakfiledialog from flatpak-platform-plugin
typedef struct {
uint type;
QString filterString;
} Filter;
typedef QList Filters;
typedef struct {
QString userVisibleName;
Filters filters;
} FilterList;
typedef QList FilterListList;
- FileChooser(QObject *parent = 0);
- ~FileChooser();
+ FileChooserPortal(QObject *parent);
+ ~FileChooserPortal();
public Q_SLOTS:
- uint openFile(const QDBusObjectPath &handle,
+ uint OpenFile(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &options,
QVariantMap &results);
- uint saveFile(const QDBusObjectPath &handle,
+ uint SaveFile(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &options,
QVariantMap &results);
};
#endif // XDG_DESKTOP_PORTAL_KDE_FILECHOOSER_H
diff --git a/src/inhibit.cpp b/src/inhibit.cpp
index b2c8f32..3bad185 100644
--- a/src/inhibit.cpp
+++ b/src/inhibit.cpp
@@ -1,80 +1,80 @@
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "inhibit.h"
#include "request.h"
#include
#include
#include
#include
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeInhibit, "xdg-desktop-portal-kde-inhibit")
-Inhibit::Inhibit(QObject *parent)
- : QObject(parent)
+InhibitPortal::InhibitPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-Inhibit::~Inhibit()
+InhibitPortal::~InhibitPortal()
{
}
-void Inhibit::inhibit(const QDBusObjectPath &handle, const QString &app_id, const QString &window, uint flags, const QVariantMap &options)
+void InhibitPortal::Inhibit(const QDBusObjectPath &handle, const QString &app_id, const QString &window, uint flags, const QVariantMap &options)
{
qCDebug(XdgDesktopPortalKdeInhibit) << "Inhibit called with parameters:";
qCDebug(XdgDesktopPortalKdeInhibit) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeInhibit) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeInhibit) << " window: " << window;
qCDebug(XdgDesktopPortalKdeInhibit) << " flags: " << flags;
qCDebug(XdgDesktopPortalKdeInhibit) << " options: " << options;
QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.kde.Solid.PowerManagement"),
QLatin1String("/org/kde/Solid/PowerManagement/PolicyAgent"),
QLatin1String("org.kde.Solid.PowerManagement.PolicyAgent"),
QLatin1String("AddInhibition"));
// interrupt session (1)
message << (uint)1 << app_id << options.value(QLatin1String("reason")).toString();
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
connect(watcher, &QDBusPendingCallWatcher::finished, [handle, this] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply reply = *watcher;
if (reply.isError()) {
qCDebug(XdgDesktopPortalKdeInhibit) << "Inhibition error: " << reply.error().message();
} else {
QDBusConnection sessionBus = QDBusConnection::sessionBus();
Request *request = new Request(this, QLatin1String("org.freedesktop.impl.portal.Inhibit"), QVariant(reply.value()));
if (sessionBus.registerVirtualObject(handle.path(), request, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
connect(request, &Request::closeRequested, [request, handle] () {
QDBusConnection::sessionBus().unregisterObject(handle.path());
request->deleteLater();
});
} else {
qCDebug(XdgDesktopPortalKdeInhibit) << sessionBus.lastError().message();
qCDebug(XdgDesktopPortalKdeInhibit) << "Failed to register request object with inhibition";
request->deleteLater();
}
}
});
}
diff --git a/src/inhibit.h b/src/inhibit.h
index de92fcf..4b141dd 100644
--- a/src/inhibit.h
+++ b/src/inhibit.h
@@ -1,46 +1,46 @@
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_INHIBIT_H
#define XDG_DESKTOP_PORTAL_KDE_INHIBIT_H
-#include
+#include
#include
#include "request.h"
-class Inhibit : public QObject
+class InhibitPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Inhibit")
public:
- Inhibit(QObject *parent = 0);
- ~Inhibit();
+ InhibitPortal(QObject *parent);
+ ~InhibitPortal();
public Q_SLOTS:
- void inhibit(const QDBusObjectPath &handle,
+ void Inhibit(const QDBusObjectPath &handle,
const QString &app_id,
const QString &window,
uint flags,
const QVariantMap &options);
};
#endif // XDG_DESKTOP_PORTAL_KDE_INHIBIT_H
diff --git a/src/notification.cpp b/src/notification.cpp
index e3b1936..f052707 100644
--- a/src/notification.cpp
+++ b/src/notification.cpp
@@ -1,143 +1,144 @@
/*
* Copyright © 2016 Red Hat, Inc
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "notification.h"
#include
#include
#include
#include
+
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeNotification, "xdg-desktop-portal-kde-notification")
-Notification::Notification(QObject *parent)
- : QObject(parent)
+NotificationPortal::NotificationPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-Notification::~Notification()
+NotificationPortal::~NotificationPortal()
{
}
-void Notification::addNotification(const QString &app_id,
+void NotificationPortal::AddNotification(const QString &app_id,
const QString &id,
const QVariantMap ¬ification)
{
qCDebug(XdgDesktopPortalKdeNotification) << "AddNotification called with parameters:";
qCDebug(XdgDesktopPortalKdeNotification) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeNotification) << " id: " << id;
qCDebug(XdgDesktopPortalKdeNotification) << " notification: " << notification;
// We have to use "notification" as an ID because any other ID will not be configured
KNotification *notify = new KNotification(QLatin1String("notification"), KNotification::CloseOnTimeout | KNotification::DefaultEvent, this);
if (notification.contains(QLatin1String("title"))) {
notify->setTitle(notification.value(QLatin1String("title")).toString());
}
if (notification.contains(QLatin1String("body"))) {
notify->setText(notification.value(QLatin1String("body")).toString());
}
if (notification.contains(QLatin1String("icon"))) {
notify->setIconName(notification.value(QLatin1String("icon")).toString());
}
if (notification.contains(QLatin1String("priority"))) {
// TODO KNotification has no option for priority
}
if (notification.contains(QLatin1String("default-action"))) {
// TODO KNotification has no option for default action
}
if (notification.contains(QLatin1String("default-action-target"))) {
// TODO KNotification has no option for default action
}
if (notification.contains(QLatin1String("buttons"))) {
QList buttons;
QDBusArgument dbusArgument = notification.value(QLatin1String("buttons")).value();
while (!dbusArgument.atEnd()) {
dbusArgument >> buttons;
}
QStringList actions;
Q_FOREACH (const QVariantMap &button, buttons) {
actions << button.value(QLatin1String("label")).toString();
}
if (!actions.isEmpty()) {
notify->setActions(actions);
}
}
notify->setProperty("app_id", app_id);
notify->setProperty("id", id);
- connect(notify, static_cast(&KNotification::activated), this, &Notification::notificationActivated);
- connect(notify, &KNotification::closed, this, &Notification::notificationClosed);
+ connect(notify, static_cast(&KNotification::activated), this, &NotificationPortal::notificationActivated);
+ connect(notify, &KNotification::closed, this, &NotificationPortal::notificationClosed);
notify->sendEvent();
m_notifications.insert(QString("%1:%2").arg(app_id, id), notify);
}
-void Notification::notificationActivated(uint action)
+void NotificationPortal::notificationActivated(uint action)
{
KNotification *notify = qobject_cast(sender());
if (!notify) {
return;
}
const QString appId = notify->property("app_id").toString();
const QString id = notify->property("id").toString();
qCDebug(XdgDesktopPortalKdeNotification) << "Notification activated:";
qCDebug(XdgDesktopPortalKdeNotification) << " app_id: " << appId;
qCDebug(XdgDesktopPortalKdeNotification) << " id: " << id;
qCDebug(XdgDesktopPortalKdeNotification) << " action: " << action;
QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/org/freedesktop/portal/desktop"),
QLatin1String("org.freedesktop.impl.portal.Notification"),
QLatin1String("ActionInvoked"));
message << appId << id << QString::number(action) << QVariantList();
QDBusConnection::sessionBus().send(message);
}
-void Notification::removeNotification(const QString &app_id,
+void NotificationPortal::RemoveNotification(const QString &app_id,
const QString &id)
{
qCDebug(XdgDesktopPortalKdeNotification) << "RemoveNotification called with parameters:";
qCDebug(XdgDesktopPortalKdeNotification) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeNotification) << " id: " << id;
KNotification *notify = m_notifications.take(QString("%1:%2").arg(app_id, id));
if (notify) {
notify->close();
notify->deleteLater();
}
}
-void Notification::notificationClosed()
+void NotificationPortal::notificationClosed()
{
KNotification *notify = qobject_cast(sender());
if (!notify) {
return;
}
const QString appId = notify->property("app_id").toString();
const QString id = notify->property("id").toString();
m_notifications.remove(QString("%1:%2").arg(appId, id));
notify->deleteLater();
}
diff --git a/src/notification.h b/src/notification.h
index 17ab01d..8c668dd 100644
--- a/src/notification.h
+++ b/src/notification.h
@@ -1,51 +1,51 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H
#define XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H
-#include
+#include
#include
#include
-class Notification : public QObject
+class NotificationPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Notification")
public:
- Notification(QObject *parent = 0);
- ~Notification();
+ NotificationPortal(QObject *parent);
+ ~NotificationPortal();
public Q_SLOTS:
- void addNotification(const QString &app_id,
+ void AddNotification(const QString &app_id,
const QString &id,
const QVariantMap ¬ification);
- void removeNotification(const QString &app_id,
+ void RemoveNotification(const QString &app_id,
const QString &id);
private Q_SLOTS:
void notificationActivated(uint action);
void notificationClosed();
private:
QHash m_notifications;
};
#endif // XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H
diff --git a/src/print.cpp b/src/print.cpp
index 0ff9973..439b6ce 100644
--- a/src/print.cpp
+++ b/src/print.cpp
@@ -1,977 +1,977 @@
/*
* Copyright © 2016-2017 Jan Grulich
* Copyright © 2007,2010 by John Layt
* Copyright © 2007 Alex Merry
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
*/
#include "print.h"
#include
#include
#include
#include
#include
#include
#include
// #include
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdePrint, "xdg-desktop-portal-kde-print")
// INFO: code below is copied from Qt as there is no public API for converting key to PageSizeId
// TODO seems to by Windows only stuff
// Standard sources data
// struct StandardPaperSource {
// QPrinter::PaperSource sourceNum;
// const char *source;
// }
//
// static const StandardPaperSource qt_paperSources[] = {
// {QPrinter::Auto, "Auto"},
// {QPrinter::Cassette, "Cassette"},
// {QPrinter::Envelope, "Envelope"},
// {QPrinter::EnvelopeManual, "EnvelopeManual"},
// {QPrinter::FormSource, "FormSource"},
// {QPrinter::LargeCapacity, "LargeCapacity"},
// {QPrinter::LargeFormat, "AnyLargeFormat"},
// {QPrinter::Lower, "Lower"},
// {QPrinter::Middle, "Middle"},
// {QPrinter::Manual, "Manual"},
// {QPrinter::Manual, "ManualFeed"},
// {QPrinter::OnlyOne, "OnlyOne"}, // = QPrint::Upper
// {QPrinter::Tractor, "Tractor"},
// {QPrinter::SmallFormat, "AnySmallFormat"},
// {QPrinter::Upper, "Upper"},
// };
// Standard sizes data
struct StandardPageSize {
QPageSize::PageSizeId id;
const char *mediaOption; // PPD standard mediaOption ID
};
// Standard page sizes taken from the Postscript PPD Standard v4.3
// See http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
// Excludes all Transverse and Rotated sizes
// NB!This table needs to be in sync with QPageSize::PageSizeId
const static StandardPageSize qt_pageSizes[] = {
// Existing Qt sizes including ISO, US, ANSI and other standards
{QPageSize::A4, "A4"},
{QPageSize::B5, "ISOB5"},
{QPageSize::Letter, "Letter"},
{QPageSize::Legal, "Legal"},
{QPageSize::Executive, "Executive.7.5x10in"}, // Qt size differs from Postscript / Windows
{QPageSize::A0, "A0"},
{QPageSize::A1, "A1"},
{QPageSize::A2, "A2"},
{QPageSize::A3, "A3"},
{QPageSize::A5, "A5"},
{QPageSize::A6, "A6"},
{QPageSize::A7, "A7"},
{QPageSize::A8, "A8"},
{QPageSize::A9, "A9"},
{QPageSize::B0, "ISOB0"},
{QPageSize::B1, "ISOB1"},
{QPageSize::B10, "ISOB10"},
{QPageSize::B2, "ISOB2"},
{QPageSize::B3, "ISOB3"},
{QPageSize::B4, "ISOB4"},
{QPageSize::B6, "ISOB6"},
{QPageSize::B7, "ISOB7"},
{QPageSize::B8, "ISOB8"},
{QPageSize::B9, "ISOB9"},
{QPageSize::C5E, "EnvC5"},
{QPageSize::Comm10E, "Env10"},
{QPageSize::DLE, "EnvDL"},
{QPageSize::Folio, "Folio"},
{QPageSize::Ledger, "Ledger"},
{QPageSize::Tabloid, "Tabloid"},
{QPageSize::Custom, "Custom"}, // Special case to keep in sync with QPageSize::PageSizeId
// ISO Standard Sizes
{QPageSize::A10, "A10"},
{QPageSize::A3Extra, "A3Extra"},
{QPageSize::A4Extra, "A4Extra"},
{QPageSize::A4Plus, "A4Plus"},
{QPageSize::A4Small, "A4Small"},
{QPageSize::A5Extra, "A5Extra"},
{QPageSize::B5Extra, "ISOB5Extra"},
// JIS Standard Sizes
{QPageSize::JisB0, "B0"},
{QPageSize::JisB1, "B1"},
{QPageSize::JisB2, "B2"},
{QPageSize::JisB3, "B3"},
{QPageSize::JisB4, "B4"},
{QPageSize::JisB5, "B5"},
{QPageSize::JisB6, "B6"},
{QPageSize::JisB7, "B7"},
{QPageSize::JisB8, "B8"},
{QPageSize::JisB9, "B9"},
{QPageSize::JisB10, "B10"},
// ANSI / US Standard sizes
{QPageSize::AnsiC, "AnsiC"},
{QPageSize::AnsiD, "AnsiD"},
{QPageSize::AnsiE, "AnsiE"},
{QPageSize::LegalExtra, "LegalExtra"},
{QPageSize::LetterExtra, "LetterExtra"},
{QPageSize::LetterPlus, "LetterPlus"},
{QPageSize::LetterSmall, "LetterSmall"},
{QPageSize::TabloidExtra, "TabloidExtra"},
// Architectural sizes
{QPageSize::ArchA, "ARCHA"},
{QPageSize::ArchB, "ARCHB"},
{QPageSize::ArchC, "ARCHC"},
{QPageSize::ArchD, "ARCHD"},
{QPageSize::ArchE, "ARCHE"},
// Inch-based Sizes
{QPageSize::Imperial7x9, "7x9"},
{QPageSize::Imperial8x10, "8x10"},
{QPageSize::Imperial9x11, "9x11"},
{QPageSize::Imperial9x12, "9x12"},
{QPageSize::Imperial10x11, "10x11"},
{QPageSize::Imperial10x13, "10x13"},
{QPageSize::Imperial10x14, "10x14"},
{QPageSize::Imperial12x11, "12x11"},
{QPageSize::Imperial15x11, "15x11"},
// Other Page Sizes
{QPageSize::ExecutiveStandard, "Executive"}, // Qt size differs from Postscript / Windows
{QPageSize::Note, "Note"},
{QPageSize::Quarto, "Quarto"},
{QPageSize::Statement, "Statement"},
{QPageSize::SuperA, "SuperA"},
{QPageSize::SuperB, "SuperB"},
{QPageSize::Postcard, "Postcard"},
{QPageSize::DoublePostcard, "DoublePostcard"},
{QPageSize::Prc16K, "PRC16K"},
{QPageSize::Prc32K, "PRC32K"},
{QPageSize::Prc32KBig, "PRC32KBig"},
// Fan Fold Sizes
{QPageSize::FanFoldUS, "FanFoldUS"},
{QPageSize::FanFoldGerman, "FanFoldGerman"},
{QPageSize::FanFoldGermanLegal, "FanFoldGermanLegal"},
// ISO Envelopes
{QPageSize::EnvelopeB4, "EnvISOB4"},
{QPageSize::EnvelopeB5, "EnvISOB5"},
{QPageSize::EnvelopeB6, "EnvISOB6"},
{QPageSize::EnvelopeC0, "EnvC0"},
{QPageSize::EnvelopeC1, "EnvC1"},
{QPageSize::EnvelopeC2, "EnvC2"},
{QPageSize::EnvelopeC3, "EnvC3"},
{QPageSize::EnvelopeC4, "EnvC4"},
{QPageSize::EnvelopeC6, "EnvC6"},
{QPageSize::EnvelopeC65, "EnvC65"},
{QPageSize::EnvelopeC7, "EnvC7"},
// US Envelopes
{QPageSize::Envelope9, "Env9"},
{QPageSize::Envelope11, "Env11"},
{QPageSize::Envelope12, "Env12"},
{QPageSize::Envelope14, "Env14"},
{QPageSize::EnvelopeMonarch, "EnvMonarch"},
{QPageSize::EnvelopePersonal, "EnvPersonal"},
// Other Envelopes
{QPageSize::EnvelopeChou3, "EnvChou3"},
{QPageSize::EnvelopeChou4, "EnvChou4"},
{QPageSize::EnvelopeInvite, "EnvInvite"},
{QPageSize::EnvelopeItalian, "EnvItalian"},
{QPageSize::EnvelopeKaku2, "EnvKaku2"},
{QPageSize::EnvelopeKaku3, "EnvKaku3"},
{QPageSize::EnvelopePrc1, "EnvPRC1"},
{QPageSize::EnvelopePrc2, "EnvPRC2"},
{QPageSize::EnvelopePrc3, "EnvPRC3"},
{QPageSize::EnvelopePrc4, "EnvPRC4"},
{QPageSize::EnvelopePrc5, "EnvPRC5"},
{QPageSize::EnvelopePrc6, "EnvPRC6"},
{QPageSize::EnvelopePrc7, "EnvPRC7"},
{QPageSize::EnvelopePrc8, "EnvPRC8"},
{QPageSize::EnvelopePrc9, "EnvPRC9"},
{QPageSize::EnvelopePrc10, "EnvPRC10"},
{QPageSize::EnvelopeYou4, "EnvYou4"}
};
// Return key name for PageSize
static QString qt_keyForPageSizeId(QPageSize::PageSizeId id)
{
return QString::fromLatin1(qt_pageSizes[id].mediaOption);
}
// Return id name for PPD Key
static QPageSize::PageSizeId qt_idForPpdKey(const QString &ppdKey)
{
if (ppdKey.isEmpty()) {
return QPageSize::Custom;
}
for (int i = 0; i <= int(QPageSize::LastPageSize); ++i) {
if (QLatin1String(qt_pageSizes[i].mediaOption) == ppdKey) {
return qt_pageSizes[i].id;
}
}
return QPageSize::Custom;
}
-Print::Print(QObject *parent)
- : QObject(parent)
+PrintPortal::PrintPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
{
}
-Print::~Print()
+PrintPortal::~PrintPortal()
{
}
-uint Print::print(const QDBusObjectPath &handle,
+uint PrintPortal::Print(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QDBusUnixFileDescriptor &fd,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdePrint) << "Print called with parameters:";
qCDebug(XdgDesktopPortalKdePrint) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdePrint) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdePrint) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdePrint) << " title: " << title;
qCDebug(XdgDesktopPortalKdePrint) << " fd: " << fd.fileDescriptor();
qCDebug(XdgDesktopPortalKdePrint) << " options: " << options;
QFile fileToPrint;
if (fileToPrint.open(fd.fileDescriptor(), QIODevice::ReadOnly)) {
QPrinter *printer = nullptr;
// Use printer associated with token if possible
if (options.contains(QLatin1String("token"))) {
printer = m_printers.value(options.value(QLatin1String("token")).toUInt());
} else {
// Use the last configured printer otherwise
if (m_printers.count()) {
printer = m_printers.last();
}
}
if (!printer) {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: no QPrinter what can be used for printing";
return 1;
}
// We are going to print to a file
if (!printer->outputFileName().isEmpty()) {
if (QFile::exists(printer->outputFileName())) {
QFile::remove(printer->outputFileName());
}
QByteArray pdfContent = fileToPrint.readAll();
QFile outputFile(printer->outputFileName());
if (outputFile.open(QIODevice::ReadWrite)) {
outputFile.write(pdfContent);
outputFile.close();
} else {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: couldn't open the file for writing";
}
fileToPrint.close();
return 0;
// TODO poscript support?
// Print to a printer via lpr command
} else {
// The code below is copied from Okular
bool useCupsOptions = cupsAvailable();
QString exe;
QStringList argList;
//Decide what executable to use to print with, need the CUPS version of lpr if available
//Some distros name the CUPS version of lpr as lpr-cups or lpr.cups so try those first
//before default to lpr, or failing that to lp
if (!QStandardPaths::findExecutable(QStringLiteral("lpr-cups")).isEmpty()) {
exe = QStringLiteral("lpr-cups");
} else if (!QStandardPaths::findExecutable(QStringLiteral("lpr.cups")).isEmpty()) {
exe = QStringLiteral("lpr.cups");
} else if (!QStandardPaths::findExecutable(QStringLiteral("lpr")).isEmpty()) {
exe = QStringLiteral("lpr");
} else if (!QStandardPaths::findExecutable(QStringLiteral("lp")).isEmpty()) {
exe = QStringLiteral("lp");
} else {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: couldn't run lpr command for printing";
return 1;
}
QTemporaryFile tempFile;
if (tempFile.open()) {
tempFile.write(fileToPrint.readAll());
tempFile.close();
} else {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: couldn't create temporary file for printing";
return 1;
}
argList = printArguments(printer, useCupsOptions, exe, printer->orientation()) << tempFile.fileName();
// qCDebug(XdgDesktopPortalKdePrint) << "Executing" << exe << "with arguments" << argList << tempFile.fileName();
int retValue = KProcess::execute(exe, argList);
if (retValue <= 0) {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: running KProcess failed";
return 1;
}
return retValue;
}
} else {
qCDebug(XdgDesktopPortalKdePrint) << "Failed to print: couldn't not read from fd";
return 1;
}
return 0;
}
-uint Print::preparePrint(const QDBusObjectPath &handle,
+uint PrintPortal::PreparePrint(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &settings,
const QVariantMap &page_setup,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdePrint) << "PreparePrint called with parameters:";
qCDebug(XdgDesktopPortalKdePrint) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdePrint) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdePrint) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdePrint) << " title: " << title;
qCDebug(XdgDesktopPortalKdePrint) << " settings: " << settings;
qCDebug(XdgDesktopPortalKdePrint) << " page_setup: " << page_setup;
qCDebug(XdgDesktopPortalKdePrint) << " options: " << options;
// Create new one
QPrinter *printer = new QPrinter();
// First we have to load pre-configured options
// Process settings (used by printer)
if (settings.contains(QLatin1String("orientation"))) {
// TODO: what is the difference between this and the one in page setup
}
if (settings.contains(QLatin1String("paper-format"))) {
// TODO: what is the difference between this and the one in page setup
}
if (settings.contains(QLatin1String("paper-width"))) {
// TODO: what is the difference between this and the one in page setup
}
if (settings.contains(QLatin1String("paper-height"))) {
// TODO: what is the difference between this and the one in page setup
}
if (settings.contains(QLatin1String("n-copies"))) {
printer->setCopyCount(settings.value(QLatin1String("n-copies")).toString().toInt());
}
if (settings.contains(QLatin1String("default-source"))) {
// TODO seems to be windows only stuff
}
if (settings.contains(QLatin1String("quality"))) {
// TODO doesn't seem to be used by Qt
}
if (settings.contains(QLatin1String("resolution"))) {
printer->setResolution(settings.value(QLatin1String("resolution")).toString().toInt());
}
if (settings.contains(QLatin1String("use-color"))) {
printer->setColorMode(settings.value(QLatin1String("use-color")).toString() == QLatin1String("yes") ? QPrinter::Color : QPrinter::GrayScale);
}
if (settings.contains(QLatin1String("duplex"))) {
const QString duplex = settings.value(QLatin1String("duplex")).toString();
if (duplex == QLatin1String("simplex")) {
printer->setDuplex(QPrinter::DuplexNone);
} else if (duplex == QLatin1String("horizontal")) {
printer->setDuplex(QPrinter::DuplexShortSide);
} else if (duplex == QLatin1String("vertical")) {
printer->setDuplex(QPrinter::DuplexLongSide);
}
}
if (settings.contains(QLatin1String("collate"))) {
printer->setCollateCopies(settings.value(QLatin1String("collate")).toString() == QLatin1String("yes"));
}
if (settings.contains(QLatin1String("reverse"))) {
printer->setPageOrder(settings.value(QLatin1String("reverse")).toString() == QLatin1String("yes") ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
}
if (settings.contains(QLatin1String("media-type"))) {
// TODO doesn't seem to be used by Qt
}
if (settings.contains(QLatin1String("dither"))) {
// TODO doesn't seem to be used by Qt
}
if (settings.contains(QLatin1String("scale"))) {
// TODO doesn't seem to be used by Qt
}
if (settings.contains(QLatin1String("print-pages"))) {
const QString printPages = settings.value(QLatin1String("print-pages")).toString();
if (printPages == QLatin1String("all")) {
printer->setPrintRange(QPrinter::AllPages);
} else if (printPages == QLatin1String("selection")) {
printer->setPrintRange(QPrinter::Selection);
} else if (printPages == QLatin1String("current")) {
printer->setPrintRange(QPrinter::CurrentPage);
} else if (printPages == QLatin1String("ranges")) {
printer->setPrintRange(QPrinter::PageRange);
}
}
if (settings.contains(QLatin1String("page-ranges"))) {
const QString range = settings.value(QLatin1String("page-ranges")).toString();
// Gnome supports format like 1-5,7,9,11-15, however Qt support only e.g.1-15
// so get the first and the last value
const QStringList ranges = range.split(QLatin1Char(','));
if (ranges.count()) {
QStringList firstRangeValues = ranges.first().split(QLatin1Char('-'));
QStringList lastRangeValues = ranges.last().split(QLatin1Char('-'));
printer->setFromTo(firstRangeValues.first().toInt(), lastRangeValues.last().toInt());
}
}
if (settings.contains(QLatin1String("page-set"))) {
// WARNING Qt internal private API, anyway the print dialog doesn't seem to
// read these propertis, but I'll leave it here in case this changes in future
const QString pageSet = settings.value(QLatin1String("page-set")).toString();
if (pageSet == QLatin1String("all")) {
QCUPSSupport::setPageSet(printer, QCUPSSupport::AllPages);
} else if (pageSet == QLatin1String("even")) {
QCUPSSupport::setPageSet(printer, QCUPSSupport::EvenPages);
} else if (pageSet == QLatin1String("odd")) {
QCUPSSupport::setPageSet(printer, QCUPSSupport::OddPages);
}
}
if (settings.contains(QLatin1String("finishings"))) {
// TODO doesn't seem to be used by Qt
}
QCUPSSupport::PagesPerSheet pagesPerSheet = QCUPSSupport::OnePagePerSheet;
QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = QCUPSSupport::LeftToRightTopToBottom;
if (settings.contains(QLatin1String("number-up"))) {
// WARNING Qt internal private API, anyway the print dialog doesn't seem to
// read these propertis, but I'll leave it here in case this changes in future
const QString numberUp = settings.value(QLatin1String("number-up")).toString();
if (numberUp == QLatin1String("1")) {
pagesPerSheet = QCUPSSupport::OnePagePerSheet;
} else if (numberUp == QLatin1String("2")) {
pagesPerSheet = QCUPSSupport::TwoPagesPerSheet;
} else if (numberUp == QLatin1String("4")) {
pagesPerSheet = QCUPSSupport::FourPagesPerSheet;
} else if (numberUp == QLatin1String("6")) {
pagesPerSheet = QCUPSSupport::SixPagesPerSheet;
} else if (numberUp == QLatin1String("9")) {
pagesPerSheet = QCUPSSupport::NinePagesPerSheet;
} else if (numberUp == QLatin1String("16")) {
pagesPerSheet = QCUPSSupport::SixteenPagesPerSheet;
}
}
if (settings.contains(QLatin1String("number-up-layout"))) {
// WARNING Qt internal private API, anyway the print dialog doesn't seem to
// read these propertis, but I'll leave it here in case this changes in future
const QString layout = settings.value(QLatin1String("number-up-layout")).toString();
if (layout == QLatin1String("lrtb")) {
pagesPerSheetLayout = QCUPSSupport::LeftToRightTopToBottom;
} else if (layout == QLatin1String("lrbt")) {
pagesPerSheetLayout = QCUPSSupport::LeftToRightBottomToTop;
} else if (layout == QLatin1String("rltb")) {
pagesPerSheetLayout = QCUPSSupport::RightToLeftTopToBottom;
} else if (layout == QLatin1String("rlbt")) {
pagesPerSheetLayout = QCUPSSupport::RightToLeftBottomToTop;
} else if (layout == QLatin1String("tblr")) {
pagesPerSheetLayout = QCUPSSupport::TopToBottomLeftToRight;
} else if (layout == QLatin1String("tbrl")) {
pagesPerSheetLayout = QCUPSSupport::TopToBottomRightToLeft;
} else if (layout == QLatin1String("btlr")) {
pagesPerSheetLayout = QCUPSSupport::BottomToTopLeftToRight;
} else if (layout == QLatin1String("btrl")) {
pagesPerSheetLayout = QCUPSSupport::BottomToTopRightToLeft;
}
}
QCUPSSupport::setPagesPerSheetLayout(printer, pagesPerSheet, pagesPerSheetLayout);
if (settings.contains(QLatin1String("output-bin"))) {
// TODO not sure what this setting represents
}
if (settings.contains(QLatin1String("resolution-x"))) {
// TODO possible to set only full resolution, but I can count the total
// resolution I guess, anyway doesn't seem to be used by the print dialog
}
if (settings.contains(QLatin1String("resolution-y"))) {
// TODO possible to set only full resolution, but I can count the total
// resolution I guess, anyway doesn't seem to be used by the print dialog
}
if (settings.contains(QLatin1String("printer-lpi"))) {
// TODO not possible to set, maybe count it?
}
if (settings.contains(QLatin1String("output-basename"))) {
// TODO processed in output-uri
// printer->setOutputFileName(settings.value(QLatin1String("output-basename")).toString());
}
if (settings.contains(QLatin1String("output-file-format"))) {
// TODO only PDF supported by Qt so when printing to file we can use PDF only
// btw. this should be already set automatically because we set output file name
printer->setOutputFormat(QPrinter::PdfFormat);
}
if (settings.contains(QLatin1String("output-uri"))) {
const QUrl uri = QUrl(settings.value(QLatin1String("output-uri")).toString());
// Check whether the uri is not just a directory name and whether we don't need to
// append output-basename
if (settings.contains(QLatin1String("output-basename"))) {
const QString basename = settings.value(QLatin1String("output-basename")).toString();
if (!uri.toDisplayString().endsWith(basename) && uri.toDisplayString().endsWith(QLatin1Char('/'))) {
printer->setOutputFileName(uri.toDisplayString() + basename);
}
} else {
printer->setOutputFileName(uri.toDisplayString());
}
}
// Process page setup
QMarginsF pageMargins = printer->pageLayout().margins(QPageLayout::Millimeter);
if (page_setup.contains(QLatin1String("PPDName"))) {
printer->setPageSize(QPageSize(qt_idForPpdKey(page_setup.value(QLatin1String("PPDName")).toString())));
}
if (page_setup.contains(QLatin1String("Name"))) {
// TODO: Try to use name instead of PPDName, at least I think it's how it's supposed to be used
if (!page_setup.contains(QLatin1String("PPDName"))) {
printer->setPageSize(QPageSize(qt_idForPpdKey(page_setup.value(QLatin1String("PPDName")).toString())));
}
}
if (page_setup.contains(QLatin1String("DisplayName"))) {
// TODO: This should just set a different name for the standardized one I guess
printer->setPageSize(QPageSize(printer->pageLayout().pageSize().size(QPageSize::Millimeter),
QPageSize::Millimeter, page_setup.value(QLatin1String("DisplayName")).toString()));
}
if (page_setup.contains(QLatin1String("Width")) && page_setup.contains(QLatin1String("Height"))) {
QSizeF paperSize;
paperSize.setHeight(page_setup.value(QLatin1String("Height")).toReal());
paperSize.setWidth(page_setup.value(QLatin1String("Width")).toReal());
printer->setPageSize(QPageSize(paperSize, QPageSize::Millimeter, page_setup.value(QLatin1String("DisplayName")).toString()));
}
if (page_setup.contains(QLatin1String("MarginTop"))) {
pageMargins.setTop(page_setup.value(QLatin1String("MarginTop")).toReal());
}
if (page_setup.contains(QLatin1String("MarginBottom"))) {
pageMargins.setBottom(page_setup.value(QLatin1String("MarginBottom")).toReal());
}
if (page_setup.contains(QLatin1String("MarginLeft"))) {
pageMargins.setLeft(page_setup.value(QLatin1String("MarginLeft")).toReal());
}
if (page_setup.contains(QLatin1String("MarginRight"))) {
pageMargins.setRight(page_setup.value(QLatin1String("MarginLeft")).toReal());
}
if (page_setup.contains(QLatin1String("Orientation"))) {
const QString orientation = page_setup.value(QLatin1String("Orientation")).toString();
if (orientation == QLatin1String("landscape") ||
orientation == QLatin1String("reverse_landscape")) {
printer->setPageOrientation(QPageLayout::Landscape);
} else if (orientation == QLatin1String("portrait") ||
orientation == QLatin1String("reverse_portrait")) {
printer->setPageOrientation(QPageLayout::Portrait);
}
}
printer->setPageMargins(pageMargins, QPageLayout::Millimeter);
QPrintDialog *printDialog = new QPrintDialog(printer);
// Process options
if (options.contains(QLatin1String("modal"))) {
printDialog->setModal(options.value(QLatin1String("modal")).toBool());
}
// Pass back what we configured
if (printDialog->exec() == QDialog::Accepted) {
QVariantMap resultingSettings;
QVariantMap resultingPageSetup;
// Process back printer settings
resultingSettings.insert(QLatin1String("n-copies"), QString::number(printer->copyCount()));
resultingSettings.insert(QLatin1String("resolution"), QString::number(printer->resolution()));
resultingSettings.insert(QLatin1String("use-color"), printer->colorMode() == QPrinter::Color ? QLatin1String("yes") : QLatin1String("no"));
if (printer->duplex() == QPrinter::DuplexNone) {
resultingSettings.insert(QLatin1String("duplex"), QLatin1String("simplex"));
} else if (printer->duplex() == QPrinter::DuplexShortSide) {
resultingSettings.insert(QLatin1String("duplex"), QLatin1String("horizontal"));
} else if (printer->duplex() == QPrinter::DuplexLongSide) {
resultingSettings.insert(QLatin1String("duplex"), QLatin1String("vertical"));
}
resultingSettings.insert(QLatin1String("collate"), printer->collateCopies() ? QLatin1String("yes") : QLatin1String("no"));
resultingSettings.insert(QLatin1String("reverse"), printer->pageOrder() == QPrinter::LastPageFirst ? QLatin1String("yes") : QLatin1String("no"));
if (printer->printRange() == QPrinter::AllPages) {
resultingSettings.insert(QLatin1String("print-pages"), QLatin1String("all"));
} else if (printer->printRange() == QPrinter::Selection) {
resultingSettings.insert(QLatin1String("print-pages"), QLatin1String("selection"));
} else if (printer->printRange() == QPrinter::CurrentPage) {
resultingSettings.insert(QLatin1String("print-pages"), QLatin1String("current"));
} else if (printer->printRange() == QPrinter::PageRange) {
resultingSettings.insert(QLatin1String("print-pages"), QLatin1String("ranges"));
resultingSettings.insert(QLatin1String("page-ranges"), QString("%1-%2").arg(printer->fromPage()).arg(printer->toPage()));
}
// Set cups specific properties
const QStringList cupsOptions = QCUPSSupport::cupsOptionsList(printer);
qCDebug(XdgDesktopPortalKdePrint) << cupsOptions;
if (cupsOptions.contains(QLatin1String("page-set"))) {
resultingSettings.insert(QLatin1String("page-set"), cupsOptions.at(cupsOptions.indexOf(QLatin1String("page-set")) + 1));
}
if (cupsOptions.contains(QLatin1String("number-up"))) {
resultingSettings.insert(QLatin1String("number-up"), cupsOptions.at(cupsOptions.indexOf(QLatin1String("number-up")) + 1));
}
if (cupsOptions.contains(QLatin1String("number-up-layout"))) {
resultingSettings.insert(QLatin1String("number-up-layout"), cupsOptions.at(cupsOptions.indexOf(QLatin1String("number-up-layout")) + 1));
}
if (printer->outputFormat() == QPrinter::PdfFormat) {
resultingSettings.insert(QLatin1String("output-file-format"), QLatin1String("pdf"));
}
if (!printer->outputFileName().isEmpty()) {
resultingSettings.insert(QLatin1String("output-uri"), QUrl::fromLocalFile(printer->outputFileName()).toDisplayString());
}
// Process back page setup
resultingPageSetup.insert(QLatin1String("PPDName"), qt_keyForPageSizeId(printer->pageLayout().pageSize().id()));
// TODO: verify if this make sense
resultingPageSetup.insert(QLatin1String("Name"), qt_keyForPageSizeId(printer->pageLayout().pageSize().id()));
// TODO: verify if this make sense
resultingPageSetup.insert(QLatin1String("DisplayName"), qt_keyForPageSizeId(printer->pageLayout().pageSize().id()));
resultingPageSetup.insert(QLatin1String("Width"), printer->pageLayout().pageSize().size(QPageSize::Millimeter).width());
resultingPageSetup.insert(QLatin1String("Height"), printer->pageLayout().pageSize().size(QPageSize::Millimeter).height());
resultingPageSetup.insert(QLatin1String("MarginTop"), printer->pageLayout().margins(QPageLayout::Millimeter).top());
resultingPageSetup.insert(QLatin1String("MarginBottom"), printer->pageLayout().margins(QPageLayout::Millimeter).bottom());
resultingPageSetup.insert(QLatin1String("MarginLeft"), printer->pageLayout().margins(QPageLayout::Millimeter).left());
resultingPageSetup.insert(QLatin1String("MarginRight"), printer->pageLayout().margins(QPageLayout::Millimeter).right());
resultingPageSetup.insert(QLatin1String("Orientation"), printer->pageLayout().orientation() == QPageLayout::Landscape ? QLatin1String("landscape") : QLatin1String("portrait"));
qCDebug(XdgDesktopPortalKdePrint) << "Settings: ";
qCDebug(XdgDesktopPortalKdePrint) << "---------------------------";
qCDebug(XdgDesktopPortalKdePrint) << resultingSettings;
qCDebug(XdgDesktopPortalKdePrint) << "Page setup: ";
qCDebug(XdgDesktopPortalKdePrint) << "---------------------------";
qCDebug(XdgDesktopPortalKdePrint) << resultingPageSetup;
uint token = QDateTime::currentDateTime().toTime_t();
results.insert(QLatin1String("settings"), resultingSettings);
results.insert(QLatin1String("page-setup"), resultingPageSetup);
results.insert(QLatin1String("token"), token);
m_printers.insert(token, printer);
printDialog->deleteLater();
return 0;
} else {
printDialog->deleteLater();
return 1;
}
return 0;
}
-QStringList Print::destination(const QPrinter *printer, const QString &version)
+QStringList PrintPortal::destination(const QPrinter *printer, const QString &version)
{
if (version == QLatin1String("lp")) {
return QStringList(QStringLiteral("-d")) << printer->printerName();
}
if (version.startsWith(QLatin1String("lpr"))) {
return QStringList(QStringLiteral("-P")) << printer->printerName();
}
return QStringList();
}
-QStringList Print::copies(const QPrinter *printer, const QString &version)
+QStringList PrintPortal::copies(const QPrinter *printer, const QString &version)
{
int cp = printer->actualNumCopies();
if (version == QLatin1String("lp")) {
return QStringList(QStringLiteral("-n")) << QStringLiteral("%1").arg(cp);
}
if (version.startsWith(QLatin1String("lpr"))) {
return QStringList() << QStringLiteral("-#%1").arg(cp);
}
return QStringList();
}
-QStringList Print::jobname(const QPrinter *printer, const QString &version)
+QStringList PrintPortal::jobname(const QPrinter *printer, const QString &version)
{
if (!printer->docName().isEmpty()) {
if (version == QLatin1String("lp")) {
return QStringList(QStringLiteral("-t")) << printer->docName();
}
if (version.startsWith(QLatin1String("lpr"))) {
const QString shortenedDocName = QString::fromUtf8(printer->docName().toUtf8().left(255));
return QStringList(QStringLiteral("-J")) << shortenedDocName;
}
}
return QStringList();
}
// What about Upper and MultiPurpose? And others in PPD???
-QString Print::mediaPaperSource(const QPrinter *printer)
+QString PrintPortal::mediaPaperSource(const QPrinter *printer)
{
switch (printer->paperSource()) {
case QPrinter::Auto:
return QString();
case QPrinter::Cassette:
return QStringLiteral("Cassette");
case QPrinter::Envelope:
return QStringLiteral("Envelope");
case QPrinter::EnvelopeManual:
return QStringLiteral("EnvelopeManual");
case QPrinter::FormSource:
return QStringLiteral("FormSource");
case QPrinter::LargeCapacity:
return QStringLiteral("LargeCapacity");
case QPrinter::LargeFormat:
return QStringLiteral("LargeFormat");
case QPrinter::Lower:
return QStringLiteral("Lower");
case QPrinter::MaxPageSource:
return QStringLiteral("MaxPageSource");
case QPrinter::Middle:
return QStringLiteral("Middle");
case QPrinter::Manual:
return QStringLiteral("Manual");
case QPrinter::OnlyOne:
return QStringLiteral("OnlyOne");
case QPrinter::Tractor:
return QStringLiteral("Tractor");
case QPrinter::SmallFormat:
return QStringLiteral("SmallFormat");
default:
return QString();
}
}
-QStringList Print::optionOrientation(const QPrinter *printer, QPrinter::Orientation documentOrientation)
+QStringList PrintPortal::optionOrientation(const QPrinter *printer, QPrinter::Orientation documentOrientation)
{
// portrait and landscape options rotate the document according to the document orientation
// If we want to print a landscape document as one would expect it, we have to pass the
// portrait option so that the document is not rotated additionally
if (printer->orientation() == documentOrientation) {
// the user wants the document printed as is
return QStringList(QStringLiteral("-o")) << QStringLiteral("portrait");
} else {
// the user expects the document being rotated by 90 degrees
return QStringList(QStringLiteral("-o")) << QStringLiteral("landscape");
}
}
-QStringList Print::optionDoubleSidedPrinting(const QPrinter *printer)
+QStringList PrintPortal::optionDoubleSidedPrinting(const QPrinter *printer)
{
switch (printer->duplex()) {
case QPrinter::DuplexNone:
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=one-sided");
case QPrinter::DuplexAuto:
if (printer->orientation() == QPrinter::Landscape) {
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-short-edge");
} else {
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-long-edge");
}
case QPrinter::DuplexLongSide:
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-long-edge");
case QPrinter::DuplexShortSide:
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-short-edge");
default:
return QStringList(); //Use printer default
}
}
-QStringList Print::optionPageOrder(const QPrinter *printer)
+QStringList PrintPortal::optionPageOrder(const QPrinter *printer)
{
if (printer->pageOrder() == QPrinter::LastPageFirst) {
return QStringList(QStringLiteral("-o")) << QStringLiteral("outputorder=reverse");
}
return QStringList(QStringLiteral("-o")) << QStringLiteral("outputorder=normal");
}
-QStringList Print::optionCollateCopies(const QPrinter *printer)
+QStringList PrintPortal::optionCollateCopies(const QPrinter *printer)
{
if (printer->collateCopies()) {
return QStringList(QStringLiteral("-o")) << QStringLiteral("Collate=True");
}
return QStringList(QStringLiteral("-o")) << QStringLiteral("Collate=False");
}
-QStringList Print::optionPageMargins(const QPrinter *printer)
+QStringList PrintPortal::optionPageMargins(const QPrinter *printer)
{
if (printer->printEngine()->property(QPrintEngine::PPK_PageMargins).isNull()) {
return QStringList();
} else {
qreal l, t, r, b;
printer->getPageMargins(&l, &t, &r, &b, QPrinter::Point);
return QStringList(QStringLiteral("-o")) << QStringLiteral("page-left=%1").arg(l)
<< QStringLiteral("-o") << QStringLiteral("page-top=%1").arg(t)
<< QStringLiteral("-o") << QStringLiteral("page-right=%1").arg(r)
<< QStringLiteral("-o") << QStringLiteral("page-bottom=%1").arg(b) << QStringLiteral("-o") << QStringLiteral("fit-to-page");
}
}
-QStringList Print::optionCupsProperties(const QPrinter *printer)
+QStringList PrintPortal::optionCupsProperties(const QPrinter *printer)
{
QStringList dialogOptions = printer->printEngine()->property(QPrintEngine::PrintEnginePropertyKey(0xfe00)).toStringList();
QStringList cupsOptions;
for (int i = 0; i < dialogOptions.count(); i = i + 2) {
// Ignore some cups properties as the pdf we get is already formatted using these
if (dialogOptions[i] == QLatin1String("number-up") || dialogOptions[i] == QLatin1String("number-up-layout")) {
continue;
}
if (dialogOptions[i + 1].isEmpty()) {
cupsOptions << QStringLiteral("-o") << dialogOptions[i];
} else {
cupsOptions << QStringLiteral("-o") << dialogOptions[i] + QLatin1Char('=') + dialogOptions[i + 1];
}
}
return cupsOptions;
}
-QStringList Print::optionMedia(const QPrinter *printer)
+QStringList PrintPortal::optionMedia(const QPrinter *printer)
{
if (!qt_keyForPageSizeId(printer->pageLayout().pageSize().id()).isEmpty() &&
!mediaPaperSource(printer).isEmpty()) {
return QStringList(QStringLiteral("-o")) <<
QStringLiteral("media=%1,%2").arg(qt_keyForPageSizeId(printer->pageLayout().pageSize().id()), mediaPaperSource(printer));
}
if (!qt_keyForPageSizeId(printer->pageLayout().pageSize().id()).isEmpty()) {
return QStringList(QStringLiteral("-o")) <<
QStringLiteral("media=%1").arg(qt_keyForPageSizeId(printer->pageLayout().pageSize().id()));
}
if (!mediaPaperSource(printer).isEmpty()) {
return QStringList(QStringLiteral("-o")) <<
QStringLiteral("media=%1").arg(mediaPaperSource(printer));
}
return QStringList();
}
-QStringList Print::pages(const QPrinter *printer, bool useCupsOptions, const QString &version)
+QStringList PrintPortal::pages(const QPrinter *printer, bool useCupsOptions, const QString &version)
{
if (printer->printRange() == QPrinter::PageRange) {
if (version == QLatin1String("lp")) {
return QStringList(QStringLiteral("-P")) << QStringLiteral("%1-%2").arg(printer->fromPage())
.arg(printer->toPage());
}
if (version.startsWith(QLatin1String("lpr")) && useCupsOptions) {
return QStringList(QStringLiteral("-o")) << QStringLiteral("page-ranges=%1-%2").arg(printer->fromPage())
.arg(printer->toPage());
}
}
return QStringList(); // AllPages
}
-QStringList Print::cupsOptions(const QPrinter *printer, QPrinter::Orientation documentOrientation)
+QStringList PrintPortal::cupsOptions(const QPrinter *printer, QPrinter::Orientation documentOrientation)
{
QStringList optionList;
// if (!optionMedia(printer).isEmpty()) {
// optionList << optionMedia(printer);
// }
// if (!optionOrientation(printer, documentOrientation).isEmpty()) {
// optionList << optionOrientation(printer, documentOrientation);
// }
if (!optionDoubleSidedPrinting(printer).isEmpty()) {
optionList << optionDoubleSidedPrinting(printer);
}
if (!optionPageOrder(printer).isEmpty()) {
optionList << optionPageOrder(printer);
}
if (!optionCollateCopies(printer).isEmpty()) {
optionList << optionCollateCopies(printer);
}
// if (!optionPageMargins(printer).isEmpty()) {
// optionList << optionPageMargins(printer);
// }
optionList << optionCupsProperties(printer);
return optionList;
}
-QStringList Print::printArguments(const QPrinter *printer, bool useCupsOptions,
+QStringList PrintPortal::printArguments(const QPrinter *printer, bool useCupsOptions,
const QString &version, QPrinter::Orientation documentOrientation)
{
QStringList argList;
if (!destination(printer, version).isEmpty()) {
argList << destination(printer, version);
}
// if (!copies(printer, version).isEmpty()) {
// argList << copies(printer, version);
// }
if (!jobname(printer, version).isEmpty()) {
argList << jobname(printer, version);
}
// if (!pages(printer, useCupsOptions, version).isEmpty()) {
// argList << pages(printer, useCupsOptions, version);
// }
if (useCupsOptions && !cupsOptions(printer, documentOrientation).isEmpty()) {
argList << cupsOptions(printer, documentOrientation);
}
if (version == QLatin1String("lp")) {
argList << QStringLiteral("--");
}
return argList;
}
-bool Print::cupsAvailable()
+bool PrintPortal::cupsAvailable()
{
// Ideally we would have access to the private Qt method
// QCUPSSupport::cupsAvailable() to do this as it is very complex routine.
// However, if CUPS is available then QPrinter::numCopies() will always return 1
// whereas if CUPS is not available it will return the real number of copies.
// This behaviour is guaranteed never to change, so we can use it as a reliable substitute.
QPrinter testPrinter;
testPrinter.setNumCopies(2);
return (testPrinter.numCopies() == 1);
}
diff --git a/src/print.h b/src/print.h
index ff823c7..9718167 100644
--- a/src/print.h
+++ b/src/print.h
@@ -1,77 +1,77 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_PRINT_H
#define XDG_DESKTOP_PORTAL_KDE_PRINT_H
-#include
+#include
#include
#include
#include
#include
-class Print : public QObject
+class PrintPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Print")
public:
- Print(QObject *parent = nullptr);
- ~Print();
+ PrintPortal(QObject *parent);
+ ~PrintPortal();
public Q_SLOTS:
- uint print(const QDBusObjectPath &handle,
+ uint Print(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QDBusUnixFileDescriptor &fd,
const QVariantMap &options,
QVariantMap &results);
- uint preparePrint(const QDBusObjectPath &handle,
+ uint PreparePrint(const QDBusObjectPath &handle,
const QString &app_id,
const QString &parent_window,
const QString &title,
const QVariantMap &settings,
const QVariantMap &page_setup,
const QVariantMap &options,
QVariantMap &results);
private:
QMap m_printers;
bool cupsAvailable();
QStringList printArguments(const QPrinter *printer, bool useCupsOptions, const QString &version,
QPrinter::Orientation documentOrientation);
QStringList destination(const QPrinter *printer, const QString &version);
QStringList copies(const QPrinter *printer, const QString &version);
QStringList jobname(const QPrinter *printer, const QString &version);
QStringList cupsOptions(const QPrinter *printer, QPrinter::Orientation documentOrientation);
QStringList pages(const QPrinter *printer, bool useCupsOptions, const QString &version);
QStringList optionMedia(const QPrinter *printer);
QString mediaPaperSource(const QPrinter *printer);
QStringList optionOrientation(const QPrinter *printer, QPrinter::Orientation documentOrientation);
QStringList optionDoubleSidedPrinting(const QPrinter *printer);
QStringList optionPageOrder(const QPrinter *printer);
QStringList optionCollateCopies(const QPrinter *printer);
QStringList optionPageMargins(const QPrinter *printer);
QStringList optionCupsProperties(const QPrinter *printer);
};
#endif // XDG_DESKTOP_PORTAL_KDE_PRINT_H
diff --git a/src/xdg-desktop-portal-kde.cpp b/src/xdg-desktop-portal-kde.cpp
index ad48e79..98f3039 100644
--- a/src/xdg-desktop-portal-kde.cpp
+++ b/src/xdg-desktop-portal-kde.cpp
@@ -1,48 +1,48 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include
#include
#include
#include "desktopportal.h"
Q_LOGGING_CATEGORY(XdgDesktopPortalKde, "xdg-desktop-portal-kde")
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (sessionBus.registerService(QLatin1String("org.freedesktop.impl.portal.desktop.kde"))) {
DesktopPortal *desktopPortal = new DesktopPortal(&a);
- if (sessionBus.registerVirtualObject(QLatin1String("/org/freedesktop/portal/desktop"), desktopPortal, QDBusConnection::VirtualObjectRegisterOption::SingleNode)) {
+ if (sessionBus.registerObject(QLatin1String("/org/freedesktop/portal/desktop"), desktopPortal, QDBusConnection::ExportAdaptors)) {
qCDebug(XdgDesktopPortalKde) << "Desktop portal registered successfuly";
} else {
qCDebug(XdgDesktopPortalKde) << "Failed to register desktop portal";
}
} else {
qCDebug(XdgDesktopPortalKde) << "Failed to register org.freedesktop.impl.portal.desktop.kde service";
}
return a.exec();
}