Add xdg-portal backend

This commit is contained in:
Victor Tran 2021-08-13 01:30:30 +10:00
parent 25850aadeb
commit 87e130e942
No known key found for this signature in database
GPG key ID: 1F0729FE016CDC3E
14 changed files with 649 additions and 0 deletions

View file

@ -0,0 +1,57 @@
QT += gui widgets thelib thefile
SHARE_APP_NAME = thedesk/portal
TARGET = thedesk-desktop-portal
CONFIG += c++11 console
CONFIG -= app_bundle
# Include the-libs build tools
include(/usr/share/the-libs/pri/buildmaster.pri)
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
dialogs/filedialog.cpp \
interfaces/filechooserinterface.cpp \
main.cpp \
portalhandle.cpp
DBUS_ADAPTOR_HEADERS = portalhandle.h
qtPrepareTool(QDBUSCPP2XML, qdbuscpp2xml)
cpp2xml.output = ${QMAKE_FILE_BASE}.xml
cpp2xml.commands = $$QDBUSCPP2XML -a -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
cpp2xml.input = DBUS_ADAPTOR_HEADERS
cpp2xml.CONFIG = no_link target_predeps
cpp2xml.variable_out = DBUS_ADAPTORS
QMAKE_EXTRA_COMPILERS += cpp2xml
DBUS_ADAPTORS = portalhandle.xml
unix {
target.path = $$THELIBS_INSTALL_LIB
portaldef.files = thedesk.portal
portaldef.path = $$THELIBS_INSTALL_PREFIX/share/xdg-desktop-portal/portals
dbusactivation.files = org.freedesktop.impl.portal.desktop.thedesk.service
dbusactivation.path = $$THELIBS_INSTALL_PREFIX/share/dbus-1/services
INSTALLS += target portaldef dbusactivation
}
DISTFILES += \
org.freedesktop.impl.portal.desktop.thedesk.service \
thedesk.portal
HEADERS += \
dialogs/filedialog.h \
interfaces/filechooserinterface.h \
portalhandle.h
FORMS += \
dialogs/filedialog.ui

View file

@ -0,0 +1,153 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#include "filedialog.h"
#include "ui_filedialog.h"
#include <QDBusMetaType>
struct FileDialogPrivate {
QStringList urls;
};
struct Filter {
uint type;
QString pattern;
};
Q_DECLARE_METATYPE(Filter)
QDBusArgument& operator<<(QDBusArgument& argument, const Filter& filter) {
argument.beginStructure();
argument << filter.type << filter.pattern;
argument.endStructure();
return argument;
}
const QDBusArgument& operator>>(const QDBusArgument& argument, Filter& filter) {
argument.beginStructure();
argument >> filter.type >> filter.pattern;
argument.endStructure();
return argument;
}
struct FilterCategory {
QString name;
QList<Filter> filters;
};
Q_DECLARE_METATYPE(FilterCategory)
QDBusArgument& operator<<(QDBusArgument& argument, const FilterCategory& filter) {
argument.beginStructure();
argument << filter.name << filter.filters;
argument.endStructure();
return argument;
}
const QDBusArgument& operator>>(const QDBusArgument& argument, FilterCategory& filter) {
argument.beginStructure();
argument >> filter.name >> filter.filters;
argument.endStructure();
return argument;
}
FileDialog::FileDialog(bool isSave, QVariantMap options, QWidget* parent) :
QDialog(parent),
ui(new Ui::FileDialog) {
ui->setupUi(this);
d = new FileDialogPrivate();
ui->titleLabel->setBackButtonShown(true);
QString openButtonText = options.value("accept_label", isSave ? tr("Overwrite") : tr("Open")).toString();
QIcon openButtonIcon = QIcon::fromTheme(isSave ? "document-save" : "document-open");
ui->filePicker->setOpenFileButtons({
{
openButtonText,
openButtonIcon,
[ = ](QList<QUrl> selected) {
for (QUrl url : selected) {
d->urls.append(url.toString());
}
this->accept();
}
}
});
if (isSave) {
ui->filePicker->setColumnActions({
{
tr("Save Here"),
tr("Create New File Here"),
[ = ](DirectoryPtr directory) {
//TODO
}
}
});
}
//Set up filters
qDBusRegisterMetaType<Filter>();
qDBusRegisterMetaType<FilterCategory>();
qDBusRegisterMetaType<QList<Filter>>();
qDBusRegisterMetaType<QList<FilterCategory>>();
QDBusArgument filtersArgument = options.value("filters").value<QDBusArgument>();
QList<FilterCategory> filters;
filtersArgument >> filters;
QList<FileTab::Filter> pickerFilters;
for (FilterCategory filterCatg : filters) {
for (Filter filter : filterCatg.filters) {
pickerFilters.append(FileTab::Filter{filter.type == 1, filter.pattern});
}
}
ui->filePicker->setFilters(pickerFilters);
this->resize(SC_DPI_T(this->size(), QSize));
}
FileDialog::~FileDialog() {
delete d;
delete ui;
}
QStringList FileDialog::uris() {
return d->urls;
}
QVariant FileDialog::choices() {
return QVariant();
}
bool FileDialog::isWritable() {
return true;
}
void FileDialog::setWindowTitle(QString windowTitle) {
QDialog::setWindowTitle(windowTitle);
ui->titleLabel->setText(windowTitle);
}
void FileDialog::on_titleLabel_backButtonClicked() {
this->reject();
}

View file

@ -0,0 +1,52 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#ifndef FILEDIALOG_H
#define FILEDIALOG_H
#include <QDialog>
#include <QDBusMessage>
namespace Ui {
class FileDialog;
}
struct FileDialogPrivate;
class FileDialog : public QDialog {
Q_OBJECT
public:
explicit FileDialog(bool isSave, QVariantMap options, QWidget* parent = nullptr);
~FileDialog();
QStringList uris();
QVariant choices();
bool isWritable();
void setWindowTitle(QString windowTitle);
private slots:
void on_titleLabel_backButtonClicked();
private:
Ui::FileDialog* ui;
FileDialogPrivate* d;
};
#endif // FILEDIALOG_H

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FileDialog</class>
<widget class="QDialog" name="FileDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>945</width>
<height>661</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="tTitleLabel" name="titleLabel">
<property name="text">
<string>Dialog Title</string>
</property>
</widget>
</item>
<item>
<widget class="FileTab" name="filePicker" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>tTitleLabel</class>
<extends>QLabel</extends>
<header location="global">ttitlelabel.h</header>
<slots>
<signal>backButtonClicked()</signal>
</slots>
</customwidget>
<customwidget>
<class>FileTab</class>
<extends>QWidget</extends>
<header location="global">filetab.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,113 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#include "filechooserinterface.h"
#include "portalhandle.h"
#include "dialogs/filedialog.h"
#include <tlogger.h>
#include <QWindow>
#include <QDBusVariant>
FileChooserInterface::FileChooserInterface(QObject* parent) : QDBusAbstractAdaptor(parent) {
}
uint FileChooserInterface::OpenFile(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results) {
tDebug("FileChooserInterface") << "Open File";
PortalHandle* portalHandle = new PortalHandle(handle);
FileDialog* dialog = new FileDialog(false, options);
if (parent_window.startsWith("x11:")) {
int winId = parent_window.mid(4).toInt();
QWindow* parentWindow = QWindow::fromWinId(winId);
dialog->createWinId();
// if (parentWindow) {
// dialog->windowHandle()->setParent(parentWindow);
// dialog->windowHandle()->setModality(Qt::WindowModal);
// }
}
if (title.isEmpty()) {
dialog->setWindowTitle(tr("Open"));
} else {
dialog->setWindowTitle(title);
}
if (dialog->exec() == FileDialog::Accepted) {
results.insert("uris", dialog->uris());
// results.insert("choices", dialog->choices());
results.insert("writable", dialog->isWritable());
portalHandle->deleteLater();
return 0;
} else {
portalHandle->deleteLater();
return 1;
}
connect(portalHandle, &PortalHandle::closed, this, [ = ] {
dialog->close();
});
}
uint FileChooserInterface::SaveFile(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results) {
PortalHandle* portalHandle = new PortalHandle(handle);
FileDialog* dialog = new FileDialog(true, options);
if (parent_window.startsWith("x11:")) {
int winId = parent_window.mid(4).toInt();
QWindow* parentWindow = QWindow::fromWinId(winId);
dialog->createWinId();
// if (parentWindow) {
// dialog->windowHandle()->setParent(parentWindow);
// dialog->windowHandle()->setModality(Qt::WindowModal);
// }
}
if (title.isEmpty()) {
dialog->setWindowTitle(tr("Save"));
} else {
dialog->setWindowTitle(title);
}
if (dialog->exec() == FileDialog::Accepted) {
results.insert("uris", dialog->uris());
// results.insert("choices", dialog->choices());
results.insert("writable", dialog->isWritable());
portalHandle->deleteLater();
return 0;
} else {
portalHandle->deleteLater();
return 1;
}
connect(portalHandle, &PortalHandle::closed, this, [ = ] {
dialog->close();
});
return 0;
}
uint FileChooserInterface::SaveFiles(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results) {
return 0;
}

View file

@ -0,0 +1,44 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#ifndef FILECHOOSERINTERFACE_H
#define FILECHOOSERINTERFACE_H
#include <QObject>
#include <QDBusAbstractAdaptor>
#include <QDBusObjectPath>
#include <QDBusMessage>
class FileChooserInterface : public QDBusAbstractAdaptor {
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.FileChooser")
public:
explicit FileChooserInterface(QObject* parent = nullptr);
public slots:
Q_SCRIPTABLE uint OpenFile(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results);
Q_SCRIPTABLE uint SaveFile(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results);
Q_SCRIPTABLE uint SaveFiles(const QDBusObjectPath& handle, const QString& app_id, const QString& parent_window, const QString& title, const QVariantMap& options, const QDBusMessage& message, QVariantMap& results);
signals:
};
#endif // FILECHOOSERINTERFACE_H

37
desktop-portal/main.cpp Normal file
View file

@ -0,0 +1,37 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#include <tapplication.h>
#include "interfaces/filechooserinterface.h"
#include <QDBusConnection>
int main(int argc, char* argv[]) {
tApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
QDBusConnection::sessionBus().registerService("org.freedesktop.impl.portal.desktop.thedesk");
QObject* rootDbusObject = new QObject();
new FileChooserInterface(rootDbusObject);
QDBusConnection::sessionBus().registerObject("/org/freedesktop/portal/desktop", rootDbusObject, QDBusConnection::ExportAdaptors);
return a.exec();
}

View file

@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.freedesktop.impl.portal.desktop.thedesk
Exec=/usr/lib/xdg-desktop-portal-thedesk
SystemdService=xdg-desktop-portal-thedesk.service

View file

@ -0,0 +1,32 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#include "portalhandle.h"
#include "portalhandle_adaptor.h"
PortalHandle::PortalHandle(QDBusObjectPath path, QObject* parent) : QObject(parent) {
new RequestAdaptor(this);
QDBusConnection::sessionBus().registerObject(path.path(), this);
}
void PortalHandle::Close() {
emit closed();
}

View file

@ -0,0 +1,40 @@
/****************************************
*
* INSERT-PROJECT-NAME-HERE - INSERT-GENERIC-NAME-HERE
* Copyright (C) 2021 Victor Tran
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* *************************************/
#ifndef PORTALHANDLE_H
#define PORTALHANDLE_H
#include <QObject>
#include <QDBusObjectPath>
class PortalHandle : public QObject {
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Request");
public:
explicit PortalHandle(QDBusObjectPath path, QObject* parent = nullptr);
public slots:
Q_SCRIPTABLE void Close();
signals:
void closed();
};
#endif // PORTALHANDLE_H

View file

@ -0,0 +1,4 @@
[portal]
DBusName=org.freedesktop.impl.portal.desktop.thedesk
Interfaces=org.freedesktop.impl.portal.FileChooser
UseIn=thedesk

View file

@ -0,0 +1 @@
<クd<>箆!ソ`。スン

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" sourcelanguage="en_US">
<context>
<name>FileChooserInterface</name>
<message>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FileDialog</name>
<message>
<source>Dialog</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dialog Title</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Overwrite</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Save Here</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Create New File Here</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -13,6 +13,7 @@ startdeskproj.depends = libraryproj
SUBDIRS = libraryproj \
deskproj \
desktop-portal \
platform \
pluginsproj \
polkitagent \