Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package xdg-desktop-portal-lxqt for
openSUSE:Factory checked in at 2026-04-22 16:57:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xdg-desktop-portal-lxqt (Old)
and /work/SRC/openSUSE:Factory/.xdg-desktop-portal-lxqt.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xdg-desktop-portal-lxqt"
Wed Apr 22 16:57:47 2026 rev:10 rq:1348594 version:1.4.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/xdg-desktop-portal-lxqt/xdg-desktop-portal-lxqt.changes
2025-11-06 18:17:08.121389114 +0100
+++
/work/SRC/openSUSE:Factory/.xdg-desktop-portal-lxqt.new.11940/xdg-desktop-portal-lxqt.changes
2026-04-22 16:58:19.840858431 +0200
@@ -1,0 +2,7 @@
+Tue Apr 21 01:12:19 UTC 2026 - Shawn Dunn <[email protected]>
+
+- Update to version 1.4.0:
+ * Added support for setting parent window on Wayland
+ * Added access portal and refactored shared choice types
+
+-------------------------------------------------------------------
Old:
----
xdg-desktop-portal-lxqt-1.3.0.tar.xz
xdg-desktop-portal-lxqt-1.3.0.tar.xz.asc
New:
----
xdg-desktop-portal-lxqt-1.4.0.tar.xz
xdg-desktop-portal-lxqt-1.4.0.tar.xz.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ xdg-desktop-portal-lxqt.spec ++++++
--- /var/tmp/diff_new_pack.mhKD1S/_old 2026-04-22 16:58:20.528886902 +0200
+++ /var/tmp/diff_new_pack.mhKD1S/_new 2026-04-22 16:58:20.532887067 +0200
@@ -17,7 +17,7 @@
Name: xdg-desktop-portal-lxqt
-Version: 1.3.0
+Version: 1.4.0
Release: 0
Summary: A backend implementation for xdg-desktop-portal
License: LGPL-2.1-or-later
@@ -25,17 +25,22 @@
Source0: %{url}/releases/download/%{version}/%{name}-%{version}.tar.xz
Source1:
%{url}/releases/download/%{version}/%{name}-%{version}.tar.xz.asc
Source2: %{name}.keyring
+
BuildRequires: cmake >= 3.5.0
+BuildRequires: desktop-file-utils
BuildRequires: gcc-c++
BuildRequires: pkgconfig
BuildRequires: qt6-gui-private-devel
+
BuildRequires: cmake(KF6WindowSystem)
BuildRequires: cmake(Qt6Core)
BuildRequires: cmake(Qt6DBus)
BuildRequires: cmake(Qt6Widgets)
BuildRequires: cmake(fm-qt6)
+
BuildRequires: pkgconfig(libexif)
BuildRequires: pkgconfig(libmenu-cache)
+
Requires: xdg-desktop-portal
Supplements: (xdg-desktop-portal and lxqt-session)
@@ -62,6 +67,9 @@
%preun
%systemd_user_preun %{name}.service
+%check
+desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
+
%files
%doc README.md
%{_libexecdir}/%{name}
++++++ xdg-desktop-portal-lxqt-1.3.0.tar.xz ->
xdg-desktop-portal-lxqt-1.4.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/CHANGELOG
new/xdg-desktop-portal-lxqt-1.4.0/CHANGELOG
--- old/xdg-desktop-portal-lxqt-1.3.0/CHANGELOG 2025-11-05 13:49:16.000000000
+0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/CHANGELOG 2026-04-20 18:31:50.000000000
+0200
@@ -1,3 +1,8 @@
+xdg-desktop-portal-lxqt-1.4.0 / 2026-04-20
+==========================================
+ * Added support for setting parent window on Wayland.
+ * Added access portal and refactored shared choice types.
+
xdg-desktop-portal-lxqt-1.3.0 / 2025-11-05
==========================================
* Use native systemd service.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/CMakeLists.txt
new/xdg-desktop-portal-lxqt-1.4.0/CMakeLists.txt
--- old/xdg-desktop-portal-lxqt-1.3.0/CMakeLists.txt 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/CMakeLists.txt 2026-04-20
18:31:50.000000000 +0200
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.18.0)
-set(PROJECT_VERSION "1.3.0")
+set(PROJECT_VERSION "1.4.0")
project(xdg-desktop-portal-lxqt VERSION ${PROJECT_VERSION})
set(QT_MIN_VERSION "6.6.0")
-set(LIBFMQT_MINIMUM_VERSION "2.3.0")
+set(LIBFMQT_MINIMUM_VERSION "2.4.0")
set(KF6_MIN_VERSION "6.0.0")
set(CMAKE_AUTOMOC on)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/README.md
new/xdg-desktop-portal-lxqt-1.4.0/README.md
--- old/xdg-desktop-portal-lxqt-1.3.0/README.md 2025-11-05 13:49:16.000000000
+0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/README.md 2026-04-20 18:31:50.000000000
+0200
@@ -1,7 +1,7 @@
# xdg-desktop-portal-lxqt
A backend implementation for
[xdg-desktop-portal](http://github.com/flatpak/xdg-desktop-portal)
-that is using Qt/KF5/libfm-qt.
+that is using Qt/KF6/libfm-qt.
## Building xdg-desktop-portal-lxqt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/data/lxqt-portals.conf
new/xdg-desktop-portal-lxqt-1.4.0/data/lxqt-portals.conf
--- old/xdg-desktop-portal-lxqt-1.3.0/data/lxqt-portals.conf 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/data/lxqt-portals.conf 2026-04-20
18:31:50.000000000 +0200
@@ -1,3 +1,4 @@
[preferred]
default=lxqt
+org.freedesktop.impl.portal.Access=lxqt;gtk;
org.freedesktop.impl.portal.FileChooser=lxqt;gtk;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/data/lxqt.portal
new/xdg-desktop-portal-lxqt-1.4.0/data/lxqt.portal
--- old/xdg-desktop-portal-lxqt-1.3.0/data/lxqt.portal 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/data/lxqt.portal 2026-04-20
18:31:50.000000000 +0200
@@ -1,4 +1,4 @@
[portal]
DBusName=org.freedesktop.impl.portal.desktop.lxqt
-Interfaces=org.freedesktop.impl.portal.FileChooser
+Interfaces=org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.FileChooser
UseIn=LXQt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/CMakeLists.txt
new/xdg-desktop-portal-lxqt-1.4.0/src/CMakeLists.txt
--- old/xdg-desktop-portal-lxqt-1.3.0/src/CMakeLists.txt 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/CMakeLists.txt 2026-04-20
18:31:50.000000000 +0200
@@ -1,5 +1,7 @@
set(SRCS
utils.cpp
+ access.cpp
+ choices.cpp
filedialoghelper.cpp
filechooser.cpp
desktopportal.cpp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/access.cpp
new/xdg-desktop-portal-lxqt-1.4.0/src/access.cpp
--- old/xdg-desktop-portal-lxqt-1.3.0/src/access.cpp 1970-01-01
01:00:00.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/access.cpp 2026-04-20
18:31:50.000000000 +0200
@@ -0,0 +1,177 @@
+/* BEGIN_COMMON_COPYRIGHT_HEADER
+ * (c)LGPL2+
+ *
+ * LXQt - a lightweight, Qt based, desktop toolset
+ * https://lxqt-project.org
+ *
+ * Copyright: 2026~ LXQt team
+ * Authors:
+ * Basil Crow <[email protected]>
+ *
+ * This program or library 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.1 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * END_COMMON_COPYRIGHT_HEADER */
+
+#include "access.h"
+#include "choices.h"
+#include "utils.h"
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDBusArgument>
+#include <QDBusObjectPath>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QEventLoop>
+#include <QIcon>
+#include <QLabel>
+#include <QLoggingCategory>
+#include <QPushButton>
+#include <QToolButton>
+#include <QVBoxLayout>
+
+namespace LXQt
+{
+ Q_LOGGING_CATEGORY(XdgDesktopPortalLxqtAccess, "xdp-lxqt-access")
+
+ AccessPortal::AccessPortal(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
+ {
+ registerChoiceMetaTypes();
+ }
+
+ 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)
+ {
+ Q_UNUSED(app_id);
+
+ qCDebug(XdgDesktopPortalLxqtAccess) << "AccessDialog called with
parameters:";
+ qCDebug(XdgDesktopPortalLxqtAccess) << " handle: " << handle.path();
+ qCDebug(XdgDesktopPortalLxqtAccess) << " parent_window: " <<
parent_window;
+ qCDebug(XdgDesktopPortalLxqtAccess) << " title: " << title;
+ qCDebug(XdgDesktopPortalLxqtAccess) << " subtitle: " << subtitle;
+ qCDebug(XdgDesktopPortalLxqtAccess) << " body: " << body;
+ qCDebug(XdgDesktopPortalLxqtAccess) << " options: " << options;
+
+ bool modalDialog = true;
+ if (options.contains(QStringLiteral("modal"))) {
+ modalDialog = options.value(QStringLiteral("modal")).toBool();
+ }
+
+ QString grantLabel = tr("Grant Access");
+ if (options.contains(QStringLiteral("grant_label"))) {
+ grantLabel =
options.value(QStringLiteral("grant_label")).toString();
+ Utils::convertGtkMnemonic(grantLabel);
+ }
+
+ QString denyLabel = tr("Deny Access");
+ if (options.contains(QStringLiteral("deny_label"))) {
+ denyLabel = options.value(QStringLiteral("deny_label")).toString();
+ Utils::convertGtkMnemonic(denyLabel);
+ }
+
+ // for handling of options - choices
+ QMap<QString, QCheckBox *> checkboxes;
+ QMap<QString, QComboBox *> comboboxes;
+ std::unique_ptr<QWidget> choiceControls;
+ bool hasChoices = false;
+
+ if (options.contains(QStringLiteral("choices"))) {
+ OptionList optionList =
+
qdbus_cast<OptionList>(options.value(QStringLiteral("choices")));
+ choiceControls.reset(CreateChoiceControls(optionList, checkboxes,
comboboxes));
+ hasChoices = choiceControls != nullptr;
+ }
+
+ QDialog dialog;
+ dialog.setWindowTitle(title);
+ dialog.setWindowModality(modalDialog ? Qt::ApplicationModal :
Qt::NonModal);
+ Utils::setParentWindow(&dialog, parent_window);
+
+ QVBoxLayout *layout = new QVBoxLayout(&dialog);
+
+ // Icon
+ if (options.contains(QStringLiteral("icon"))) {
+ const QString iconName =
options.value(QStringLiteral("icon")).toString();
+ const QIcon icon = QIcon::fromTheme(iconName);
+ if (!icon.isNull()) {
+ QToolButton *iconWidget = new QToolButton(&dialog);
+ iconWidget->setIcon(icon);
+ iconWidget->setIconSize(QSize(48, 48));
+ iconWidget->setAutoRaise(true);
+ iconWidget->setFocusPolicy(Qt::NoFocus);
+ layout->addWidget(iconWidget, 0, Qt::AlignCenter);
+ }
+ }
+
+ // Subtitle (bold/larger)
+ if (!subtitle.isEmpty()) {
+ QLabel *subtitleLabel = new QLabel(&dialog);
+ QFont boldFont = subtitleLabel->font();
+ boldFont.setBold(true);
+ boldFont.setPointSizeF(boldFont.pointSizeF() * 1.2);
+ subtitleLabel->setFont(boldFont);
+ subtitleLabel->setTextFormat(Qt::PlainText);
+ subtitleLabel->setText(subtitle);
+ subtitleLabel->setWordWrap(true);
+ layout->addWidget(subtitleLabel);
+ }
+
+ // Body text
+ if (!body.isEmpty()) {
+ QLabel *bodyLabel = new QLabel(&dialog);
+ bodyLabel->setTextFormat(Qt::PlainText);
+ bodyLabel->setText(body);
+ bodyLabel->setWordWrap(true);
+ layout->addWidget(bodyLabel);
+ }
+
+ // Choice controls
+ if (hasChoices) {
+ layout->addWidget(choiceControls.release());
+ }
+
+ // Buttons
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(&dialog);
+ QPushButton *grantButton = buttonBox->addButton(grantLabel,
QDialogButtonBox::AcceptRole);
+ buttonBox->addButton(denyLabel, QDialogButtonBox::RejectRole);
+ grantButton->setDefault(true);
+ QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog,
&QDialog::accept);
+ QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog,
&QDialog::reject);
+ layout->addWidget(buttonBox);
+
+ QEventLoop loop;
+ QObject::connect(&dialog, &QDialog::finished, &loop,
&QEventLoop::quit);
+ dialog.open();
+ loop.exec();
+
+ if (dialog.result() == QDialog::Accepted) {
+ if (hasChoices) {
+ QVariant choices = EvaluateSelectedChoices(checkboxes,
comboboxes);
+ results.insert(QStringLiteral("choices"), choices);
+ }
+ return 0;
+ }
+
+ return 1;
+ }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/access.h
new/xdg-desktop-portal-lxqt-1.4.0/src/access.h
--- old/xdg-desktop-portal-lxqt-1.3.0/src/access.h 1970-01-01
01:00:00.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/access.h 2026-04-20
18:31:50.000000000 +0200
@@ -0,0 +1,53 @@
+/* BEGIN_COMMON_COPYRIGHT_HEADER
+ * (c)LGPL2+
+ *
+ * LXQt - a lightweight, Qt based, desktop toolset
+ * https://lxqt-project.org
+ *
+ * Copyright: 2026~ LXQt team
+ * Authors:
+ * Basil Crow <[email protected]>
+ *
+ * This program or library 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.1 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * END_COMMON_COPYRIGHT_HEADER */
+
+#pragma once
+
+#include <QDBusAbstractAdaptor>
+
+class QDBusObjectPath;
+
+namespace LXQt
+{
+ class AccessPortal : public QDBusAbstractAdaptor
+ {
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Access")
+ public:
+ explicit AccessPortal(QObject *parent);
+
+ public Q_SLOTS:
+ 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);
+ };
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/choices.cpp
new/xdg-desktop-portal-lxqt-1.4.0/src/choices.cpp
--- old/xdg-desktop-portal-lxqt-1.3.0/src/choices.cpp 1970-01-01
01:00:00.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/choices.cpp 2026-04-20
18:31:50.000000000 +0200
@@ -0,0 +1,159 @@
+/* BEGIN_COMMON_COPYRIGHT_HEADER
+ * (c)LGPL2+
+ *
+ * LXQt - a lightweight, Qt based, desktop toolset
+ * https://lxqt-project.org
+ *
+ * Copyright: 2016-2018 Red Hat Inc
+ * Copyright: 2016-2018 Jan Grulich <[email protected]>
+ * Copyright: 2021~ LXQt team
+ * Authors:
+ * Palo Kisa <[email protected]>
+ *
+ * This program or library 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.1 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * END_COMMON_COPYRIGHT_HEADER */
+
+#include "choices.h"
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDBusArgument>
+#include <QDBusMetaType>
+#include <QGridLayout>
+#include <QLabel>
+
+namespace LXQt
+{
+ QDBusArgument &operator<<(QDBusArgument &arg, const Choice &choice)
+ {
+ arg.beginStructure();
+ arg << choice.id << choice.value;
+ arg.endStructure();
+ return arg;
+ }
+
+ const QDBusArgument &operator>>(const QDBusArgument &arg, Choice &choice)
+ {
+ QString id;
+ QString value;
+ arg.beginStructure();
+ arg >> id >> value;
+ choice.id = id;
+ choice.value = value;
+ arg.endStructure();
+ return arg;
+ }
+
+ QDBusArgument &operator<<(QDBusArgument &arg, const Option &option)
+ {
+ arg.beginStructure();
+ arg << option.id << option.label << option.choices <<
option.initialChoiceId;
+ arg.endStructure();
+ return arg;
+ }
+
+ const QDBusArgument &operator>>(const QDBusArgument &arg, Option &option)
+ {
+ QString id;
+ QString label;
+ Choices choices;
+ QString initialChoiceId;
+ arg.beginStructure();
+ arg >> id >> label >> choices >> initialChoiceId;
+ option.id = id;
+ option.label = label;
+ option.choices = choices;
+ option.initialChoiceId = initialChoiceId;
+ arg.endStructure();
+ return arg;
+ }
+
+ void registerChoiceMetaTypes()
+ {
+ qDBusRegisterMetaType<Choice>();
+ qDBusRegisterMetaType<Choices>();
+ qDBusRegisterMetaType<Option>();
+ qDBusRegisterMetaType<OptionList>();
+ }
+
+ QWidget *CreateChoiceControls(const OptionList &optionList,
+ QMap<QString, QCheckBox *> &checkboxes,
+ QMap<QString, QComboBox *> &comboboxes)
+ {
+ if (optionList.empty()) {
+ return nullptr;
+ }
+
+ QWidget *optionsWidget = new QWidget;
+ QGridLayout *layout = new QGridLayout(optionsWidget);
+ // set stretch for (unused) column 2 so controls only take the space
they actually need
+ layout->setColumnStretch(2, 1);
+ optionsWidget->setLayout(layout);
+
+ for (const Option &option : optionList) {
+ const int nextRow = layout->rowCount();
+ // empty list of choices -> boolean choice according to the spec
+ if (option.choices.empty()) {
+ QCheckBox *checkbox = new QCheckBox(option.label,
optionsWidget);
+ checkbox->setChecked(option.initialChoiceId ==
QStringLiteral("true"));
+ layout->addWidget(checkbox, nextRow, 1);
+ checkboxes.insert(option.id, checkbox);
+ } else {
+ QComboBox *combobox = new QComboBox(optionsWidget);
+ for (const Choice &choice : option.choices) {
+ combobox->addItem(choice.value, choice.id);
+ // select this entry if initialChoiceId matches
+ if (choice.id == option.initialChoiceId) {
+ combobox->setCurrentIndex(combobox->count() - 1);
+ }
+ }
+ QString labelText = option.label;
+ if (!labelText.endsWith(QChar::fromLatin1(':'))) {
+ labelText += QChar::fromLatin1(':');
+ }
+ QLabel *label = new QLabel(labelText, optionsWidget);
+ label->setBuddy(combobox);
+ layout->addWidget(label, nextRow, 0, Qt::AlignRight);
+ layout->addWidget(combobox, nextRow, 1);
+ comboboxes.insert(option.id, combobox);
+ }
+ }
+
+ return optionsWidget;
+ }
+
+ QVariant EvaluateSelectedChoices(const QMap<QString, QCheckBox *>
&checkboxes, const QMap<QString, QComboBox *> &comboboxes)
+ {
+ Choices selectedChoices;
+ const auto checkboxKeys = checkboxes.keys();
+ for (const QString &id : checkboxKeys) {
+ Choice choice;
+ choice.id = id;
+ choice.value = checkboxes.value(id)->isChecked() ?
QStringLiteral("true") : QStringLiteral("false");
+ selectedChoices << choice;
+ }
+ const auto comboboxKeys = comboboxes.keys();
+ for (const QString &id : comboboxKeys) {
+ Choice choice;
+ choice.id = id;
+ choice.value = comboboxes.value(id)->currentData().toString();
+ selectedChoices << choice;
+ }
+
+ return QVariant::fromValue<Choices>(selectedChoices);
+ }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/choices.h
new/xdg-desktop-portal-lxqt-1.4.0/src/choices.h
--- old/xdg-desktop-portal-lxqt-1.3.0/src/choices.h 1970-01-01
01:00:00.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/choices.h 2026-04-20
18:31:50.000000000 +0200
@@ -0,0 +1,73 @@
+/* BEGIN_COMMON_COPYRIGHT_HEADER
+ * (c)LGPL2+
+ *
+ * LXQt - a lightweight, Qt based, desktop toolset
+ * https://lxqt-project.org
+ *
+ * Copyright: 2016-2018 Red Hat Inc
+ * Copyright: 2016-2018 Jan Grulich <[email protected]>
+ * Copyright: 2021~ LXQt team
+ * Authors:
+ * Palo Kisa <[email protected]>
+ *
+ * This program or library 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.1 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * END_COMMON_COPYRIGHT_HEADER */
+
+#pragma once
+
+#include <QList>
+#include <QMap>
+#include <QString>
+#include <QVariant>
+
+class QCheckBox;
+class QComboBox;
+class QDBusArgument;
+class QWidget;
+
+namespace LXQt
+{
+ struct Choice {
+ QString id;
+ QString value;
+ };
+ using Choices = QList<Choice>;
+
+ struct Option {
+ QString id;
+ QString label;
+ Choices choices;
+ QString initialChoiceId;
+ };
+ using OptionList = QList<Option>;
+
+ QDBusArgument &operator<<(QDBusArgument &arg, const Choice &choice);
+ const QDBusArgument &operator>>(const QDBusArgument &arg, Choice &choice);
+ QDBusArgument &operator<<(QDBusArgument &arg, const Option &option);
+ const QDBusArgument &operator>>(const QDBusArgument &arg, Option &option);
+
+ void registerChoiceMetaTypes();
+
+ QWidget *CreateChoiceControls(const OptionList &optionList, QMap<QString,
QCheckBox *> &checkboxes, QMap<QString, QComboBox *> &comboboxes);
+
+ QVariant EvaluateSelectedChoices(const QMap<QString, QCheckBox *>
&checkboxes, const QMap<QString, QComboBox *> &comboboxes);
+}
+
+Q_DECLARE_METATYPE(LXQt::Choice)
+Q_DECLARE_METATYPE(LXQt::Choices)
+Q_DECLARE_METATYPE(LXQt::Option)
+Q_DECLARE_METATYPE(LXQt::OptionList)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/desktopportal.cpp
new/xdg-desktop-portal-lxqt-1.4.0/src/desktopportal.cpp
--- old/xdg-desktop-portal-lxqt-1.3.0/src/desktopportal.cpp 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/desktopportal.cpp 2026-04-20
18:31:50.000000000 +0200
@@ -27,6 +27,7 @@
*
* END_COMMON_COPYRIGHT_HEADER */
+#include "access.h"
#include "desktopportal.h"
#include "filechooser.h"
@@ -34,6 +35,7 @@
{
DesktopPortal::DesktopPortal(QObject *parent)
: QObject(parent)
+ , m_access{new AccessPortal{this}}
, m_fileChooser{new FileChooserPortal{this}}
{
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/desktopportal.h
new/xdg-desktop-portal-lxqt-1.4.0/src/desktopportal.h
--- old/xdg-desktop-portal-lxqt-1.3.0/src/desktopportal.h 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/desktopportal.h 2026-04-20
18:31:50.000000000 +0200
@@ -34,6 +34,7 @@
namespace LXQt
{
+ class AccessPortal;
class FileChooserPortal;
class DesktopPortal : public QObject, public QDBusContext
@@ -43,6 +44,7 @@
explicit DesktopPortal(QObject *parent = nullptr);
private:
+ AccessPortal *m_access;
FileChooserPortal *m_fileChooser;
};
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/filechooser.cpp
new/xdg-desktop-portal-lxqt-1.4.0/src/filechooser.cpp
--- old/xdg-desktop-portal-lxqt-1.3.0/src/filechooser.cpp 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/filechooser.cpp 2026-04-20
18:31:50.000000000 +0200
@@ -27,6 +27,7 @@
*
* END_COMMON_COPYRIGHT_HEADER */
+#include "choices.h"
#include "filechooser.h"
#include "utils.h"
#include "filedialoghelper.h"
@@ -35,13 +36,10 @@
#include <QDBusMetaType>
#include <QDialogButtonBox>
#include <QFile>
-#include <QGridLayout>
-#include <QLabel>
+#include <QLayout>
#include <QLoggingCategory>
#include <QMimeDatabase>
#include <QUrl>
-#include <QCheckBox>
-#include <QComboBox>
#include <QDBusObjectPath>
#include <libfm-qt6/filedialog.h>
@@ -50,11 +48,6 @@
Q_DECLARE_METATYPE(LXQt::FileChooserPortal::Filters)
Q_DECLARE_METATYPE(LXQt::FileChooserPortal::FilterList)
Q_DECLARE_METATYPE(LXQt::FileChooserPortal::FilterListList)
-// used for options - choices
-Q_DECLARE_METATYPE(LXQt::FileChooserPortal::Choice)
-Q_DECLARE_METATYPE(LXQt::FileChooserPortal::Choices)
-Q_DECLARE_METATYPE(LXQt::FileChooserPortal::Option)
-Q_DECLARE_METATYPE(LXQt::FileChooserPortal::OptionList)
namespace LXQt
{
@@ -103,50 +96,6 @@
return arg;
}
- QDBusArgument &operator<<(QDBusArgument &arg, const
FileChooserPortal::Choice &choice)
- {
- arg.beginStructure();
- arg << choice.id << choice.value;
- arg.endStructure();
- return arg;
- }
-
- const QDBusArgument &operator>>(const QDBusArgument &arg,
FileChooserPortal::Choice &choice)
- {
- QString id;
- QString value;
- arg.beginStructure();
- arg >> id >> value;
- choice.id = id;
- choice.value = value;
- arg.endStructure();
- return arg;
- }
-
- QDBusArgument &operator<<(QDBusArgument &arg, const
FileChooserPortal::Option &option)
- {
- arg.beginStructure();
- arg << option.id << option.label << option.choices <<
option.initialChoiceId;
- arg.endStructure();
- return arg;
- }
-
- const QDBusArgument &operator>>(const QDBusArgument &arg,
FileChooserPortal::Option &option)
- {
- QString id;
- QString label;
- FileChooserPortal::Choices choices;
- QString initialChoiceId;
- arg.beginStructure();
- arg >> id >> label >> choices >> initialChoiceId;
- option.id = id;
- option.label = label;
- option.choices = choices;
- option.initialChoiceId = initialChoiceId;
- arg.endStructure();
- return arg;
- }
-
FileChooserPortal::FileChooserPortal(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
@@ -154,10 +103,7 @@
qDBusRegisterMetaType<Filters>();
qDBusRegisterMetaType<FilterList>();
qDBusRegisterMetaType<FilterListList>();
- qDBusRegisterMetaType<Choice>();
- qDBusRegisterMetaType<Choices>();
- qDBusRegisterMetaType<Option>();
- qDBusRegisterMetaType<OptionList>();
+ registerChoiceMetaTypes();
}
FileChooserPortal::~FileChooserPortal()
@@ -422,85 +368,12 @@
return 1;
}
- QWidget *FileChooserPortal::CreateChoiceControls(const
FileChooserPortal::OptionList &optionList,
- QMap<QString, QCheckBox *> &checkboxes,
- QMap<QString, QComboBox *> &comboboxes)
- {
- if (optionList.empty()) {
- return nullptr;
- }
-
- QWidget *optionsWidget = new QWidget;
- QGridLayout *layout = new QGridLayout(optionsWidget);
- // set stretch for (unused) column 2 so controls only take the space
they actually need
- layout->setColumnStretch(2, 1);
- optionsWidget->setLayout(layout);
-
- for (const Option &option : optionList) {
- const int nextRow = layout->rowCount();
- // empty list of choices -> boolean choice according to the spec
- if (option.choices.empty()) {
- QCheckBox *checkbox = new QCheckBox(option.label,
optionsWidget);
- checkbox->setChecked(option.initialChoiceId ==
QStringLiteral("true"));
- layout->addWidget(checkbox, nextRow, 1);
- checkboxes.insert(option.id, checkbox);
- } else {
- QComboBox *combobox = new QComboBox(optionsWidget);
- for (const Choice &choice : option.choices) {
- combobox->addItem(choice.value, choice.id);
- // select this entry if initialChoiceId matches
- if (choice.id == option.initialChoiceId) {
- combobox->setCurrentIndex(combobox->count() - 1);
- }
- }
- QString labelText = option.label;
- if (!labelText.endsWith(QChar::fromLatin1(':'))) {
- labelText += QChar::fromLatin1(':');
- }
- QLabel *label = new QLabel(labelText, optionsWidget);
- label->setBuddy(combobox);
- layout->addWidget(label, nextRow, 0, Qt::AlignRight);
- layout->addWidget(combobox, nextRow, 1);
- comboboxes.insert(option.id, combobox);
- }
- }
-
- return optionsWidget;
- }
-
- QVariant FileChooserPortal::EvaluateSelectedChoices(const QMap<QString,
QCheckBox *> &checkboxes, const QMap<QString, QComboBox *> &comboboxes)
- {
- Choices selectedChoices;
- const auto checkboxKeys = checkboxes.keys();
- for (const QString &id : checkboxKeys) {
- Choice choice;
- choice.id = id;
- choice.value = checkboxes.value(id)->isChecked() ?
QStringLiteral("true") : QStringLiteral("false");
- selectedChoices << choice;
- }
- const auto comboboxKeys = comboboxes.keys();
- for (const QString &id : comboboxKeys) {
- Choice choice;
- choice.id = id;
- choice.value = comboboxes.value(id)->currentData().toString();
- selectedChoices << choice;
- }
-
- return QVariant::fromValue<Choices>(selectedChoices);
- }
-
QString FileChooserPortal::ExtractAcceptLabel(const QVariantMap &options)
{
QString acceptLabel;
if (options.contains(QStringLiteral("accept_label"))) {
acceptLabel =
options.value(QStringLiteral("accept_label")).toString();
- // 'accept_label' allows mnemonic underlines, but Qt uses '&'
character, so replace/escape accordingly
- // to keep literal '&'s and transform mnemonic underlines to the
Qt equivalent using '&' for mnemonic
- acceptLabel.replace(QChar::fromLatin1('&'), QStringLiteral("&&"));
- const int mnemonic_pos =
acceptLabel.indexOf(QChar::fromLatin1('_'));
- if (mnemonic_pos != -1) {
- acceptLabel.replace(mnemonic_pos, 1, QChar::fromLatin1('&'));
- }
+ Utils::convertGtkMnemonic(acceptLabel);
}
return acceptLabel;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/filechooser.h
new/xdg-desktop-portal-lxqt-1.4.0/src/filechooser.h
--- old/xdg-desktop-portal-lxqt-1.3.0/src/filechooser.h 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/filechooser.h 2026-04-20
18:31:50.000000000 +0200
@@ -31,8 +31,6 @@
#include <QDBusAbstractAdaptor>
-class QCheckBox;
-class QComboBox;
class QDBusObjectPath;
namespace LXQt
@@ -55,20 +53,6 @@
};
using FilterListList = QList<FilterList>;
- struct Choice {
- QString id;
- QString value;
- };
- using Choices = QList<Choice>;
-
- struct Option {
- QString id;
- QString label;
- Choices choices;
- QString initialChoiceId;
- };
- using OptionList = QList<Option>;
-
explicit FileChooserPortal(QObject *parent);
~FileChooserPortal();
@@ -88,10 +72,6 @@
QVariantMap &results);
private:
- static QWidget *CreateChoiceControls(const OptionList &optionList,
QMap<QString, QCheckBox *> &checkboxes, QMap<QString, QComboBox *> &comboboxes);
-
- static QVariant EvaluateSelectedChoices(const QMap<QString, QCheckBox
*> &checkboxes, const QMap<QString, QComboBox *> &comboboxes);
-
static QString ExtractAcceptLabel(const QVariantMap &options);
static void ExtractFilters(const QVariantMap &options,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/utils.cpp
new/xdg-desktop-portal-lxqt-1.4.0/src/utils.cpp
--- old/xdg-desktop-portal-lxqt-1.3.0/src/utils.cpp 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/utils.cpp 2026-04-20
18:31:50.000000000 +0200
@@ -39,4 +39,21 @@
w->setAttribute(Qt::WA_NativeWindow, true);
KWindowSystem::setMainWindow(w->windowHandle(),
parent_window.mid(4).toULongLong(nullptr, 16));
}
+ if (parent_window.startsWith((QLatin1String("wayland:")))) {
+ if (!w->window()->windowHandle()) {
+ w->window()->winId(); // create QWindow
+ }
+ KWindowSystem::setMainWindow(w->window()->windowHandle(),
parent_window.mid(strlen("wayland:")));
+ }
+}
+
+void Utils::convertGtkMnemonic(QString &label)
+{
+ // Mnemonic underlines (GTK style) use '_', but Qt uses '&'. Escape
literal '&'s
+ // and transform the first mnemonic underline to the Qt equivalent.
+ label.replace(QChar::fromLatin1('&'), QStringLiteral("&&"));
+ const int mnemonicPos = label.indexOf(QChar::fromLatin1('_'));
+ if (mnemonicPos != -1) {
+ label.replace(mnemonicPos, 1, QChar::fromLatin1('&'));
+ }
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xdg-desktop-portal-lxqt-1.3.0/src/utils.h
new/xdg-desktop-portal-lxqt-1.4.0/src/utils.h
--- old/xdg-desktop-portal-lxqt-1.3.0/src/utils.h 2025-11-05
13:49:16.000000000 +0100
+++ new/xdg-desktop-portal-lxqt-1.4.0/src/utils.h 2026-04-20
18:31:50.000000000 +0200
@@ -35,5 +35,6 @@
{
public:
static void setParentWindow(QWidget *w, const QString &parent_window);
+ static void convertGtkMnemonic(QString &label);
};
++++++ xdg-desktop-portal-lxqt.keyring ++++++
--- /var/tmp/diff_new_pack.mhKD1S/_old 2026-04-22 16:58:20.780897330 +0200
+++ /var/tmp/diff_new_pack.mhKD1S/_new 2026-04-22 16:58:20.788897661 +0200
@@ -47,7 +47,43 @@
Oa86l8pqli+B7rpTbsAE9Ut8qUaWjm87oUNSJbaKgqNnMaE+b/8VJaEeWHgQJwsD
bJSJ/O/vzlRtDjOJ1JDlMRLs7TnOFeUh5pgwyaJoidYbJEiGlMGJbI6BjwhDTBFO
NLJtd3SsRjc7ICtGdCvej59IvCDTjxtkhx5okF03APi1aXpHQrE18/arFD7BpoGO
-sw==
-=gSIv
+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
+/AltqE7gRNR/QnfiBlo=
+=kOsM
-----END PGP PUBLIC KEY BLOCK-----