├── .git-blame-ignore-revs ├── Messages.sh ├── data ├── org.freedesktop.impl.portal.desktop.kde.cmake.in ├── plasma-xdg-desktop-portal-kde.service.in ├── org.kde.KIOFuse.VFS.xml ├── org.freedesktop.portal.Documents.xml ├── CMakeLists.txt ├── kde.portal ├── org.freedesktop.Application.xml ├── org.freedesktop.impl.portal.desktop.kde.desktop.in └── org.freedesktop.Accounts.User.xml ├── src ├── region-select │ ├── FloatingBackground.qml │ ├── FloatingTextBox.qml │ └── SelectionEditor.h ├── kirigami-filepicker │ ├── declarative │ │ ├── filepicker.qrc │ │ ├── fileplacesmodel.h │ │ ├── dirmodelutils.h │ │ ├── CreateDirectorySheet.qml │ │ ├── fileplacesmodel.cpp │ │ ├── dirmodelutils.cpp │ │ ├── PlacesGlobalDrawer.qml │ │ ├── FilePickerWindow.qml │ │ ├── dirmodel.h │ │ ├── filechooserqmlcallback.h │ │ └── filechooserqmlcallback.cpp │ ├── CMakeLists.txt │ └── api │ │ └── mobilefiledialog.h ├── ScreenChooserDialogTemplate.qml ├── xdgshortcut.h ├── inputcapturebarrier.h ├── inputcapturedialog.h ├── inputcapturedialog.cpp ├── portalicon.h ├── restoredata.h ├── portalicon.cpp ├── notificationinhibition.h ├── utils.h ├── org.kde.KWin.TabletModeManager.xml ├── dynamiclauncherdialog.h ├── quickdialog.h ├── InputCaptureDialog.qml ├── userinfodialog.h ├── dynamiclauncherdialog.cpp ├── email.h ├── notification.h ├── accessdialog.h ├── account.h ├── org.kde.KWin.VirtualKeyboard.xml ├── screenshotdialog.h ├── usb.h ├── access.h ├── wallpaper.h ├── screenchooserdialog.h ├── RemoteDesktopDialog.qml ├── remotedesktopdialog.h ├── restoredata.cpp ├── dynamiclauncher.h ├── screenshot.h ├── dbushelpers.cpp ├── request.h ├── desktopportal.h ├── clipboard.h ├── appchooser.h ├── settings.h ├── session.cpp ├── quickdialog.cpp ├── desktopportal.cpp ├── background.h ├── WallpaperDialog.qml ├── session.h ├── accessdialog.cpp ├── org.freedesktop.impl.portal.Session.xml ├── inhibit.h ├── screencasting.h ├── UserInfoDialog.qml ├── account.cpp ├── utils.cpp ├── request.cpp ├── email.cpp ├── inputcapturebarrier.cpp ├── AccessDialog.qml ├── xdg-desktop-portal-kde.cpp ├── print.h ├── notificationinhibition.cpp ├── ScreenshotDialog.qml ├── PipeWireLayout.qml ├── dbushelpers.h ├── xdgshortcut.cpp ├── waylandintegration.h ├── outputsmodel.h ├── ScreenChooserDialog.qml ├── access.cpp ├── filechooser.h ├── userinfodialog.cpp ├── waylandintegration_p.h ├── remotedesktopdialog.cpp ├── DynamicLauncherDialog.qml ├── globalshortcuts.h ├── UsbDialog.qml ├── usb.cpp ├── PipeWireDelegate.qml ├── wallpaper.cpp ├── screencast.h ├── remotedesktop.h └── inputcapture.h ├── .gitlab-ci.yml ├── .gitignore ├── README.md ├── autotests ├── CMakeLists.txt ├── xdgshortcuttest.cpp └── colorschemetest.py ├── LICENSES ├── LicenseRef-KDE-Accepted-LGPL.txt ├── MIT.txt └── BSD-2-Clause.txt ├── cmake └── FindKIOFuse.cmake ├── TODO ├── .kde-ci.yml └── CMakeLists.txt /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # clang-format 2 | 79184c06c27a417e269dbe4ab82add8edf24a5d8 3 | 9fec0c4b5f0b1b36ceab211a3b2d27fd4a2114f9 4 | 369328311ec82f9c4cca5a6ca67cee2ecc5cdca8 5 | -------------------------------------------------------------------------------- /Messages.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | $EXTRACTRC `find . -name "*.ui" -o -name "*.rc"` >> rc.cpp 3 | $XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/xdg-desktop-portal-kde.pot 4 | rm -f rc.cpp 5 | -------------------------------------------------------------------------------- /data/org.freedesktop.impl.portal.desktop.kde.cmake.in: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=org.freedesktop.impl.portal.desktop.kde 3 | Exec=@CMAKE_INSTALL_FULL_LIBEXECDIR@/xdg-desktop-portal-kde 4 | SystemdService=plasma-xdg-desktop-portal-kde.service 5 | -------------------------------------------------------------------------------- /src/region-select/FloatingBackground.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2 | import org.kde.kirigami as Kirigami 3 | 4 | Kirigami.ShadowedRectangle { 5 | radius: Kirigami.Units.mediumSpacing / 2 6 | shadow.color: Qt.rgba(0,0,0,0.2) 7 | shadow.size: 9 8 | shadow.yOffset: 2 9 | } 10 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/filepicker.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | PlacesGlobalDrawer.qml 4 | FilePickerWindow.qml 5 | FilePicker.qml 6 | CreateDirectorySheet.qml 7 | 8 | 9 | -------------------------------------------------------------------------------- /data/plasma-xdg-desktop-portal-kde.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Xdg Desktop Portal For KDE 3 | PartOf=graphical-session.target 4 | After=plasma-core.target 5 | 6 | [Service] 7 | ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/xdg-desktop-portal-kde 8 | BusName=org.freedesktop.impl.portal.desktop.kde 9 | Slice=session.slice 10 | # Auto restart is off as we are DBus activated 11 | Restart=no 12 | -------------------------------------------------------------------------------- /src/ScreenChooserDialogTemplate.qml: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.0-or-later 2 | // SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | // SPDX-FileCopyrightText: 2025 Harald Sitter 4 | 5 | pragma ComponentBehavior: Bound 6 | 7 | import QtQuick 8 | 9 | PortalDialog { 10 | property bool multiple: false 11 | 12 | signal clearSelection() 13 | } 14 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | include: 5 | - project: sysadmin/ci-utilities 6 | file: 7 | - /gitlab-templates/xml-lint.yml 8 | - /gitlab-templates/yaml-lint.yml 9 | - /gitlab-templates/qml-lint.yml 10 | - /gitlab-templates/linux-qt6.yml 11 | - /gitlab-templates/freebsd-qt6.yml 12 | - /gitlab-templates/linux-qt6-next.yml 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the following files 2 | *~ 3 | *.[oa] 4 | *.diff 5 | *.kate-swp 6 | *.kdev4 7 | .kdev_include_paths 8 | *.kdevelop.pcs 9 | *.moc 10 | *.moc.cpp 11 | *.orig 12 | *.user 13 | .*.swp 14 | .swp.* 15 | Doxyfile 16 | Makefile 17 | avail 18 | random_seed 19 | /build*/ 20 | CMakeLists.txt.user* 21 | *.unc-backup* 22 | .clang-format 23 | /build*/ 24 | /compile_commands.json 25 | .clangd 26 | .idea 27 | /cmake-build* 28 | .cache 29 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/fileplacesmodel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 Linus Jahn 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class FilePlacesModel : public KFilePlacesModel 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | FilePlacesModel(QObject *parent = nullptr); 15 | 16 | QHash roleNames() const override; 17 | }; 18 | -------------------------------------------------------------------------------- /src/xdgshortcut.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Aleix Pol i Gonzalez 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /** 14 | * Specifies a shortcut as defined in the xdg-specs: 15 | * 16 | * https://gitlab.freedesktop.org/xdg/xdg-specs/-/tree/master/shortcuts 17 | */ 18 | 19 | namespace XdgShortcut 20 | { 21 | std::optional parse(const QString &shortcutString); 22 | } 23 | -------------------------------------------------------------------------------- /src/inputcapturebarrier.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | enum class BarrierFailureReason { 15 | Diagonal, 16 | NotOnEdge, 17 | BetweenScreensOrDoesNotFill, 18 | }; 19 | 20 | std::variant> checkAndMakeBarrier(int x1, int y1, int x2, int y2, const QList &screenGeometries); 21 | -------------------------------------------------------------------------------- /src/inputcapturedialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | #ifndef XDG_DESKTOP_PORTAL_KDE_INPUTCAPTURE_DIALOG_H 7 | #define XDG_DESKTOP_PORTAL_KDE_INPUTCAPTURE_DIALOG_H 8 | 9 | #include "inputcapture.h" 10 | #include "quickdialog.h" 11 | 12 | class InputCaptureDialog : public QuickDialog 13 | { 14 | Q_OBJECT 15 | public: 16 | InputCaptureDialog(const QString &appId, InputCapturePortal::Capabilities capabilties, QObject *parent = nullptr); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/inputcapturedialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | #include "inputcapturedialog.h" 7 | 8 | #include "utils.h" 9 | 10 | using namespace Qt::StringLiterals; 11 | 12 | InputCaptureDialog::InputCaptureDialog(const QString &appId, InputCapturePortal::Capabilities capabilties, QObject *parent) 13 | : QuickDialog(parent) 14 | { 15 | create(u"InputCaptureDialog"_s, {{u"app"_s, Utils::applicationName(appId)}}); 16 | } 17 | 18 | #include "moc_inputcapturedialog.cpp" 19 | -------------------------------------------------------------------------------- /data/org.kde.KIOFuse.VFS.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/region-select/FloatingTextBox.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2 | import org.kde.kirigami as Kirigami 3 | 4 | Kirigami.Padding { 5 | // Reusable/shared object 6 | required property FontMetrics fontMetrics 7 | 8 | padding: Kirigami.Units.mediumSpacing * 2 9 | verticalPadding: padding - fontMetrics.descent 10 | 11 | FloatingBackground { 12 | anchors.fill: parent 13 | z: -1 14 | 15 | radius: Kirigami.Units.mediumSpacing / 2 + border.width 16 | 17 | color: Qt.alpha(Kirigami.Theme.backgroundColor, 0.85) 18 | border.color: Qt.alpha(Kirigami.Theme.textColor, 0.2) 19 | border.width: 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xdg-desktop-portal-kde 2 | 3 | A backend implementation for [xdg-desktop-portal](http://github.com/flatpak/xdg-desktop-portal) 4 | that is using Qt/KF5. 5 | 6 | ## Building xdg-desktop-portal-kde 7 | 8 | ### Dependencies: 9 | - xdg-desktop-portal (runtime dependency) 10 | - Qt 5 (build dependency) 11 | - KDE Frameworks - KCoreAddons, KI18n, KNotifications(build dependency) 12 | 13 | ### Build instructions: 14 | ``` 15 | $ mkdir build && cd build 16 | $ cmake .. [your_options] 17 | $ make -j5 18 | $ make install 19 | ``` 20 | 21 | ## Testing xdg-desktop-portal-kde 22 | 23 | The repository [xdg-portal-test-kde](https://invent.kde.org/libraries/xdg-portal-test-kde) contains a simple test application. 24 | -------------------------------------------------------------------------------- /autotests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ecm_add_tests( 2 | xdgshortcuttest.cpp 3 | 4 | LINK_LIBRARIES Qt::Test Qt::Gui 5 | ) 6 | target_sources(xdgshortcuttest PRIVATE ${CMAKE_SOURCE_DIR}/src/xdgshortcut.cpp ${CMAKE_SOURCE_DIR}/src/xdgshortcut.h) 7 | target_link_libraries(xdgshortcuttest Qt::GuiPrivate) 8 | 9 | add_test( 10 | NAME colorschemetest 11 | COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/colorschemetest.py 12 | ) 13 | set_tests_properties(colorschemetest PROPERTIES ENVIRONMENT "CMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") 14 | 15 | ecm_add_test(inputcapturebarriertest.cpp ${CMAKE_SOURCE_DIR}/src/inputcapturebarrier.cpp TEST_NAME inputcapturebarriertest LINK_LIBRARIES Qt::Test Qt::Gui) 16 | -------------------------------------------------------------------------------- /data/org.freedesktop.portal.Documents.xml: -------------------------------------------------------------------------------- 1 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/portalicon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | struct PortalIcon { 15 | QString str; 16 | QDBusVariant data; 17 | 18 | static auto registerDBusType() 19 | { 20 | return qDBusRegisterMetaType(); 21 | } 22 | }; 23 | 24 | QDBusArgument &operator<<(QDBusArgument &argument, const PortalIcon &icon); 25 | const QDBusArgument &operator>>(const QDBusArgument &argument, PortalIcon &icon); 26 | 27 | Q_DECLARE_METATYPE(PortalIcon) 28 | -------------------------------------------------------------------------------- /src/restoredata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: LGPL-2.0-or-later 3 | * 4 | * SPDX-FileCopyrightText: 2022 Aleix Pol 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct RestoreData { 12 | static uint currentRestoreDataVersion() 13 | { 14 | return 1; 15 | } 16 | 17 | QString session; 18 | quint32 version = 0; 19 | QVariantMap payload; 20 | }; 21 | 22 | const QDBusArgument &operator<<(QDBusArgument &arg, const RestoreData &data); 23 | const QDBusArgument &operator>>(const QDBusArgument &arg, RestoreData &data); 24 | QDebug operator<<(QDebug dbg, const RestoreData &c); 25 | 26 | Q_DECLARE_METATYPE(RestoreData) 27 | -------------------------------------------------------------------------------- /src/portalicon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #include "portalicon.h" 10 | 11 | QDBusArgument &operator<<(QDBusArgument &argument, const PortalIcon &icon) 12 | { 13 | argument.beginStructure(); 14 | argument << icon.str << icon.data; 15 | argument.endStructure(); 16 | return argument; 17 | } 18 | 19 | const QDBusArgument &operator>>(const QDBusArgument &argument, PortalIcon &icon) 20 | { 21 | argument.beginStructure(); 22 | argument >> icon.str >> icon.data; 23 | argument.endStructure(); 24 | return argument; 25 | } 26 | -------------------------------------------------------------------------------- /src/notificationinhibition.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Kai Uwe Broulik 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #ifndef XDG_DESKTOP_PORTAL_KDE_NOTIFICATIONINHIBITION_H 8 | #define XDG_DESKTOP_PORTAL_KDE_NOTIFICATIONINHIBITION_H 9 | 10 | #include 11 | 12 | class NotificationInhibition : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit NotificationInhibition(const QString &appId, const QString &reason, QObject *parent = nullptr); 17 | ~NotificationInhibition() override; 18 | 19 | private: 20 | static void uninhibit(uint cookie); 21 | uint m_cookie = 0; 22 | }; 23 | 24 | #endif // XDG_DESKTOP_PORTAL_KDE_NOTIFICATIONINHIBITION_H 25 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Alexander Volkov 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #ifndef XDG_DESKTOP_PORTAL_KDE_UTILS_H 8 | #define XDG_DESKTOP_PORTAL_KDE_UTILS_H 9 | 10 | class QString; 11 | class QWidget; 12 | class QWindow; 13 | 14 | enum class DialogResult : unsigned { 15 | Accepted = 0, 16 | Rejected = 1 17 | }; 18 | 19 | class Utils 20 | { 21 | public: 22 | static void setParentWindow(QWidget *w, const QString &parent_window); 23 | static void setParentWindow(QWindow *w, const QString &parent_window); 24 | 25 | static QString applicationName(const QString &appId); 26 | }; 27 | 28 | #endif // XDG_DESKTOP_PORTAL_KDE_UTILS_H 29 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-KDE-Accepted-LGPL.txt: -------------------------------------------------------------------------------- 1 | This library is free software; you can redistribute it and/or 2 | modify it under the terms of the GNU Lesser General Public 3 | License as published by the Free Software Foundation; either 4 | version 3 of the license or (at your option) any later version 5 | that is accepted by the membership of KDE e.V. (or its successor 6 | approved by the membership of KDE e.V.), which shall act as a 7 | proxy as defined in Section 6 of version 3 of the license. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | -------------------------------------------------------------------------------- /src/org.kde.KWin.TabletModeManager.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | configure_file(org.freedesktop.impl.portal.desktop.kde.desktop.in org.freedesktop.impl.portal.desktop.kde.desktop @ONLY) 2 | configure_file(org.freedesktop.impl.portal.desktop.kde.cmake.in org.freedesktop.impl.portal.desktop.kde.service @ONLY) 3 | 4 | install(FILES kde.portal DESTINATION ${KDE_INSTALL_DATADIR}/xdg-desktop-portal/portals) 5 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.impl.portal.desktop.kde.service DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR}) 6 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.impl.portal.desktop.kde.desktop DESTINATION ${KDE_INSTALL_APPDIR}) 7 | 8 | ecm_install_configured_files(INPUT plasma-xdg-desktop-portal-kde.service.in @ONLY 9 | DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) 10 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/dirmodelutils.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 Linus Jahn 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class DirModelUtils : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit DirModelUtils(QObject *parent = nullptr); 15 | 16 | Q_INVOKABLE QStringList getUrlParts(const QUrl &url) const; 17 | Q_INVOKABLE QUrl partialUrlForIndex(QUrl url, int index) const; 18 | Q_INVOKABLE QUrl directoryOfUrl(const QString &path) const; 19 | Q_INVOKABLE QString fileNameOfUrl(const QString &path) const; 20 | 21 | Q_INVOKABLE void mkdir(const QUrl path) const; 22 | 23 | Q_SIGNALS: 24 | void homePathChanged(); 25 | }; 26 | -------------------------------------------------------------------------------- /src/dynamiclauncherdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 2 | // SPDX-FileCopyrightText: 2022 Harald Sitter 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include "quickdialog.h" 9 | 10 | class DynamicLauncherDialog : public QuickDialog 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit DynamicLauncherDialog(const QString &title, const QIcon &icon, const QString &name, const QUrl &launcherURL, QObject *parent = nullptr); 15 | 16 | Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged) 17 | Q_SIGNAL void nameChanged(); 18 | QString m_name; 19 | 20 | Q_PROPERTY(QVariant icon MEMBER m_icon NOTIFY iconChanged) 21 | Q_SIGNAL void iconChanged(); 22 | QVariant m_icon; 23 | }; 24 | -------------------------------------------------------------------------------- /data/kde.portal: -------------------------------------------------------------------------------- 1 | [portal] 2 | DBusName=org.freedesktop.impl.portal.desktop.kde 3 | Interfaces=org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.Account;org.freedesktop.impl.portal.AppChooser;org.freedesktop.impl.portal.Background;org.freedesktop.impl.portal.Email;org.freedesktop.impl.portal.FileChooser;org.freedesktop.impl.portal.Inhibit;org.freedesktop.impl.portal.Notification;org.freedesktop.impl.portal.Print;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.RemoteDesktop;org.freedesktop.impl.portal.Settings;org.freedesktop.impl.portal.DynamicLauncher;org.freedesktop.impl.portal.GlobalShortcuts;org.freedesktop.impl.portal.InputCapture;org.freedesktop.impl.portal.Clipboard;org.freedesktop.impl.portal.Wallpaper;org.freedesktop.impl.portal.Usb 4 | UseIn=KDE 5 | -------------------------------------------------------------------------------- /cmake/FindKIOFuse.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-2-Clause 2 | # SPDX-FileCopyrightText: 2022 Harald Sitter 3 | 4 | execute_process( 5 | COMMAND dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames 6 | OUTPUT_VARIABLE _kiofuseOut) 7 | 8 | set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) 9 | if("${_kiofuseOut}" MATCHES "\"org.kde.KIOFuse\"") 10 | set(${CMAKE_FIND_PACKAGE_NAME}_FOUND TRUE) 11 | endif() 12 | 13 | include(FindPackageHandleStandardArgs) 14 | find_package_handle_standard_args(${CMAKE_FIND_PACKAGE_NAME} 15 | FOUND_VAR ${CMAKE_FIND_PACKAGE_NAME}_FOUND 16 | REQUIRED_VARS ${CMAKE_FIND_PACKAGE_NAME}_FOUND 17 | REASON_FAILURE_MESSAGE "Could not find DBus service org.kde.KIOFuse in org.freedesktop.DBus.ListActivatableNames" 18 | ) 19 | -------------------------------------------------------------------------------- /data/org.freedesktop.Application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/CreateDirectorySheet.qml: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 Jonah Brüchert 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | import QtQuick 6 | import QtQuick.Layouts 7 | import QtQuick.Controls as QQC2 8 | 9 | import org.kde.kirigami as Kirigami 10 | import org.kde.kirigamifilepicker 11 | 12 | Kirigami.PromptDialog { 13 | id: sheet 14 | 15 | property string parentPath 16 | 17 | title: i18n("Create New Folder") 18 | 19 | standardButtons: QQC2.Dialog.Ok | QQC2.Dialog.Cancel 20 | 21 | onAccepted: { 22 | DirModelUtils.mkdir(parentPath + "/" + nameField.text); 23 | sheet.close(); 24 | } 25 | onRejected: { 26 | nameField.clear(); 27 | sheet.close(); 28 | } 29 | 30 | QQC2.TextField { 31 | id: nameField 32 | placeholderText: i18n("Folder name") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/quickdialog.h: -------------------------------------------------------------------------------- 1 | /* This file is part of the KDE project 2 | SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | 4 | SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "utils.h" 10 | 11 | #include 12 | #include 13 | 14 | class QWindow; 15 | 16 | class QuickDialog : public QObject 17 | { 18 | Q_OBJECT 19 | public: 20 | QuickDialog(QObject *parent = nullptr); 21 | ~QuickDialog() override; 22 | 23 | QWindow *windowHandle() const 24 | { 25 | return m_theDialog; 26 | } 27 | 28 | void create(const QString &componentName, const QVariantMap &props); 29 | 30 | public Q_SLOTS: 31 | void reject(); 32 | virtual void accept(); 33 | 34 | Q_SIGNALS: 35 | void finished(DialogResult result); 36 | void accepted(); 37 | void rejected(); 38 | 39 | protected: 40 | QWindow *m_theDialog = nullptr; 41 | }; 42 | -------------------------------------------------------------------------------- /src/InputCaptureDialog.qml: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | 7 | import QtQuick 8 | import QtQuick.Controls as QQC2 9 | 10 | PortalDialog { 11 | 12 | readonly property string app: "" 13 | 14 | iconName: "dialog-input-devices" 15 | title: i18nc("@title:window", "Input Capture Requested") 16 | subtitle: app === "" ? i18nc("The application is unknown", "An application requested to capture input events") : i18nc("%1 is the name of the application", "%1 requested to capture input events", app) 17 | 18 | width: contentWidth 19 | height: contentHeight 20 | 21 | standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 22 | 23 | Component.onCompleted: dialogButtonBox.standardButton(QQC2.DialogButtonBox.Ok).text = i18nc("@action:button", "Allow") 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/userinfodialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2020 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_USERINFO_DIALOG_H 10 | #define XDG_DESKTOP_PORTAL_KDE_USERINFO_DIALOG_H 11 | 12 | #include "quickdialog.h" 13 | 14 | class OrgFreedesktopAccountsUserInterface; 15 | struct UserDetails; 16 | 17 | class UserInfoDialog : public QuickDialog 18 | { 19 | Q_OBJECT 20 | public: 21 | explicit UserInfoDialog(const QString &reason, const QString &app_id, QObject *parent = nullptr); 22 | ~UserInfoDialog() override; 23 | Q_DISABLE_COPY_MOVE(UserInfoDialog) 24 | 25 | [[nodiscard]] QString id() const; 26 | [[nodiscard]] QString name() const; 27 | [[nodiscard]] QString image() const; 28 | 29 | private: 30 | std::unique_ptr m_userDetails; 31 | }; 32 | 33 | #endif // XDG_DESKTOP_PORTAL_KDE_USERINFO_DIALOG_H 34 | -------------------------------------------------------------------------------- /src/dynamiclauncherdialog.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 2 | // SPDX-FileCopyrightText: 2022 Harald Sitter 3 | 4 | #include "dynamiclauncherdialog.h" 5 | 6 | #include 7 | 8 | #include "dynamiclauncherdialog_debug.h" 9 | 10 | DynamicLauncherDialog::DynamicLauncherDialog(const QString &title, const QIcon &icon, const QString &name, const QUrl &launcherURL, QObject *parent) 11 | : QuickDialog(parent) 12 | , m_name(name) 13 | , m_icon(icon) 14 | { 15 | create(QStringLiteral("DynamicLauncherDialog"), 16 | { 17 | {QStringLiteral("title"), title}, 18 | {QStringLiteral("launcherName"), name}, 19 | {QStringLiteral("launcherIcon"), icon}, 20 | {QStringLiteral("launcherURL"), launcherURL}, 21 | {QStringLiteral("dialog"), QVariant::fromValue(this)}, 22 | }); 23 | } 24 | 25 | #include "moc_dynamiclauncherdialog.cpp" 26 | -------------------------------------------------------------------------------- /src/email.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_EMAIL_H 10 | #define XDG_DESKTOP_PORTAL_KDE_EMAIL_H 11 | 12 | #include 13 | #include 14 | 15 | class QDBusMessage; 16 | 17 | class EmailPortal : public QDBusAbstractAdaptor 18 | { 19 | Q_OBJECT 20 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Email") 21 | public: 22 | explicit EmailPortal(QObject *parent); 23 | 24 | public Q_SLOTS: 25 | void ComposeEmail(const QDBusObjectPath &handle, 26 | const QString &app_id, 27 | const QString &window, 28 | const QVariantMap &options, 29 | const QDBusMessage &message, 30 | uint &replyResponse, 31 | QVariantMap &replyResults); 32 | }; 33 | 34 | #endif // XDG_DESKTOP_PORTAL_KDE_EMAIL_H 35 | -------------------------------------------------------------------------------- /src/notification.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H 10 | #define XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | class NotificationPortal : public QDBusAbstractAdaptor 18 | { 19 | Q_OBJECT 20 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Notification") 21 | public: 22 | explicit NotificationPortal(QObject *parent); 23 | 24 | public Q_SLOTS: 25 | void AddNotification(const QString &app_id, const QString &id, const QVariantMap ¬ification); 26 | void RemoveNotification(const QString &app_id, const QString &id); 27 | private Q_SLOTS: 28 | void notificationClosed(); 29 | 30 | private: 31 | QHash> m_notifications; 32 | }; 33 | 34 | #endif // XDG_DESKTOP_PORTAL_KDE_NOTIFICATION_H 35 | -------------------------------------------------------------------------------- /src/accessdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_ACCESS_DIALOG_H 10 | #define XDG_DESKTOP_PORTAL_KDE_ACCESS_DIALOG_H 11 | 12 | #include "dbushelpers.h" 13 | #include "quickdialog.h" 14 | #include 15 | 16 | class AccessDialog : public QuickDialog 17 | { 18 | Q_OBJECT 19 | public: 20 | explicit AccessDialog(QObject *parent = nullptr); 21 | 22 | void setAcceptLabel(const QString &label); 23 | void setBody(const QString &body); 24 | void setIcon(const QString &icon); 25 | void setRejectLabel(const QString &label); 26 | void setTitle(const QString &title); 27 | void setSubtitle(const QString &subtitle); 28 | void setChoices(const OptionList &choices); 29 | 30 | Choices selectedChoices() const; 31 | 32 | void createDialog(); 33 | 34 | private: 35 | QVariantMap m_props; 36 | }; 37 | 38 | #endif // XDG_DESKTOP_PORTAL_KDE_ACCESS_DIALOG_H 39 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(filepicker_lib_SRCS 2 | api/mobilefiledialog.cpp 3 | api/mobilefiledialog.h 4 | declarative/dirmodel.cpp 5 | declarative/dirmodel.h 6 | declarative/dirmodelutils.cpp 7 | declarative/dirmodelutils.h 8 | declarative/filechooserqmlcallback.cpp 9 | declarative/filechooserqmlcallback.h 10 | declarative/fileplacesmodel.cpp 11 | declarative/fileplacesmodel.h 12 | declarative/filepicker.qrc 13 | ) 14 | 15 | ecm_qt_declare_logging_category(filepicker_lib_SRCS 16 | IDENTIFIER "KirigamiFilepicker" 17 | CATEGORY_NAME "xdp-kde-file-chooser" 18 | HEADER mobilefiledialog_debug.h) 19 | 20 | add_library(KirigamiFilepicker STATIC ${filepicker_lib_SRCS}) 21 | set_property(TARGET KirigamiFilepicker PROPERTY POSITION_INDEPENDENT_CODE ON) 22 | target_include_directories(KirigamiFilepicker PRIVATE declarative) 23 | target_link_libraries(KirigamiFilepicker 24 | Qt::Quick 25 | Qt::Qml 26 | KF6::I18n 27 | KF6::KIOCore 28 | KF6::KIOFileWidgets 29 | ) 30 | target_include_directories(KirigamiFilepicker PUBLIC api) 31 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /src/account.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2020 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_ACCOUNT_H 10 | #define XDG_DESKTOP_PORTAL_KDE_ACCOUNT_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | class AccountPortal : public QDBusAbstractAdaptor 17 | { 18 | Q_OBJECT 19 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Account") 20 | public: 21 | explicit AccountPortal(QObject *parent); 22 | 23 | public Q_SLOTS: 24 | void GetUserInformation(const QDBusObjectPath &handle, // 25 | const QString &app_id, 26 | const QString &parent_window, 27 | const QVariantMap &options, 28 | const QDBusMessage &message, 29 | uint &replyResponse, 30 | QVariantMap &replyResults); 31 | }; 32 | 33 | #endif // XDG_DESKTOP_PORTAL_KDE_ACCOUNT_H 34 | -------------------------------------------------------------------------------- /src/org.kde.KWin.VirtualKeyboard.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/fileplacesmodel.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 Linus Jahn 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | #include "fileplacesmodel.h" 6 | 7 | FilePlacesModel::FilePlacesModel(QObject *parent) 8 | : KFilePlacesModel(parent) 9 | { 10 | } 11 | 12 | QHash FilePlacesModel::roleNames() const 13 | { 14 | return { 15 | {Qt::DisplayRole, QByteArrayLiteral("displayRole")}, 16 | {KFilePlacesModel::UrlRole, QByteArrayLiteral("url")}, 17 | {KFilePlacesModel::HiddenRole, QByteArrayLiteral("hidden")}, 18 | {KFilePlacesModel::SetupNeededRole, QByteArrayLiteral("setupNeeded")}, 19 | {KFilePlacesModel::FixedDeviceRole, QByteArrayLiteral("fixedDevice")}, 20 | {KFilePlacesModel::CapacityBarRecommendedRole, QByteArrayLiteral("capacityBarRecommended")}, 21 | {KFilePlacesModel::GroupRole, QByteArrayLiteral("group")}, 22 | {KFilePlacesModel::IconNameRole, QByteArrayLiteral("iconName")}, 23 | {KFilePlacesModel::GroupHiddenRole, QByteArrayLiteral("groupHidden")}, 24 | }; 25 | } 26 | 27 | #include "moc_fileplacesmodel.cpp" 28 | -------------------------------------------------------------------------------- /src/screenshotdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_DIALOG_H 10 | #define XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_DIALOG_H 11 | 12 | #include "quickdialog.h" 13 | #include 14 | #include 15 | 16 | class ScreenshotDialog : public QuickDialog 17 | { 18 | Q_OBJECT 19 | public: 20 | explicit ScreenshotDialog(QObject *parent = nullptr); 21 | 22 | enum Flags { 23 | Borders = 1, 24 | Cursor = 1 << 1, 25 | }; 26 | Q_ENUM(Flags) 27 | enum ScreenshotType { 28 | FullScreen, 29 | CurrentScreen, 30 | ActiveWindow, 31 | }; 32 | Q_ENUM(ScreenshotType) 33 | 34 | QImage image() const; 35 | void takeScreenshotNonInteractive(); 36 | 37 | public Q_SLOTS: 38 | void takeScreenshotInteractive(); 39 | 40 | Q_SIGNALS: 41 | void failed(); 42 | 43 | private: 44 | QFuture takeScreenshot(); 45 | 46 | QImage m_image; 47 | }; 48 | 49 | #endif // XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_DIALOG_H 50 | -------------------------------------------------------------------------------- /src/usb.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2025 David Redondo 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | class QDBusMessage; 14 | 15 | class UsbPortal : public QDBusAbstractAdaptor 16 | { 17 | Q_OBJECT 18 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Usb") 19 | Q_PROPERTY(uint version READ version CONSTANT) 20 | public: 21 | explicit UsbPortal(QObject *parent); 22 | 23 | static constexpr uint version() 24 | { 25 | return 1; 26 | } 27 | public Q_SLOTS: 28 | void AcquireDevices(const QDBusObjectPath &handle, 29 | const QString &parent_window, 30 | const QString &app_id, 31 | const QList> &devices, 32 | const QVariantMap &options, 33 | const QDBusMessage &message, 34 | uint &replyResponse, 35 | QVariantMap &replyResults); 36 | }; 37 | -------------------------------------------------------------------------------- /src/access.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_ACCESS_H 10 | #define XDG_DESKTOP_PORTAL_KDE_ACCESS_H 11 | 12 | #include 13 | #include 14 | 15 | class QDBusMessage; 16 | 17 | class AccessPortal : public QDBusAbstractAdaptor 18 | { 19 | Q_OBJECT 20 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Access") 21 | public: 22 | explicit AccessPortal(QObject *parent); 23 | 24 | public Q_SLOTS: 25 | void AccessDialog(const QDBusObjectPath &handle, 26 | const QString &app_id, 27 | const QString &parent_window, 28 | const QString &title, 29 | const QString &subtitle, 30 | const QString &body, 31 | const QVariantMap &options, 32 | const QDBusMessage &message, 33 | uint &replyResponse, 34 | QVariantMap &replyResults); 35 | }; 36 | 37 | #endif // XDG_DESKTOP_PORTAL_KDE_ACCESS_H 38 | -------------------------------------------------------------------------------- /src/wallpaper.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 2 | // SPDX-FileCopyrightText: 2025 David Redondo 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class QDBusMessage; 11 | 12 | namespace WallpaperLocation 13 | { 14 | Q_NAMESPACE 15 | QML_ELEMENT 16 | enum Location { 17 | Desktop, 18 | Lockscreen, 19 | Both 20 | }; 21 | Q_ENUM_NS(Location) 22 | } 23 | 24 | class WallpaperPortal : public QDBusAbstractAdaptor 25 | { 26 | Q_OBJECT 27 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Wallpaper") 28 | public: 29 | explicit WallpaperPortal(QObject *parent = nullptr) 30 | : QDBusAbstractAdaptor(parent) 31 | { 32 | } 33 | public Q_SLOTS: 34 | void SetWallpaperURI(const QDBusObjectPath &handle, 35 | const QString &app_id, 36 | const QString &parent_window, 37 | const QString &uri, 38 | const QVariantMap &options, 39 | const QDBusMessage &message, 40 | uint &replyResponse); 41 | }; 42 | -------------------------------------------------------------------------------- /LICENSES/BSD-2-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /src/screenchooserdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_SCREENCHOOSER_DIALOG_H 10 | #define XDG_DESKTOP_PORTAL_KDE_SCREENCHOOSER_DIALOG_H 11 | 12 | #include "outputsmodel.h" 13 | #include "quickdialog.h" 14 | #include "screencast.h" 15 | #include 16 | #include 17 | 18 | namespace KWayland 19 | { 20 | namespace Client 21 | { 22 | class PlasmaWindow; 23 | } 24 | } 25 | 26 | class ScreenChooserDialog : public QuickDialog 27 | { 28 | Q_OBJECT 29 | public: 30 | ScreenChooserDialog(const QString &appName, bool multiple, ScreenCastPortal::SourceTypes types); 31 | ~ScreenChooserDialog() override; 32 | 33 | QList selectedOutputs() const; 34 | QList selectedWindows() const; 35 | bool allowRestore() const; 36 | QRect selectedRegion() const; 37 | 38 | public Q_SLOTS: 39 | void accept() override; 40 | 41 | Q_SIGNALS: 42 | void clearSelection(); 43 | 44 | private: 45 | void setRegion(const QRect region); 46 | 47 | QRect m_region; 48 | }; 49 | 50 | #endif // XDG_DESKTOP_PORTAL_KDE_SCREENCHOOSER_DIALOG_H 51 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | ############################# 2 | # Missing portals # 3 | ############################# 4 | 5 | * Background portal 6 | - a portal for autostart of applications, or to notify users that an application 7 | was started in background 8 | 9 | ############################# 10 | # Missing functions # 11 | ############################# 12 | 13 | * Inhibit portal 14 | - CreateMonitor 15 | - creates a monitoring session. While this session is active, the caller will 16 | receive StateChanged signals with updates on the session state. 17 | - StateChanged 18 | - the StateChanged signal is sent to active monitoring sessions when the session 19 | state changes. 20 | - QueryEndResponse 21 | - acknowledges that the caller received the #org.freedesktop.impl.portal.Inhibit::StateChanged 22 | signal. This method should be called within one second or receiving a StateChanged 23 | signal with the 'Query End' state. 24 | 25 | * Remote desktop portal 26 | - NotifyKeyboardKeysym 27 | - NotifyKeyboardKeycode 28 | - NotifyTouchDown 29 | - NotifyTouchMotion 30 | - NotifyTouchUp 31 | 32 | * Screensharing portal 33 | - AvailableCursorModes 34 | - CreateSession - cursor_mode option 35 | - Window source type - ability to share windows only 36 | -------------------------------------------------------------------------------- /data/org.freedesktop.impl.portal.desktop.kde.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Portal 4 | Name[ar]=البوابة 5 | Name[ast]=Portal 6 | Name[az]=Portal 7 | Name[bg]=Портал 8 | Name[ca]=Portal 9 | Name[ca@valencia]=Portal 10 | Name[cs]=Portál 11 | Name[da]=Portal 12 | Name[de]=Portal 13 | Name[el]=Πύλη 14 | Name[en_GB]=Portal 15 | Name[eo]=Portalo 16 | Name[es]=Portal 17 | Name[eu]=Ataria 18 | Name[fi]=Portaali 19 | Name[fr]=Portail 20 | Name[gl]=Portal 21 | Name[he]=שער גישה 22 | Name[hi]=पोर्टल 23 | Name[hu]=Portál 24 | Name[ia]=Portal 25 | Name[id]=Portal 26 | Name[is]=Umsýslugátt 27 | Name[it]=Portale 28 | Name[ka]=Portal 29 | Name[ko]=포털 30 | Name[lt]=Portalas 31 | Name[lv]=Portal 32 | Name[nb]=Portal 33 | Name[nl]=Portaal 34 | Name[nn]=Portal 35 | Name[pa]=ਪੋਰਟਲ 36 | Name[pl]=Portal 37 | Name[pt]=Portal 38 | Name[pt_BR]=Portal 39 | Name[ro]=Portal 40 | Name[ru]=Портал 41 | Name[sa]=पोर्टल 42 | Name[sk]=Portal 43 | Name[sl]=Portal 44 | Name[sv]=Portal 45 | Name[tr]=Portal 46 | Name[uk]=Портал 47 | Name[zh_CN]=系统门户 48 | Name[zh_TW]=Portal 49 | Exec=@CMAKE_INSTALL_FULL_LIBEXECDIR@/xdg-desktop-portal-kde 50 | X-KDE-Wayland-Interfaces=org_kde_kwin_fake_input,org_kde_plasma_window_management,zkde_screencast_unstable_v1 51 | X-KDE-DBUS-Restricted-Interfaces=org.kde.KWin.ScreenShot2 52 | NoDisplay=true 53 | Icon=kde 54 | -------------------------------------------------------------------------------- /data/org.freedesktop.Accounts.User.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | The username of the user. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | The users real name. 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | The filename of a png file containing the users icon. 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Emitted when the user is changed. 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/RemoteDesktopDialog.qml: -------------------------------------------------------------------------------- 1 | /* This file is part of the KDE project 2 | SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | 4 | SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | import QtQuick 8 | import QtQuick.Layouts 9 | import QtQuick.Controls as QQC2 10 | 11 | PortalDialog { 12 | id: root 13 | 14 | property alias description: desc.text 15 | property alias allowRestore: allowRestoreItem.checked 16 | property alias persistenceRequested: allowRestoreItem.visible 17 | 18 | width: contentWidth 19 | height: contentHeight 20 | iconName: "krfb" 21 | 22 | ColumnLayout { 23 | QQC2.Label { 24 | id: desc 25 | textFormat: Text.MarkdownText 26 | Layout.fillHeight: true 27 | } 28 | QQC2.CheckBox { 29 | id: allowRestoreItem 30 | checked: true 31 | text: i18n("Allow restoring on future sessions") 32 | } 33 | } 34 | 35 | standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 36 | 37 | Component.onCompleted: { 38 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Ok).text = i18nc("@action:button Approve the application gaining extra privileges", "Approve") 39 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Cancel).text = i18nc("@action:button Deny the application gaining extra privileges", "Deny") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/remotedesktopdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_DIALOG_H 10 | #define XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_DIALOG_H 11 | 12 | #include "outputsmodel.h" 13 | #include "quickdialog.h" 14 | #include "remotedesktop.h" 15 | #include "screencast.h" 16 | 17 | namespace Ui 18 | { 19 | class RemoteDesktopDialog; 20 | } 21 | 22 | class RemoteDesktopDialog : public QuickDialog 23 | { 24 | Q_OBJECT 25 | public: 26 | RemoteDesktopDialog(const QString &appName, 27 | RemoteDesktopPortal::DeviceTypes deviceTypes, 28 | bool screenSharingEnabled, 29 | ScreenCastPortal::PersistMode persistMode, 30 | QObject *parent = nullptr); 31 | 32 | QList selectedOutputs() const; 33 | bool allowRestore() const; 34 | 35 | static QString buildMainText(const QString &appName); 36 | static QString buildRequestDescription(RemoteDesktopPortal::DeviceTypes deviceTypes, bool screenSharingEnabled); 37 | static QString buildNotificationDescription(const QString &appName, RemoteDesktopPortal::DeviceTypes deviceTypes, bool screenSharingEnabled); 38 | }; 39 | 40 | #endif // XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_DIALOG_H 41 | -------------------------------------------------------------------------------- /src/restoredata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: LGPL-2.0-or-later 3 | * 4 | * SPDX-FileCopyrightText: 2022 Aleix Pol 5 | */ 6 | 7 | #include "restoredata.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | const QDBusArgument &operator<<(QDBusArgument &arg, const RestoreData &data) 14 | { 15 | arg.beginStructure(); 16 | arg << data.session; 17 | arg << data.version; 18 | 19 | QByteArray payloadSerialised; 20 | { 21 | QDataStream ds(&payloadSerialised, QIODevice::WriteOnly); 22 | ds << data.payload; 23 | } 24 | 25 | arg << QDBusVariant(payloadSerialised); 26 | arg.endStructure(); 27 | return arg; 28 | } 29 | const QDBusArgument &operator>>(const QDBusArgument &arg, RestoreData &data) 30 | { 31 | arg.beginStructure(); 32 | arg >> data.session; 33 | arg >> data.version; 34 | 35 | QDBusVariant payloadVariant; 36 | arg >> payloadVariant; 37 | { 38 | QByteArray payloadSerialised = payloadVariant.variant().toByteArray(); 39 | QDataStream ds(&payloadSerialised, QIODevice::ReadOnly); 40 | ds >> data.payload; 41 | } 42 | arg.endStructure(); 43 | return arg; 44 | } 45 | 46 | QDebug operator<<(QDebug dbg, const RestoreData &c) 47 | { 48 | dbg.nospace() << "RestoreData(" << c.session << ", " << c.version << ", " << c.payload << ")"; 49 | return dbg.space(); 50 | } 51 | -------------------------------------------------------------------------------- /src/region-select/SelectionEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.h" 9 | 10 | class QQuickView; 11 | 12 | class SelectionEditorPrivate; 13 | 14 | class SelectionEditor : public QObject 15 | { 16 | Q_OBJECT 17 | 18 | Q_PROPERTY(QRect rect READ rect NOTIFY rectChanged FINAL) 19 | Q_PROPERTY(bool isDragging READ isDragging NOTIFY isDraggingChanged FINAL) 20 | 21 | public: 22 | explicit SelectionEditor(QObject *parent = nullptr); 23 | ~SelectionEditor() override; 24 | 25 | bool isDragging() const; 26 | QRect rect() const; 27 | 28 | Q_SCRIPTABLE void dragStart(const QString &screenName, int x, int y); 29 | Q_SCRIPTABLE void setMousePosition(const QString &screenName, int x, int y); 30 | Q_SCRIPTABLE void dragRelease(const QString &screenName, int x, int y); 31 | Q_SCRIPTABLE void dragReset(); 32 | Q_SCRIPTABLE void reject(); 33 | 34 | Q_SIGNALS: 35 | void rectChanged(); 36 | void emptyChanged(); 37 | void isDraggingChanged(); 38 | void finished(DialogResult result); 39 | 40 | protected: 41 | bool eventFilter(QObject *watched, QEvent *event) override; 42 | void keyPressEvent(QKeyEvent *event); 43 | 44 | void showViews(); 45 | 46 | private: 47 | void accept(); 48 | 49 | SelectionEditorPrivate *d; 50 | QQmlEngine *m_engine; 51 | QList m_views; 52 | }; 53 | -------------------------------------------------------------------------------- /src/dynamiclauncher.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 2 | // SPDX-FileCopyrightText: 2022 Harald Sitter 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | class QDBusMessage; 10 | 11 | class DynamicLauncherPortal : public QDBusAbstractAdaptor 12 | { 13 | Q_OBJECT 14 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.DynamicLauncher") 15 | 16 | Q_PROPERTY(uint version MEMBER m_version CONSTANT) 17 | const uint m_version = 1; 18 | 19 | Q_PROPERTY(uint SupportedLauncherTypes MEMBER m_supportedTypes CONSTANT) 20 | const uint m_supportedTypes = uint(Type::Application) | uint(Type::Webapp); 21 | 22 | public: 23 | enum class Type { 24 | Application = 1, 25 | Webapp = 2 26 | }; 27 | 28 | explicit DynamicLauncherPortal(QObject *parent = nullptr); 29 | 30 | public Q_SLOTS: 31 | void PrepareInstall(const QDBusObjectPath &handle, 32 | const QString &app_id, 33 | const QString &parent_window, 34 | const QString &name, 35 | const QDBusVariant &icon_v, 36 | const QVariantMap &options, 37 | const QDBusMessage &message, 38 | uint &replyResponse, 39 | QVariantMap &replyResults); 40 | uint RequestInstallToken(const QString &app_id, const QVariantMap &options); 41 | }; 42 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/dirmodelutils.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 Linus Jahn 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | #include "dirmodelutils.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | DirModelUtils::DirModelUtils(QObject *parent) 13 | : QObject(parent) 14 | { 15 | } 16 | 17 | QStringList DirModelUtils::getUrlParts(const QUrl &url) const 18 | { 19 | if (url.path() == QStringLiteral("/")) 20 | return {}; 21 | 22 | return url.path().split(QStringLiteral("/")).mid(1); 23 | } 24 | 25 | QUrl DirModelUtils::partialUrlForIndex(QUrl url, int index) const 26 | { 27 | const QStringList urlParts = url.path().split(QStringLiteral("/")); 28 | QString path = QStringLiteral("/"); 29 | for (int i = 0; i < index + 1; i++) { 30 | path += urlParts.at(i + 1); 31 | path += QStringLiteral("/"); 32 | } 33 | 34 | url.setPath(path); 35 | 36 | return url; 37 | } 38 | 39 | QUrl DirModelUtils::directoryOfUrl(const QString &path) const 40 | { 41 | const int index = path.lastIndexOf(QLatin1Char('/')); 42 | return QUrl::fromLocalFile(path.mid(0, index)); 43 | } 44 | 45 | QString DirModelUtils::fileNameOfUrl(const QString &path) const 46 | { 47 | const int index = path.lastIndexOf(QLatin1Char('/')); 48 | return path.mid(index + 1); 49 | } 50 | 51 | void DirModelUtils::mkdir(const QUrl path) const 52 | { 53 | KIO::mkdir(path); 54 | } 55 | 56 | #include "moc_dirmodelutils.cpp" 57 | -------------------------------------------------------------------------------- /src/screenshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_H 10 | #define XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_H 11 | 12 | #include 13 | #include 14 | 15 | class QDBusMessage; 16 | 17 | class ScreenshotPortal : public QDBusAbstractAdaptor 18 | { 19 | Q_OBJECT 20 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Screenshot") 21 | Q_PROPERTY(uint version READ version CONSTANT) 22 | public: 23 | struct ColorRGB { 24 | double red; 25 | double green; 26 | double blue; 27 | }; 28 | 29 | explicit ScreenshotPortal(QObject *parent); 30 | ~ScreenshotPortal() override; 31 | 32 | uint version() const 33 | { 34 | return 2; 35 | } 36 | 37 | public Q_SLOTS: 38 | void Screenshot(const QDBusObjectPath &handle, 39 | const QString &app_id, 40 | const QString &parent_window, 41 | const QVariantMap &options, 42 | const QDBusMessage &message, 43 | uint &replyResponse, 44 | QVariantMap &replyResults); 45 | 46 | uint PickColor(const QDBusObjectPath &handle, const QString &app_id, const QString &parent_window, const QVariantMap &options, QVariantMap &results); 47 | }; 48 | 49 | #endif // XDG_DESKTOP_PORTAL_KDE_SCREENSHOT_H 50 | -------------------------------------------------------------------------------- /.kde-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | Dependencies: 5 | - 'on': ['@all'] 6 | 'require': 7 | 'frameworks/extra-cmake-modules': '@latest-kf6' 8 | 'frameworks/kauth': '@latest-kf6' 9 | 'frameworks/kcodecs': '@latest-kf6' 10 | 'frameworks/kcompletion': '@latest-kf6' 11 | 'frameworks/kconfig': '@latest-kf6' 12 | 'frameworks/kconfigwidgets': '@latest-kf6' 13 | 'frameworks/kcoreaddons': '@latest-kf6' 14 | 'frameworks/ki18n': '@latest-kf6' 15 | 'frameworks/kio': '@latest-kf6' 16 | 'frameworks/kitemviews': '@latest-kf6' 17 | 'frameworks/kjobwidgets': '@latest-kf6' 18 | 'frameworks/knotifications': '@latest-kf6' 19 | 'frameworks/kservice': '@latest-kf6' 20 | 'frameworks/kwidgetsaddons': '@latest-kf6' 21 | 'frameworks/kwindowsystem': '@latest-kf6' 22 | 'frameworks/kxmlgui': '@latest-kf6' 23 | 'frameworks/solid': '@latest-kf6' 24 | 'frameworks/kirigami': '@latest-kf6' 25 | 'frameworks/kstatusnotifieritem': '@latest-kf6' 26 | 'frameworks/kcrash': '@latest-kf6' 27 | 'frameworks/kdeclarative': '@latest-kf6' 28 | 'plasma/kwayland': '@same' 29 | 'plasma/plasma-workspace': '@same' 30 | 'third-party/wayland': '@latest' 31 | 'third-party/wayland-protocols': '@latest' 32 | 33 | RuntimeDependencies: 34 | - 'on': ['@all'] 35 | 'require': 36 | 'frameworks/kiconthemes': '@latest-kf6' # IconDialog 37 | 38 | Options: 39 | require-passing-tests-on: ['Linux', 'FreeBSD'] 40 | run-qmllint: true 41 | -------------------------------------------------------------------------------- /src/dbushelpers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2019 Red Hat Inc 3 | * SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez 4 | * 5 | * SPDX-License-Identifier: LGPL-2.0-or-later 6 | * 7 | * SPDX-FileCopyrightText: 2018-2019 Jan Grulich 8 | */ 9 | 10 | #include "dbushelpers.h" 11 | 12 | QDBusArgument &operator<<(QDBusArgument &arg, const Choice &choice) 13 | { 14 | arg.beginStructure(); 15 | arg << choice.id << choice.value; 16 | arg.endStructure(); 17 | return arg; 18 | } 19 | 20 | const QDBusArgument &operator>>(const QDBusArgument &arg, Choice &choice) 21 | { 22 | QString id; 23 | QString value; 24 | arg.beginStructure(); 25 | arg >> id >> value; 26 | choice.id = id; 27 | choice.value = value; 28 | arg.endStructure(); 29 | return arg; 30 | } 31 | 32 | QDBusArgument &operator<<(QDBusArgument &arg, const Option &option) 33 | { 34 | arg.beginStructure(); 35 | arg << option.id << option.label << option.choices << option.initialChoiceId; 36 | arg.endStructure(); 37 | return arg; 38 | } 39 | 40 | const QDBusArgument &operator>>(const QDBusArgument &arg, Option &option) 41 | { 42 | QString id; 43 | QString label; 44 | Choices choices; 45 | QString initialChoiceId; 46 | arg.beginStructure(); 47 | arg >> id >> label >> choices >> initialChoiceId; 48 | option.id = id; 49 | option.label = label; 50 | option.choices = choices; 51 | option.initialChoiceId = initialChoiceId; 52 | arg.endStructure(); 53 | return arg; 54 | } 55 | 56 | #include "moc_dbushelpers.cpp" 57 | -------------------------------------------------------------------------------- /src/request.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | * SPDX-FileCopyrightText: 2022 Harald Sitter 8 | */ 9 | 10 | #ifndef XDG_DESKTOP_PORTAL_KDE_REQUEST_H 11 | #define XDG_DESKTOP_PORTAL_KDE_REQUEST_H 12 | 13 | #include "session.h" 14 | 15 | #include 16 | #include 17 | 18 | class QDBusObjectPath; 19 | 20 | class Request : public QDBusVirtualObject 21 | { 22 | Q_OBJECT 23 | public: 24 | explicit Request(const QDBusObjectPath &handle, QObject *parent = nullptr); 25 | 26 | bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) override; 27 | QString introspect(const QString &path) const override; 28 | 29 | template 30 | static Request *makeClosableDialogRequest(const QDBusObjectPath &handle, T *dialogAndParent) 31 | { 32 | auto request = new Request(handle, dialogAndParent); 33 | connect(request, &Request::closeRequested, dialogAndParent, &T::reject); 34 | return request; 35 | } 36 | 37 | template 38 | static Request *makeClosableDialogRequestWithSession(const QDBusObjectPath &handle, T *dialogAndParent, Session *session) 39 | { 40 | auto request = makeClosableDialogRequest(handle, dialogAndParent); 41 | connect(session, &Session::closed, dialogAndParent, &T::reject); 42 | return request; 43 | } 44 | 45 | Q_SIGNALS: 46 | void closeRequested(); 47 | }; 48 | 49 | #endif // XDG_DESKTOP_PORTAL_KDE_REQUEST_H 50 | -------------------------------------------------------------------------------- /src/desktopportal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H 10 | #define XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H 11 | 12 | #include 13 | #include 14 | 15 | class AccessPortal; 16 | class AccountPortal; 17 | class AppChooserPortal; 18 | class BackgroundPortal; 19 | class EmailPortal; 20 | class FileChooserPortal; 21 | class InhibitPortal; 22 | class NotificationPortal; 23 | class PrintPortal; 24 | class ScreenshotPortal; 25 | class SettingsPortal; 26 | class ScreenCastPortal; 27 | class RemoteDesktopPortal; 28 | class DynamicLauncherPortal; 29 | 30 | class DesktopPortal : public QObject, public QDBusContext 31 | { 32 | Q_OBJECT 33 | public: 34 | explicit DesktopPortal(QObject *parent = nullptr); 35 | 36 | private: 37 | AccessPortal *const m_access; 38 | AccountPortal *const m_account; 39 | AppChooserPortal *const m_appChooser; 40 | BackgroundPortal *m_background = nullptr; 41 | EmailPortal *const m_email; 42 | FileChooserPortal *const m_fileChooser; 43 | InhibitPortal *const m_inhibit; 44 | NotificationPortal *const m_notification; 45 | PrintPortal *const m_print; 46 | ScreenshotPortal *m_screenshot = nullptr; 47 | SettingsPortal *const m_settings; 48 | ScreenCastPortal *m_screenCast = nullptr; 49 | RemoteDesktopPortal *m_remoteDesktop = nullptr; 50 | DynamicLauncherPortal *const m_dynamicLauncher; 51 | }; 52 | 53 | #endif // XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H 54 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/PlacesGlobalDrawer.qml: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 Linus Jahn 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | import QtQuick 6 | import QtQuick.Controls as QQC2 7 | import QtQuick.Layouts 8 | import org.kde.kirigami as Kirigami 9 | import org.kde.kirigamifilepicker 10 | 11 | /** 12 | * The PlacesGlobalDrawer type provides a GlobalDrawer containing common places on the file system 13 | */ 14 | Kirigami.OverlayDrawer { 15 | id: root 16 | 17 | signal placeOpenRequested(url place) 18 | 19 | handleClosedIcon.source: null 20 | handleOpenIcon.source: null 21 | width: Math.min(applicationWindow().width * 0.8, Kirigami.Units.gridUnit * 20) 22 | 23 | leftPadding: 0 24 | rightPadding: 0 25 | 26 | contentItem: ListView { 27 | spacing: 0 28 | model: FilePlacesModel { 29 | id: filePlacesModel 30 | } 31 | 32 | section.property: "group" 33 | section.delegate: Kirigami.Heading { 34 | leftPadding: Kirigami.Units.smallSpacing 35 | level: 6 36 | text: section 37 | } 38 | 39 | delegate: QQC2.ItemDelegate { 40 | required property string displayRole 41 | required property string iconName 42 | required property bool hidden 43 | required property url url 44 | 45 | visible: !hidden 46 | width: ListView.view.width 47 | text: displayRole 48 | icon.name: iconName 49 | onClicked: { 50 | root.placeOpenRequested(url) 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/clipboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class Session; 15 | 16 | class ClipboardPortal : public QDBusAbstractAdaptor 17 | { 18 | Q_OBJECT 19 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Clipboard") 20 | public: 21 | explicit ClipboardPortal(QObject *parent); 22 | 23 | QVariant fetchData(Session *session, const QString &mimetype); 24 | 25 | public Q_SLOTS: 26 | void RequestClipboard(const QDBusObjectPath &session_handle, const QVariantMap &options); 27 | void SetSelection(const QDBusObjectPath &session_handle, const QVariantMap &options); 28 | QDBusUnixFileDescriptor SelectionWrite(const QDBusObjectPath &session_handle, uint serial, const QDBusMessage &message); 29 | void SelectionWriteDone(const QDBusObjectPath &session_handle, uint serial, bool success, const QDBusMessage &message); 30 | QDBusUnixFileDescriptor SelectionRead(const QDBusObjectPath &session_handle, const QString &mime_type, const QDBusMessage &message); 31 | 32 | Q_SIGNALS: 33 | void SelectionOwnerChanged(const QDBusObjectPath &session_handle, const QVariantMap &options); 34 | void SelectionTransfer(const QDBusObjectPath &session_handle, const QString &mimeType, uint serial); 35 | 36 | private: 37 | struct Transfer { 38 | QEventLoop &loop; 39 | int fd = -1; 40 | QByteArray data; 41 | }; 42 | std::map m_pendingTransfers; 43 | }; 44 | -------------------------------------------------------------------------------- /src/appchooser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016-2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016-2018 Jan Grulich 7 | * SPDX-FileCopyrightText: 2022 Harald Sitter 8 | */ 9 | 10 | #ifndef XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H 11 | #define XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H 12 | 13 | #include 14 | #include 15 | 16 | class QDBusMessage; 17 | class AppChooserDialog; 18 | 19 | class AppChooserPortal : public QDBusAbstractAdaptor 20 | { 21 | Q_OBJECT 22 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.AppChooser") 23 | public: 24 | explicit AppChooserPortal(QObject *parent); 25 | 26 | public Q_SLOTS: 27 | void ChooseApplication(const QDBusObjectPath &handle, 28 | const QString &app_id, 29 | const QString &parent_window, 30 | const QStringList &choices, 31 | const QVariantMap &options, 32 | const QDBusMessage &message, 33 | uint &replyResponse, 34 | QVariantMap &replyResults); 35 | 36 | uint ChooseApplicationPrivate(const QString &parent_window, 37 | const QStringList &urls, 38 | const QVariantMap &options, 39 | const QDBusMessage &msg, 40 | QVariantMap &replyResults); 41 | void UpdateChoices(const QDBusObjectPath &handle, const QStringList &choices); 42 | 43 | private: 44 | QMap m_appChooserDialogs; 45 | }; 46 | 47 | #endif // XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_H 48 | -------------------------------------------------------------------------------- /autotests/xdgshortcuttest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "../src/xdgshortcut.h" 11 | 12 | class XdgShortcutTest : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | XdgShortcutTest(QObject *parent = nullptr) 17 | : QObject(parent) 18 | { 19 | QStandardPaths::setTestModeEnabled(true); 20 | } 21 | 22 | private Q_SLOTS: 23 | void initTestCase() 24 | { 25 | } 26 | 27 | void testCheckShortcut_data() 28 | { 29 | QTest::addColumn("expression"); 30 | QTest::addColumn("result"); 31 | 32 | QTest::newRow("a") << "a" << QKeySequence(Qt::Key_A); 33 | QTest::newRow("ctrla") << "CTRL+a" << QKeySequence(Qt::Key_A | Qt::ControlModifier); 34 | QTest::newRow("ctrlshifta") << "CTRL+SHIFT+a" << QKeySequence(QKeyCombination(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_A )); 35 | QTest::newRow("ctrlaltreturn") << "CTRL+ALT+Return" << QKeySequence(QKeyCombination(Qt::ControlModifier | Qt::AltModifier | Qt::Key_Return)); 36 | QTest::newRow("withweirdtoken") << "CTRL+a;Banana" << QKeySequence(Qt::Key_A | Qt::ControlModifier); 37 | QTest::newRow("justcontrol") << "Control_L" << QKeySequence(Qt::Key_Control); 38 | } 39 | 40 | void testCheckShortcut() 41 | { 42 | QFETCH(QString, expression); 43 | QFETCH(QKeySequence, result); 44 | 45 | const auto shortcut = XdgShortcut::parse(expression); 46 | QVERIFY(shortcut.has_value()); 47 | QCOMPARE(*shortcut, result); 48 | } 49 | }; 50 | 51 | QTEST_GUILESS_MAIN(XdgShortcutTest) 52 | 53 | #include "xdgshortcuttest.moc" 54 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2019 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018-2019 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_SETTINGS_H 10 | #define XDG_DESKTOP_PORTAL_KDE_SETTINGS_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include "dbushelpers.h" 18 | 19 | class DesktopPortal; 20 | class FdoAppearanceSettings; 21 | class KDEGlobalsSettings; 22 | class SettingsModule; 23 | 24 | class SettingsModule : public QObject 25 | { 26 | Q_OBJECT 27 | public: 28 | using QObject::QObject; 29 | ~SettingsModule() override = default; 30 | Q_DISABLE_COPY_MOVE(SettingsModule) 31 | virtual inline QString group() = 0; 32 | virtual VariantMapMap readAll(const QStringList &groups) = 0; 33 | virtual QVariant read(const QString &group, const QString &key) = 0; 34 | Q_SIGNAL void settingChanged(const QString &group, const QString &key, const QDBusVariant &value); 35 | }; 36 | 37 | class SettingsPortal : public QDBusAbstractAdaptor 38 | { 39 | Q_OBJECT 40 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Settings") 41 | Q_PROPERTY(uint version READ version CONSTANT) 42 | public: 43 | explicit SettingsPortal(DesktopPortal *parent); 44 | 45 | uint version() const 46 | { 47 | return 1; 48 | } 49 | 50 | public Q_SLOTS: 51 | void ReadAll(const QStringList &groups); 52 | void Read(const QString &group, const QString &key); 53 | 54 | Q_SIGNALS: 55 | void SettingChanged(const QString &group, const QString &key, const QDBusVariant &value); 56 | 57 | private: 58 | DesktopPortal *const m_parent; 59 | std::vector> m_settings; 60 | }; 61 | 62 | #endif // XDG_DESKTOP_PORTAL_KDE_SETTINGS_H 63 | -------------------------------------------------------------------------------- /src/session.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #include "session.h" 10 | #include "desktopportal.h" 11 | #include "session_debug.h" 12 | #include "sessionadaptor.h" 13 | #include "xdgshortcut.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "remotedesktopdialog.h" 27 | #include "utils.h" 28 | #include 29 | 30 | static QMap sessionList; 31 | 32 | using namespace Qt::StringLiterals; 33 | 34 | Session::Session(QObject *parent, const QString &appId, const QString &path) 35 | : QObject(parent) 36 | , m_appId(appId) 37 | , m_path(path) 38 | { 39 | new SessionAdaptor(this); 40 | if (QDBusConnection::sessionBus().registerObject(path, this)) { 41 | m_valid = true; 42 | sessionList.insert(path, this); 43 | } 44 | } 45 | 46 | Session::~Session() 47 | { 48 | } 49 | 50 | bool Session::close() 51 | { 52 | QDBusMessage reply = QDBusMessage::createSignal(m_path, QStringLiteral("org.freedesktop.impl.portal.Session"), QStringLiteral("Closed")); 53 | const bool result = QDBusConnection::sessionBus().send(reply); 54 | 55 | Q_EMIT closed(); 56 | 57 | sessionList.remove(m_path); 58 | QDBusConnection::sessionBus().unregisterObject(m_path); 59 | 60 | deleteLater(); 61 | m_valid = false; 62 | 63 | return result; 64 | } 65 | 66 | Session *Session::getSession(const QString &sessionHandle) 67 | { 68 | return sessionList.value(sessionHandle); 69 | } 70 | 71 | void Session::Close() 72 | { 73 | close(); 74 | } 75 | 76 | #include "moc_session.cpp" 77 | -------------------------------------------------------------------------------- /src/quickdialog.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of the KDE project 2 | SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | 4 | SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #include "quickdialog.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace Qt::StringLiterals; 15 | 16 | QuickDialog::QuickDialog(QObject *parent) 17 | : QObject(parent) 18 | { 19 | } 20 | 21 | QuickDialog::~QuickDialog() noexcept 22 | { 23 | delete m_theDialog; 24 | } 25 | 26 | void QuickDialog::create(const QString &componentName, const QVariantMap &props) 27 | { 28 | auto engine = new QQmlApplicationEngine(this); 29 | auto context = new KLocalizedContext(engine); 30 | context->setTranslationDomain(QStringLiteral(TRANSLATION_DOMAIN)); 31 | engine->rootContext()->setContextObject(context); 32 | 33 | engine->setInitialProperties(props); 34 | engine->loadFromModule("org.kde.xdgdesktopportal"_L1, componentName); 35 | 36 | connect(engine, &QQmlEngine::warnings, this, [](const QList &warnings) { 37 | for (const QQmlError &warning : warnings) { 38 | qWarning() << warning; 39 | } 40 | }); 41 | 42 | const QList rootObjects = engine->rootObjects(); 43 | if (rootObjects.isEmpty()) { 44 | return; 45 | } 46 | m_theDialog = qobject_cast(rootObjects.constFirst()); 47 | connect(m_theDialog, SIGNAL(accept()), this, SLOT(accept())); 48 | connect(m_theDialog, SIGNAL(reject()), this, SLOT(reject())); 49 | 50 | QTimer::singleShot(0, m_theDialog, SLOT(present())); 51 | } 52 | 53 | void QuickDialog::reject() 54 | { 55 | Q_EMIT rejected(); 56 | Q_EMIT finished(DialogResult::Rejected); 57 | deleteLater(); 58 | } 59 | 60 | void QuickDialog::accept() 61 | { 62 | Q_EMIT accepted(); 63 | Q_EMIT finished(DialogResult::Accepted); 64 | deleteLater(); 65 | } 66 | 67 | #include "moc_quickdialog.cpp" 68 | -------------------------------------------------------------------------------- /src/desktopportal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #include "desktopportal.h" 10 | #include "desktopportal_debug.h" 11 | 12 | #include "access.h" 13 | #include "account.h" 14 | #include "appchooser.h" 15 | #include "background.h" 16 | #include "clipboard.h" 17 | #include "dynamiclauncher.h" 18 | #include "email.h" 19 | #include "filechooser.h" 20 | #include "globalshortcuts.h" 21 | #include "inhibit.h" 22 | #include "inputcapture.h" 23 | #include "notification.h" 24 | #include "print.h" 25 | #include "remotedesktop.h" 26 | #include "screencast.h" 27 | #include "screenshot.h" 28 | #include "settings.h" 29 | #include "usb.h" 30 | #include "wallpaper.h" 31 | #include "waylandintegration.h" 32 | 33 | DesktopPortal::DesktopPortal(QObject *parent) 34 | : QObject(parent) 35 | , m_access(new AccessPortal(this)) 36 | , m_account(new AccountPortal(this)) 37 | , m_appChooser(new AppChooserPortal(this)) 38 | , m_email(new EmailPortal(this)) 39 | , m_fileChooser(new FileChooserPortal(this)) 40 | , m_inhibit(new InhibitPortal(this)) 41 | , m_notification(new NotificationPortal(this)) 42 | , m_print(new PrintPortal(this)) 43 | , m_settings(new SettingsPortal(this)) 44 | , m_dynamicLauncher(new DynamicLauncherPortal(this)) 45 | { 46 | const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); 47 | if (xdgCurrentDesktop.compare("KDE", Qt::CaseInsensitive) == 0) { 48 | new GlobalShortcutsPortal(this); 49 | 50 | m_background = new BackgroundPortal(this, this); 51 | m_screenCast = new ScreenCastPortal(this); 52 | m_remoteDesktop = new RemoteDesktopPortal(this); 53 | m_screenshot = new ScreenshotPortal(this); 54 | new InputCapturePortal(this); 55 | new ClipboardPortal(this); 56 | new WallpaperPortal(this); 57 | WaylandIntegration::init(); 58 | } 59 | new UsbPortal(this); 60 | } 61 | 62 | #include "moc_desktopportal.cpp" 63 | -------------------------------------------------------------------------------- /src/background.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2020 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_BACKGROUND_H 10 | #define XDG_DESKTOP_PORTAL_KDE_BACKGROUND_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace KWayland 18 | { 19 | namespace Client 20 | { 21 | class PlasmaWindow; 22 | } 23 | } 24 | 25 | class KNotification; 26 | 27 | class BackgroundPortal : public QDBusAbstractAdaptor 28 | { 29 | Q_OBJECT 30 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Background") 31 | public: 32 | explicit BackgroundPortal(QObject *parent, QDBusContext *context); 33 | ~BackgroundPortal() override; 34 | 35 | enum ApplicationState { 36 | Background = 0, 37 | Running = 1, 38 | Active = 2, 39 | }; 40 | 41 | enum AutostartFlag { 42 | None = 0x0, 43 | Activatable = 0x1, 44 | }; 45 | Q_DECLARE_FLAGS(AutostartFlags, AutostartFlag) 46 | 47 | enum NotifyResult { 48 | Forbid = 0, 49 | Allow = 1, 50 | AllowOnce = 2, 51 | }; 52 | 53 | public Q_SLOTS: 54 | QVariantMap GetAppState(); 55 | 56 | uint NotifyBackground(const QDBusObjectPath &handle, const QString &app_id, const QString &name, QVariantMap &results); 57 | 58 | bool EnableAutostart(const QString &app_id, bool enable, const QStringList &commandline, uint flags); 59 | Q_SIGNALS: 60 | void RunningApplicationsChanged(); 61 | 62 | private: 63 | void addWindow(KWayland::Client::PlasmaWindow *window); 64 | void setActiveWindow(const QString &appId, bool active); 65 | 66 | uint m_notificationCounter = 0; 67 | QList m_windows; 68 | QVariantMap m_appStates; 69 | QSet m_backgroundAppWarned; 70 | QDBusContext *const m_context; 71 | }; 72 | Q_DECLARE_OPERATORS_FOR_FLAGS(BackgroundPortal::AutostartFlags) 73 | 74 | #endif // XDG_DESKTOP_PORTAL_KDE_BACKGROUND_H 75 | -------------------------------------------------------------------------------- /src/WallpaperDialog.qml: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2025 David Redondo 4 | */ 5 | 6 | import QtQuick 7 | import QtQuick.Controls as QQC 8 | import QtQuick.Layouts 9 | import org.kde.kirigami as Kirigami 10 | import org.kde.xdgdesktopportal 11 | 12 | PortalDialog 13 | { 14 | id: root 15 | required property int location 16 | required property string app 17 | required property url image 18 | 19 | iconName: "preferences-desktop-wallpaper" 20 | title: i18nc("@title:window", "Set Wallpaper") 21 | subtitle: { 22 | if (app === "") { 23 | switch (location) { 24 | case WallpaperLocation.Desktop: 25 | return i18nc("the app is unknown", "Allow an application to set the desktop background?") 26 | case WallpaperLocation.Lockscreen: 27 | return i18nc("the app is unknown", "Allow an application to set the lock screen background?") 28 | case WallpaperLocation.Both: 29 | return i18nc("the app is unknown", "Allow an application to set desktop and lock screen backgrounds?") 30 | } 31 | } else { 32 | switch (location) { 33 | case WallpaperLocation.Desktop: 34 | return i18nc("%1 is the application name", "Allow %1 to set the desktop background?", app) 35 | case WallpaperLocation.Lockscreen: 36 | return i18nc("%1 is the application name", "Allow %1 to set the lock screen background?", app) 37 | case WallpaperLocation.Both: 38 | return i18nc("%1 is the application name", "Allow %1 to set desktop and lock screen backgrounds?", app) 39 | } 40 | } 41 | } 42 | 43 | Item { 44 | implicitHeight: Kirigami.Units.gridUnit * 10 45 | Image { 46 | id: image 47 | anchors.fill: parent 48 | fillMode: Image.PreserveAspectFit 49 | source: root.image 50 | } 51 | } 52 | 53 | standardButtons: QQC.DialogButtonBox.Ok | QQC.DialogButtonBox.Cancel 54 | } 55 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/api/mobilefiledialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 Jonah Brüchert 2 | // 3 | // SPDX-License-Identifier: LGPL-2.0-or-later 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class QQmlApplicationEngine; 11 | class FileChooserQmlCallback; 12 | class QQuickWindow; 13 | 14 | class MobileFileDialog : public QObject 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | MobileFileDialog(QObject *parent); 20 | ~MobileFileDialog() override = default; 21 | 22 | // Reset all fields for a new mobile file dialog session 23 | void reset(bool reloadWindow); 24 | 25 | QString title() const; 26 | void setTitle(const QString &title); 27 | 28 | bool selectMultiple() const; 29 | void setSelectMultiple(bool selectMultiple); 30 | 31 | bool selectExisting() const; 32 | void setSelectExisting(bool selectExisting); 33 | 34 | QStringList nameFilters() const; 35 | void setNameFilters(const QStringList &nameFilters); 36 | 37 | QStringList mimeTypeFilters() const; 38 | void setMimeTypeFilters(const QStringList &mimeTypeFilters); 39 | 40 | QUrl folder() const; 41 | void setFolder(const QUrl &folder); 42 | 43 | QString currentFile() const; 44 | void setCurrentFile(const QString ¤tFile); 45 | 46 | QString acceptLabel() const; 47 | void setAcceptLabel(const QString &acceptLabel); 48 | 49 | bool selectFolder() const; 50 | void setSelectFolder(bool selectFolder); 51 | 52 | QList results() const; 53 | 54 | uint exec(); 55 | 56 | Q_SIGNALS: 57 | void accepted(const QList &files); 58 | void titleChanged(); 59 | void selectMultipleChanged(); 60 | void selectExistingChanged(); 61 | void nameFiltersChanged(); 62 | void mimeTypeFiltersChanged(); 63 | void folderChanged(); 64 | void currentFileChanged(); 65 | void acceptLabelChanged(); 66 | void selectFolderChanged(); 67 | void cancel(); 68 | 69 | private: 70 | QQmlApplicationEngine *m_engine; 71 | FileChooserQmlCallback *m_callback; 72 | QList m_results; 73 | QQuickWindow *m_window; 74 | 75 | bool m_customTitleSet; 76 | }; 77 | -------------------------------------------------------------------------------- /src/session.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2018 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_SESSION_H 10 | #define XDG_DESKTOP_PORTAL_KDE_SESSION_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class KStatusNotifierItem; 18 | class KGlobalAccelInterface; 19 | class KGlobalAccelComponentInterface; 20 | class RemoteDesktopPortal; 21 | 22 | class Session : public QObject 23 | { 24 | Q_OBJECT 25 | Q_DISABLE_COPY(Session) 26 | public: 27 | explicit Session(QObject *parent = nullptr, const QString &appId = QString(), const QString &path = QString()); 28 | ~Session() override; 29 | 30 | enum SessionType { 31 | ScreenCast = 0, 32 | RemoteDesktop = 1, 33 | GlobalShortcuts = 2, 34 | InputCapture = 3, 35 | SessionStateMonitor = 4, 36 | }; 37 | 38 | bool close(); 39 | virtual SessionType type() const = 0; 40 | 41 | static Session *getSession(const QString &sessionHandle); 42 | template 43 | static T *getSession(const QString &sessionHandle) 44 | { 45 | return qobject_cast(getSession(sessionHandle)); 46 | } 47 | 48 | /* 49 | * The path of the session 50 | */ 51 | QString handle() const 52 | { 53 | return m_path; 54 | } 55 | 56 | QString appId() const 57 | { 58 | return m_appId; 59 | } 60 | 61 | /* 62 | * Internal: For DBus consumption 63 | */ 64 | uint version() const 65 | { 66 | return 2; 67 | } 68 | 69 | /* 70 | * Returns if the Session was registered successfully 71 | */ 72 | bool isValid() const 73 | { 74 | return m_valid; 75 | } 76 | 77 | /* 78 | * Internal: For DBus consumption 79 | */ 80 | void Close(); 81 | 82 | Q_SIGNALS: 83 | void closed(); 84 | 85 | protected: 86 | const QString m_appId; 87 | const QString m_path; 88 | 89 | private: 90 | bool m_valid = false; 91 | }; 92 | 93 | #endif // XDG_DESKTOP_PORTAL_KDE_SESSION_H 94 | -------------------------------------------------------------------------------- /src/accessdialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | */ 8 | 9 | #include "accessdialog.h" 10 | #include "accessdialog_debug.h" 11 | #include "utils.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace Qt::StringLiterals; 19 | 20 | using namespace Qt::StringLiterals; 21 | 22 | AccessDialog::AccessDialog(QObject *parent) 23 | : QuickDialog(parent) 24 | { 25 | m_props = { 26 | {u"iconName"_s, u"dialog-question"_s}, 27 | {u"title"_s, i18n("Request device access")}, 28 | }; 29 | } 30 | 31 | void AccessDialog::setAcceptLabel(const QString &label) 32 | { 33 | m_props.insert(QStringLiteral("acceptLabel"), label); 34 | } 35 | 36 | void AccessDialog::setBody(const QString &body) 37 | { 38 | m_props.insert(QStringLiteral("body"), body); 39 | } 40 | 41 | void AccessDialog::setIcon(const QString &icon) 42 | { 43 | m_props.insert(QStringLiteral("iconName"), icon); 44 | } 45 | 46 | void AccessDialog::setRejectLabel(const QString &label) 47 | { 48 | m_props.insert(QStringLiteral("rejectLabel"), label); 49 | } 50 | 51 | void AccessDialog::setSubtitle(const QString &subtitle) 52 | { 53 | m_props.insert(QStringLiteral("subtitle"), subtitle); 54 | } 55 | 56 | void AccessDialog::setTitle(const QString &title) 57 | { 58 | m_props.insert(QStringLiteral("title"), title); 59 | } 60 | 61 | void AccessDialog::setChoices(const OptionList &choices) 62 | { 63 | m_props.insert(u"choices"_s, QVariant::fromValue(choices)); 64 | } 65 | 66 | Choices AccessDialog::selectedChoices() const 67 | { 68 | auto props = m_theDialog->property("selectedChoices").value(); 69 | Choices choices; 70 | choices.reserve(props.size()); 71 | for (const auto &prop : props.asKeyValueRange()) { 72 | choices.emplaceBack(prop.first, prop.second.toString()); 73 | } 74 | return choices; 75 | } 76 | 77 | void AccessDialog::createDialog() 78 | { 79 | create(QStringLiteral("AccessDialog"), m_props); 80 | } 81 | 82 | #include "moc_accessdialog.cpp" 83 | -------------------------------------------------------------------------------- /src/org.freedesktop.impl.portal.Session.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/inhibit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | * SPDX-FileCopyrightText: 2025 David Edmundson 8 | */ 9 | 10 | #ifndef XDG_DESKTOP_PORTAL_KDE_INHIBIT_H 11 | #define XDG_DESKTOP_PORTAL_KDE_INHIBIT_H 12 | 13 | #include 14 | #include 15 | 16 | #include "request.h" 17 | 18 | class SessionStateMonitorSession; 19 | 20 | class InhibitPortal : public QDBusAbstractAdaptor 21 | { 22 | Q_OBJECT 23 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Inhibit") 24 | Q_PROPERTY(uint version READ version CONSTANT) 25 | 26 | public: 27 | explicit InhibitPortal(QObject *parent); 28 | 29 | uint version() const 30 | { 31 | return 3; 32 | } 33 | 34 | void queryCanEndSession(const QDBusMessage &message); 35 | void endSession(); 36 | 37 | public Q_SLOTS: 38 | void Inhibit(const QDBusObjectPath &handle, const QString &app_id, const QString &window, uint flags, const QVariantMap &options); 39 | uint CreateMonitor(const QDBusObjectPath &handle, const QDBusObjectPath &session_handle, const QString &app_id, const QString &window); 40 | void QueryEndResponse(const QDBusObjectPath &handle); 41 | 42 | private Q_SLOTS: 43 | void lockScreenStateChanged(bool state); 44 | 45 | Q_SIGNALS: 46 | void StateChanged(const QDBusObjectPath &path, const QVariantMap &state); 47 | 48 | private: 49 | enum LockScreenState { 50 | LockScreenInactive, 51 | LockScreenActive, 52 | }; 53 | enum SessionState { 54 | Running = 1, 55 | QueryEnd = 2, 56 | Ending = 3, 57 | }; 58 | 59 | void updateState(SessionStateMonitorSession *session, LockScreenState, SessionState state); 60 | void queryCanShutDownComplete(); 61 | QHash m_monitors; 62 | QHash m_appsBlockingLogout; 63 | QDBusMessage m_pendingCanShutDownReply; 64 | LockScreenState m_lockState = LockScreenInactive; 65 | SessionState m_sessionState = Running; 66 | }; 67 | 68 | #endif // XDG_DESKTOP_PORTAL_KDE_INHIBIT_H 69 | -------------------------------------------------------------------------------- /src/screencasting.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez 3 | 4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct zkde_screencast_unstable_v1; 16 | 17 | namespace KWayland 18 | { 19 | namespace Client 20 | { 21 | class PlasmaWindow; 22 | class Registry; 23 | class Output; 24 | } 25 | } 26 | 27 | class ScreencastingPrivate; 28 | class ScreencastingSourcePrivate; 29 | class ScreencastingStreamPrivate; 30 | class ScreencastingStream : public QObject 31 | { 32 | Q_OBJECT 33 | public: 34 | ScreencastingStream(QObject *parent); 35 | ~ScreencastingStream() override; 36 | 37 | quint32 nodeid() const; 38 | QRect geometry() const; 39 | 40 | Q_SIGNALS: 41 | void created(quint32 nodeid); 42 | void failed(const QString &error); 43 | void closed(); 44 | 45 | private: 46 | friend class Screencasting; 47 | QScopedPointer d; 48 | }; 49 | 50 | class Screencasting : public QObject 51 | { 52 | Q_OBJECT 53 | public: 54 | explicit Screencasting(QObject *parent = nullptr); 55 | explicit Screencasting(KWayland::Client::Registry *registry, int id, int version, QObject *parent = nullptr); 56 | ~Screencasting() override; 57 | 58 | enum CursorMode { 59 | Hidden = 1, 60 | Embedded = 2, 61 | Metadata = 4, 62 | }; 63 | Q_ENUM(CursorMode) 64 | 65 | ScreencastingStream *createOutputStream(QScreen *screen, CursorMode mode); 66 | ScreencastingStream *createWindowStream(const KWayland::Client::PlasmaWindow *window, CursorMode mode); 67 | ScreencastingStream *createRegionStream(const QRect &geometry, qreal scale, CursorMode mode); 68 | ScreencastingStream *createVirtualOutputStream(const QString &name, const QString &description, const QSize &size, qreal scale, CursorMode mode); 69 | 70 | void setup(zkde_screencast_unstable_v1 *screencasting); 71 | void destroy(); 72 | 73 | Q_SIGNALS: 74 | void removed(); 75 | void sourcesChanged(); 76 | 77 | private: 78 | QScopedPointer d; 79 | }; 80 | -------------------------------------------------------------------------------- /src/UserInfoDialog.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Red Hat Inc 3 | * SPDX-License-Identifier: LGPL-2.0-or-later 4 | * 5 | * SPDX-FileCopyrightText: 2020 Jan Grulich 6 | * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 7 | */ 8 | 9 | import QtQuick 10 | import QtQuick.Layouts 11 | import QtQuick.Controls as QQC2 12 | import org.kde.kirigami as Kirigami 13 | import org.kde.kirigamiaddons.components as KirigamiComponents 14 | 15 | PortalDialog { 16 | id: root 17 | 18 | title: i18nc("@action:button", "Share user info") 19 | required property string realname 20 | required property string username 21 | property alias avatar: avatar.source 22 | 23 | width: Kirigami.Units.gridUnit * 28 24 | height: Kirigami.Units.gridUnit * 30 25 | 26 | ColumnLayout { 27 | spacing: Kirigami.Units.largeSpacing 28 | 29 | Item { 30 | Layout.fillHeight: true 31 | } 32 | 33 | KirigamiComponents.Avatar { 34 | id: avatar 35 | 36 | readonly property int size: 8 * Kirigami.Units.gridUnit 37 | 38 | Layout.preferredWidth: size 39 | Layout.preferredHeight: size 40 | Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter 41 | } 42 | 43 | component Heading: Kirigami.Heading { 44 | visible: text.length > 0 45 | wrapMode: Text.WordWrap 46 | 47 | horizontalAlignment: Text.AlignHCenter 48 | verticalAlignment: Text.AlignTop 49 | 50 | Layout.alignment: Qt.AlignTop | Qt.AlignHCenter 51 | Layout.fillWidth: true 52 | } 53 | 54 | Heading { 55 | level: 1 56 | text: root.realname 57 | } 58 | 59 | Heading { 60 | // Take away the spacing here so things look a bit more packed since they are related information. 61 | Layout.topMargin: -parent.spacing 62 | 63 | level: 2 64 | text: root.username 65 | color: Kirigami.Theme.disabledTextColor 66 | } 67 | 68 | Item { 69 | Layout.fillHeight: true 70 | } 71 | } 72 | 73 | standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 74 | 75 | Component.onCompleted: { 76 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Ok).text = i18nc("@action:button", "Share") 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/account.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Red Hat Inc 3 | * SPDX-License-Identifier: LGPL-2.0-or-later 4 | * 5 | * SPDX-FileCopyrightText: 2020 Jan Grulich 6 | */ 7 | 8 | #include "account.h" 9 | #include "account_debug.h" 10 | #include "dbushelpers.h" 11 | #include "userinfodialog.h" 12 | #include "utils.h" 13 | 14 | #include 15 | 16 | AccountPortal::AccountPortal(QObject *parent) 17 | : QDBusAbstractAdaptor(parent) 18 | { 19 | } 20 | 21 | void AccountPortal::GetUserInformation(const QDBusObjectPath &handle, 22 | const QString &app_id, 23 | const QString &parent_window, 24 | const QVariantMap &options, 25 | const QDBusMessage &message, 26 | [[maybe_unused]] uint &replyResponse, 27 | [[maybe_unused]] QVariantMap &replyResults) 28 | { 29 | qCDebug(XdgDesktopPortalKdeAccount) << "GetUserInformation called with parameters:"; 30 | qCDebug(XdgDesktopPortalKdeAccount) << " handle: " << handle.path(); 31 | qCDebug(XdgDesktopPortalKdeAccount) << " parent_window: " << parent_window; 32 | qCDebug(XdgDesktopPortalKdeAccount) << " app_id: " << app_id; 33 | qCDebug(XdgDesktopPortalKdeAccount) << " options: " << options; 34 | 35 | QString reason; 36 | 37 | if (options.contains(QStringLiteral("reason"))) { 38 | reason = options.value(QStringLiteral("reason")).toString(); 39 | } 40 | 41 | UserInfoDialog *userInfoDialog = new UserInfoDialog(reason, app_id); 42 | Utils::setParentWindow(userInfoDialog->windowHandle(), parent_window); 43 | 44 | delayReply(message, userInfoDialog, this, [message, userInfoDialog](DialogResult result) { 45 | QVariantMap results; 46 | if (result == DialogResult::Accepted) { 47 | results.insert(QStringLiteral("id"), userInfoDialog->id()); 48 | results.insert(QStringLiteral("name"), userInfoDialog->name()); 49 | const QString image = userInfoDialog->image(); 50 | results.insert(QStringLiteral("image"), image.isEmpty() ? QStringLiteral("file://") : image); 51 | } 52 | return QVariantList{PortalResponse::fromDialogResult(result), results}; 53 | }); 54 | } 55 | 56 | #include "moc_account.cpp" 57 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/FilePickerWindow.qml: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019-2020 Jonah Brüchert 2 | // SPDX-FileCopyrightText: 2019 Linus Jahn 3 | // 4 | // SPDX-License-Identifier: LGPL-2.0-or-later 5 | 6 | import QtQuick 7 | import QtQuick.Controls as QQC2 8 | import QtQuick.Layouts 9 | import org.kde.kirigami as Kirigami 10 | import org.kde.kirigamifilepicker 11 | 12 | /** 13 | * The FilePickerWindow type is used by the C++ MobileFileDialog class. 14 | * It should not be used from QML, 15 | * its only purpose is to create an integration with C++ using its FileChooserCallback. 16 | */ 17 | Kirigami.ApplicationWindow { 18 | id: root 19 | 20 | title: callback.title 21 | visible: false 22 | 23 | globalDrawer: PlacesGlobalDrawer { 24 | onPlaceOpenRequested: { 25 | if (filePickerLoader.item) { 26 | filePickerLoader.item.folder = place; 27 | } 28 | close() 29 | } 30 | } 31 | 32 | contextDrawer: Kirigami.ContextDrawer {} 33 | 34 | onClosing: close => { 35 | close.accepted = false 36 | 37 | // Always make sure to exit the while loop in the filechooser portal 38 | callback.cancel() 39 | close.accepted = true 40 | } 41 | 42 | FileChooserCallback { 43 | id: callback 44 | objectName: "callback" 45 | 46 | Component.onCompleted: console.log(JSON.stringify(callback)) 47 | } 48 | 49 | pageStack.initialPage: filePickerComponent 50 | 51 | Connections { 52 | target: callback 53 | 54 | function onReloadWindow() { 55 | root.pageStack.clear(); 56 | root.pageStack.push(filePickerComponent); 57 | } 58 | } 59 | 60 | Component { 61 | id: filePickerComponent 62 | 63 | FilePicker { 64 | id: filePicker 65 | 66 | onAccepted: urls => { 67 | callback.accepted(urls) 68 | } 69 | 70 | selectMultiple: callback.selectMultiple 71 | selectExisting: callback.selectExisting 72 | nameFilters: callback.nameFilters 73 | mimeTypeFilters: callback.mimeTypeFilters 74 | currentFile: callback.currentFile 75 | acceptLabel: callback.acceptLabel 76 | selectFolder: callback.selectFolder 77 | folder: callback.folder 78 | title: callback.title 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/kirigami-filepicker/declarative/dirmodel.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 Linus Jahn 2 | // SPDX-FileCopyrightText: 2019-2020 Jonah Brüchert 3 | // 4 | // SPDX-License-Identifier: LGPL-2.0-or-later 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | class KDirLister; 15 | 16 | class DirModel : public KDirSortFilterProxyModel 17 | { 18 | Q_OBJECT 19 | Q_PROPERTY(const QUrl &folder READ folder WRITE setFolder NOTIFY folderChanged) 20 | Q_PROPERTY(bool showDotFiles READ showDotFiles WRITE setShowDotFiles NOTIFY showDotFilesChanged) 21 | Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged) 22 | Q_PROPERTY(QString nameFilter READ nameFilter WRITE setNameFilter NOTIFY nameFilterChanged) 23 | Q_PROPERTY(QStringList mimeFilters READ mimeFilters WRITE setMimeFilters RESET resetMimeFilters NOTIFY mimeFiltersChanged) 24 | 25 | Q_PROPERTY(QString lastError READ lastError NOTIFY lastErrorChanged) 26 | 27 | public: 28 | enum Roles { 29 | Name = Qt::UserRole + 1, 30 | Url, 31 | IconName, 32 | IsDir, 33 | IsLink, 34 | FileSize, 35 | MimeType, 36 | IsHidden, 37 | IsReadable, 38 | IsWritable, 39 | ModificationTime, 40 | }; 41 | 42 | Q_ENUM(Roles) 43 | 44 | explicit DirModel(QObject *parent = nullptr); 45 | 46 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 47 | QHash roleNames() const override; 48 | 49 | QUrl folder() const; 50 | void setFolder(const QUrl &folder); 51 | 52 | bool showDotFiles() const; 53 | void setShowDotFiles(bool showDotFiles); 54 | 55 | bool isLoading() const; 56 | 57 | QString nameFilter() const; 58 | void setNameFilter(const QString &nameFilter); 59 | 60 | QStringList mimeFilters() const; 61 | void setMimeFilters(const QStringList &mimeFilters); 62 | void resetMimeFilters(); 63 | 64 | QString lastError() const; 65 | 66 | Q_SIGNALS: 67 | void folderChanged(); 68 | void showDotFilesChanged(); 69 | void isLoadingChanged(); 70 | void nameFilterChanged(); 71 | void mimeFiltersChanged(); 72 | 73 | void lastErrorChanged(); 74 | 75 | private: 76 | KDirModel m_dirModel; 77 | KDirLister *m_lister; 78 | 79 | QString m_lastError; 80 | }; 81 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Alexander Volkov 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #include "utils.h" 8 | 9 | #include "waylandintegration.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void Utils::setParentWindow(QWidget *w, const QString &parent_window) 19 | { 20 | if (parent_window.startsWith(QLatin1String("x11:"))) { 21 | w->setAttribute(Qt::WA_NativeWindow, true); 22 | setParentWindow(w->windowHandle(), parent_window); 23 | } 24 | if (parent_window.startsWith((QLatin1String("wayland:")))) { 25 | if (!w->window()->windowHandle()) { 26 | w->window()->winId(); // create QWindow 27 | } 28 | setParentWindow(w->window()->windowHandle(), parent_window); 29 | } 30 | } 31 | 32 | void Utils::setParentWindow(QWindow *w, const QString &parent_window) 33 | { 34 | if (parent_window.startsWith(QLatin1String("x11:"))) { 35 | KWindowSystem::setMainWindow(w, QStringView(parent_window).mid(4).toULongLong(nullptr, 16)); 36 | } 37 | if (parent_window.startsWith((QLatin1String("wayland:")))) { 38 | KWindowSystem::setMainWindow(w, parent_window.mid(strlen("wayland:"))); 39 | } 40 | } 41 | 42 | QString Utils::applicationName(const QString &appId) 43 | { 44 | QString applicationName; 45 | const QString desktopFile = appId + QStringLiteral(".desktop"); 46 | const QStringList desktopFileLocations = QStandardPaths::locateAll(QStandardPaths::ApplicationsLocation, desktopFile, QStandardPaths::LocateFile); 47 | for (const QString &location : desktopFileLocations) { 48 | QSettings settings(location, QSettings::IniFormat); 49 | settings.beginGroup(QStringLiteral("Desktop Entry")); 50 | if (settings.contains(QStringLiteral("X-GNOME-FullName"))) { 51 | applicationName = settings.value(QStringLiteral("X-GNOME-FullName")).toString(); 52 | } else { 53 | applicationName = settings.value(QStringLiteral("Name")).toString(); 54 | } 55 | 56 | if (!applicationName.isEmpty()) { 57 | break; 58 | } 59 | } 60 | 61 | // Use `appId` as a fallback in case we're unable to find actual application name 62 | if (applicationName.isEmpty()) { 63 | applicationName = appId; 64 | } 65 | 66 | return applicationName; 67 | } 68 | -------------------------------------------------------------------------------- /src/request.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #include "request.h" 10 | #include "request_debug.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | Request::Request(const QDBusObjectPath &handle, QObject *parent) 19 | : QDBusVirtualObject(parent) 20 | { 21 | auto sessionBus = QDBusConnection::sessionBus(); 22 | if (sessionBus.registerVirtualObject(handle.path(), this, QDBusConnection::VirtualObjectRegisterOption::SubPath)) { 23 | connect(this, &Request::closeRequested, this, [this, handle]() { 24 | QDBusConnection::sessionBus().unregisterObject(handle.path()); 25 | deleteLater(); 26 | }); 27 | } else { 28 | qCDebug(XdgRequestKdeRequest) << sessionBus.lastError().message(); 29 | qCDebug(XdgRequestKdeRequest) << "Failed to register request object for" << handle.path(); 30 | deleteLater(); 31 | } 32 | } 33 | 34 | bool Request::handleMessage(const QDBusMessage &message, const QDBusConnection &connection) 35 | { 36 | /* Check to make sure we're getting properties on our interface */ 37 | if (message.type() != QDBusMessage::MessageType::MethodCallMessage) { 38 | return false; 39 | } 40 | 41 | qCDebug(XdgRequestKdeRequest) << message.interface(); 42 | qCDebug(XdgRequestKdeRequest) << message.member(); 43 | qCDebug(XdgRequestKdeRequest) << message.path(); 44 | 45 | if (message.interface() == QLatin1String("org.freedesktop.impl.portal.Request")) { 46 | if (message.member() == QLatin1String("Close")) { 47 | Q_EMIT closeRequested(); 48 | connection.send(message.createReply()); 49 | } 50 | } 51 | 52 | return true; 53 | } 54 | 55 | QString Request::introspect(const QString &path) const 56 | { 57 | QString nodes; 58 | 59 | if (path.startsWith(QLatin1String("/org/freedesktop/portal/desktop/request/"))) { 60 | nodes = QStringLiteral( 61 | "" 62 | " " 63 | " " 64 | ""); 65 | } 66 | 67 | qCDebug(XdgRequestKdeRequest) << nodes; 68 | 69 | return nodes; 70 | } 71 | 72 | #include "moc_request.cpp" 73 | -------------------------------------------------------------------------------- /src/email.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2017 Jan Grulich 7 | */ 8 | 9 | #include "email.h" 10 | #include "dbushelpers.h" 11 | #include "email_debug.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | EmailPortal::EmailPortal(QObject *parent) 20 | : QDBusAbstractAdaptor(parent) 21 | { 22 | } 23 | 24 | void EmailPortal::ComposeEmail(const QDBusObjectPath &handle, 25 | const QString &app_id, 26 | const QString &window, 27 | const QVariantMap &options, 28 | const QDBusMessage &message, 29 | [[maybe_unused]] uint &replyResponse, 30 | [[maybe_unused]] QVariantMap &replyResults) 31 | { 32 | qCDebug(XdgDesktopPortalKdeEmail) << "ComposeEmail called with parameters:"; 33 | qCDebug(XdgDesktopPortalKdeEmail) << " handle: " << handle.path(); 34 | qCDebug(XdgDesktopPortalKdeEmail) << " app_id: " << app_id; 35 | qCDebug(XdgDesktopPortalKdeEmail) << " window: " << window; 36 | qCDebug(XdgDesktopPortalKdeEmail) << " options: " << options; 37 | 38 | const QStringList addresses = options.contains(QStringLiteral("address")) ? options.value(QStringLiteral("address")).toStringList() 39 | : options.value(QStringLiteral("addresses")).toStringList(); 40 | 41 | auto job = new KEMailClientLauncherJob; 42 | job->setTo(addresses); 43 | job->setCc(options.value(QStringLiteral("cc")).toStringList()); 44 | job->setBcc(options.value(QStringLiteral("bcc")).toStringList()); 45 | job->setSubject(options.value(QStringLiteral("subject")).toString()); 46 | job->setBody(options.value(QStringLiteral("body")).toString()); 47 | 48 | const QStringList attachmentStrings = options.value(QStringLiteral("attachments")).toStringList(); 49 | QList attachments; 50 | for (const QString &attachment : attachmentStrings) { 51 | attachments << QUrl(attachment); 52 | } 53 | job->setAttachments(attachments); 54 | 55 | job->start(); 56 | delayReply(message, job, this, [](KJob *job) { 57 | return QVariantList{job->error() ? 2u : 0u, QVariantMap{}}; 58 | }); 59 | } 60 | 61 | #include "moc_email.cpp" 62 | -------------------------------------------------------------------------------- /src/inputcapturebarrier.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 3 | SPDX-FileCopyrightText: 2024 David Redondo 4 | */ 5 | 6 | #include "inputcapturebarrier.h" 7 | 8 | #include 9 | 10 | std::variant> checkAndMakeBarrier(int x1, int y1, int x2, int y2, const QList &screenGeometries) 11 | { 12 | // This function checks and allows barriers that are 13 | // - fully on a edge of a screen 14 | // - not next to any other screen 15 | 16 | if (x1 != x2 && y1 != y2) { 17 | return BarrierFailureReason::Diagonal; 18 | } 19 | 20 | bool foundScreen = false; 21 | 22 | bool transpose = false; 23 | if (x1 != x2) { 24 | std::swap(x1, y1); 25 | std::swap(x2, y2); 26 | transpose = true; 27 | } 28 | if (y1 > y2) { 29 | std::swap(y1, y2); 30 | } 31 | bool onRightEdge = false; 32 | for (auto geometry : screenGeometries) { 33 | if (transpose) { 34 | geometry = geometry.transposed(); 35 | geometry.moveTo(geometry.y(), geometry.x()); 36 | } 37 | 38 | if (y1 > geometry.bottom() || geometry.y() > y2) { 39 | continue; 40 | } 41 | if (x1 == geometry.x() || x1 == geometry.x() + geometry.width()) { 42 | if (y1 == geometry.y() && y2 == geometry.bottom() && !foundScreen) { 43 | foundScreen = true; 44 | onRightEdge = x1 == geometry.x() + geometry.width(); 45 | } else { 46 | // the edge one or doesnt fill the edge of this screen or it fills the edge of some other screen 47 | // that is next to this screen; either way we dont allow it 48 | return BarrierFailureReason::BetweenScreensOrDoesNotFill; 49 | } 50 | } 51 | } 52 | 53 | if (!foundScreen) { 54 | return BarrierFailureReason::NotOnEdge; 55 | } 56 | if (onRightEdge) { 57 | // Barriers on right/top edge will have a coordinate of just past the screen (on 1920 pixel wide screen at 0x0 1920) 58 | // We send coordinates on the screen to KWin which is consistent with the other case which sends the coordinate 59 | // of the first row/column of pixels 60 | --x1; 61 | --x2; 62 | } 63 | if (transpose) { 64 | std::swap(x1, y1); 65 | std::swap(x2, y2); 66 | } 67 | return QPair{{x1, y1}, {x2, y2}}; 68 | } 69 | -------------------------------------------------------------------------------- /src/AccessDialog.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | */ 4 | 5 | import QtQuick 6 | import QtQuick.Controls as QQC2 7 | import QtQuick.Layouts 8 | import org.kde.kirigami as Kirigami 9 | 10 | PortalDialog { 11 | id: root 12 | 13 | property alias body: bodyLabel.text 14 | property string acceptLabel 15 | property string rejectLabel 16 | property var choices 17 | property var selectedChoices: new Object() 18 | 19 | width: contentWidth 20 | height: contentHeight 21 | 22 | QQC2.Label { 23 | id: bodyLabel 24 | Layout.fillWidth: true 25 | wrapMode: Text.WordWrap 26 | } 27 | 28 | Kirigami.FormLayout { 29 | Layout.fillWidth: true 30 | visible: root.choices?.length > 0 31 | Repeater { 32 | model: root.choices 33 | delegate: Loader { 34 | Kirigami.FormData.label: modelData.label 35 | sourceComponent: modelData.choices.length == 0 ? checkBox : comboBox 36 | Component { 37 | id: checkBox 38 | QQC2.CheckBox { 39 | Kirigami.FormData.label: modelData.label 40 | checked: modelData.initialChoiceId === "true" 41 | onToggled: { 42 | root.selectedChoices[modelData.id] = checked ? "true" : "false" 43 | } 44 | } 45 | } 46 | Component { 47 | id: comboBox 48 | QQC2.ComboBox { 49 | model: modelData.choices 50 | textRole: "value" 51 | valueRole: "id" 52 | onActivated: root.selectedChoices[modelData.id] = currentValue 53 | Component.onCompleted: currentIndex = indexOfValue(modelData.initialChoiceId) 54 | } 55 | } 56 | Component.onCompleted: root.selectedChoices[modelData.id] = modelData.initialChoiceId 57 | } 58 | } 59 | } 60 | 61 | 62 | 63 | standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 64 | 65 | Component.onCompleted: { 66 | if (root.acceptLabel.length > 0) { 67 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Ok).text = Qt.binding(() => root.acceptLabel); 68 | } 69 | if (root.rejectLabel.length > 0) { 70 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Cancel).text = Qt.binding(() => root.rejectLabel); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/xdg-desktop-portal-kde.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "../version.h" 19 | #include "debug.h" 20 | #include "desktopportal.h" 21 | 22 | #include 23 | 24 | using namespace Qt::StringLiterals; 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | // Do not try to reconnect to the compositor as KWayland can't handle that 29 | // Reconsider enabling when we do not use KWayland anymore 30 | qunsetenv("QT_WAYLAND_RECONNECT"); 31 | QCoreApplication::setAttribute(Qt::AA_DisableSessionManager); 32 | QApplication a(argc, argv); 33 | a.setQuitOnLastWindowClosed(false); 34 | a.setQuitLockEnabled(false); 35 | 36 | // Guard against an app closing the reading end when the clipboard portal writes current clipboard contents 37 | signal(SIGPIPE, SIG_IGN); 38 | 39 | QCommandLineParser parser; 40 | QCommandLineOption replaceOption(u"replace"_s, u"Replace running instance"_s); 41 | parser.addOption(replaceOption); 42 | 43 | KAboutData about(QStringLiteral("xdg-desktop-portal-kde"), QString(), QStringLiteral(XDPK_VERSION_STRING)); 44 | about.setDesktopFileName(QStringLiteral("org.freedesktop.impl.portal.desktop.kde")); 45 | about.setupCommandLine(&parser); 46 | KAboutData::setApplicationData(about); 47 | 48 | parser.process(a); 49 | about.processCommandLine(&parser); 50 | 51 | KCrash::initialize(); 52 | 53 | const auto dbusQueueOption = parser.isSet(replaceOption) ? QDBusConnectionInterface::ReplaceExistingService : QDBusConnectionInterface::DontQueueService; 54 | 55 | QDBusConnection sessionBus = QDBusConnection::sessionBus(); 56 | if (sessionBus.interface()->registerService(u"org.freedesktop.impl.portal.desktop.kde"_s, dbusQueueOption, QDBusConnectionInterface::AllowReplacement)) { 57 | DesktopPortal *desktopPortal = new DesktopPortal(&a); 58 | if (sessionBus.registerObject(QStringLiteral("/org/freedesktop/portal/desktop"), desktopPortal, QDBusConnection::ExportAdaptors)) { 59 | qCDebug(XdgDesktopPortalKde) << "Desktop portal registered successfully"; 60 | } else { 61 | qCDebug(XdgDesktopPortalKde) << "Failed to register desktop portal"; 62 | } 63 | } else { 64 | qCDebug(XdgDesktopPortalKde) << "Failed to register org.freedesktop.impl.portal.desktop.kde service"; 65 | return 1; 66 | } 67 | 68 | return a.exec(); 69 | } 70 | -------------------------------------------------------------------------------- /src/print.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Red Hat Inc 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | * 6 | * SPDX-FileCopyrightText: 2016 Jan Grulich 7 | */ 8 | 9 | #ifndef XDG_DESKTOP_PORTAL_KDE_PRINT_H 10 | #define XDG_DESKTOP_PORTAL_KDE_PRINT_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class QDBusMessage; 18 | 19 | class PrintPortal : public QDBusAbstractAdaptor 20 | { 21 | Q_OBJECT 22 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.Print") 23 | public: 24 | explicit PrintPortal(QObject *parent); 25 | 26 | public Q_SLOTS: 27 | uint Print(const QDBusObjectPath &handle, 28 | const QString &app_id, 29 | const QString &parent_window, 30 | const QString &title, 31 | const QDBusUnixFileDescriptor &fd, 32 | const QVariantMap &options, 33 | QVariantMap &results); 34 | 35 | void PreparePrint(const QDBusObjectPath &handle, 36 | const QString &app_id, 37 | const QString &parent_window, 38 | const QString &title, 39 | const QVariantMap &settings, 40 | const QVariantMap &page_setup, 41 | const QVariantMap &options, 42 | const QDBusMessage &message, 43 | uint &replyResponse, 44 | QVariantMap &replyResults); 45 | 46 | private: 47 | QMap m_printers; 48 | 49 | bool cupsAvailable(); 50 | QStringList printArguments(const QPrinter *printer, bool useCupsOptions, const QString &version, QPageLayout::Orientation documentOrientation); 51 | QStringList destination(const QPrinter *printer, const QString &version); 52 | QStringList copies(const QPrinter *printer, const QString &version); 53 | QStringList jobname(const QPrinter *printer, const QString &version); 54 | QStringList cupsOptions(const QPrinter *printer, QPageLayout::Orientation documentOrientation); 55 | QStringList pages(const QPrinter *printer, bool useCupsOptions, const QString &version); 56 | QStringList optionMedia(const QPrinter *printer); 57 | QString mediaPaperSource(const QPrinter *printer); 58 | QStringList optionOrientation(const QPrinter *printer, QPageLayout::Orientation documentOrientation); 59 | QStringList optionDoubleSidedPrinting(const QPrinter *printer); 60 | QStringList optionPageOrder(const QPrinter *printer); 61 | QStringList optionCollateCopies(const QPrinter *printer); 62 | QStringList optionPageMargins(const QPrinter *printer); 63 | QStringList optionCupsProperties(const QPrinter *printer); 64 | }; 65 | 66 | #endif // XDG_DESKTOP_PORTAL_KDE_PRINT_H 67 | -------------------------------------------------------------------------------- /src/notificationinhibition.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Kai Uwe Broulik 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #include "notificationinhibition.h" 8 | #include "notificationinhibition_debug.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static const auto s_notificationService = QStringLiteral("org.freedesktop.Notifications"); 18 | static const auto s_notificationPath = QStringLiteral("/org/freedesktop/Notifications"); 19 | static const auto s_notificationInterface = QStringLiteral("org.freedesktop.Notifications"); 20 | 21 | NotificationInhibition::NotificationInhibition(const QString &appId, const QString &reason, QObject *parent) 22 | : QObject(parent) 23 | { 24 | QDBusMessage msg = QDBusMessage::createMethodCall(s_notificationService, s_notificationPath, s_notificationInterface, QStringLiteral("Inhibit")); 25 | msg.setArguments({appId, reason, QVariantMap()}); 26 | 27 | QPointer guardedThis(this); 28 | 29 | QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(msg); 30 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall); 31 | connect(watcher, &QDBusPendingCallWatcher::finished, [guardedThis, appId, reason](QDBusPendingCallWatcher *watcher) { 32 | QDBusPendingReply reply = *watcher; 33 | watcher->deleteLater(); 34 | 35 | if (reply.isError()) { 36 | qCDebug(XdgDesktopPortalKdeNotificationInhibition) << "Failed to inhibit: " << reply.error().message(); 37 | return; 38 | } 39 | 40 | const auto cookie = reply.value(); 41 | 42 | // In case the inhibition was revoked again before the async DBus reply arrived 43 | if (guardedThis) { 44 | qCDebug(XdgDesktopPortalKdeNotificationInhibition) << "Inhibiting notifications for" << appId << "with reason" << reason << "and cookie" << cookie; 45 | guardedThis->m_cookie = cookie; 46 | } else { 47 | uninhibit(cookie); 48 | } 49 | }); 50 | } 51 | 52 | NotificationInhibition::~NotificationInhibition() 53 | { 54 | if (m_cookie) { 55 | uninhibit(m_cookie); 56 | } 57 | } 58 | 59 | void NotificationInhibition::uninhibit(uint cookie) 60 | { 61 | qCDebug(XdgDesktopPortalKdeNotificationInhibition) << "Removing inhibition with cookie" << cookie; 62 | QDBusMessage msg = QDBusMessage::createMethodCall(s_notificationService, s_notificationPath, s_notificationInterface, QStringLiteral("UnInhibit")); 63 | msg.setArguments({cookie}); 64 | QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); 65 | } 66 | 67 | #include "moc_notificationinhibition.cpp" 68 | -------------------------------------------------------------------------------- /src/ScreenshotDialog.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | import QtQuick 8 | import QtQuick.Layouts 9 | import QtQuick.Controls as QQC2 10 | import org.kde.kirigami as Kirigami 11 | 12 | PortalDialog { 13 | id: root 14 | 15 | property alias screenshotType: areaCombo.currentIndex 16 | property alias screenshotTypesModel: areaCombo.model 17 | property alias screenshotImage: screenshot.source 18 | property alias withCursor: hasCursor.checked 19 | property alias withBorders: hasWindowBorders.checked 20 | property QtObject app 21 | 22 | title: i18n("Request Screenshot") 23 | iconName: "preferences-system-windows-effect-screenshot" 24 | acceptable: screenshot.valid 25 | 26 | width: Kirigami.Units.gridUnit * 28 27 | height: Kirigami.Units.gridUnit * 30 28 | 29 | Kirigami.FormLayout { 30 | Kirigami.Heading { 31 | text: i18n("Capture Mode") 32 | } 33 | QQC2.ComboBox { 34 | id: areaCombo 35 | Kirigami.FormData.label: i18n("Area:") 36 | textRole: "display" 37 | } 38 | QQC2.SpinBox { 39 | id: delayTime 40 | Kirigami.FormData.label: i18n("Delay:") 41 | from: 0 42 | to: 60 43 | stepSize: 1 44 | textFromValue: (value, locale) => i18np("%1 second", "%1 seconds", value) 45 | valueFromText: (text, locale) => parseInt(text); 46 | } 47 | 48 | Kirigami.Heading { 49 | text: i18n("Content Options") 50 | } 51 | QQC2.CheckBox { 52 | id: hasCursor 53 | text: i18n("Include cursor pointer") 54 | checked: true 55 | } 56 | QQC2.CheckBox { 57 | id: hasWindowBorders 58 | text: i18n("Include window borders") 59 | enabled: areaCombo.currentIndex === 2 60 | checked: true 61 | } 62 | 63 | Kirigami.Icon { 64 | id: screenshot 65 | Layout.fillWidth: true 66 | Layout.fillHeight: true 67 | } 68 | } 69 | 70 | standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 71 | 72 | Component.onCompleted: { 73 | dialogButtonBox.standardButton(QQC2.DialogButtonBox.Ok).text = i18n("Save") 74 | } 75 | 76 | actions: [ 77 | QQC2.Action { 78 | readonly property Timer takeTimer: Timer { 79 | repeat: false 80 | interval: delayTime.value * 1000 81 | onTriggered: root.app.takeScreenshotInteractive() 82 | } 83 | text: i18n("Take") 84 | enabled: !takeTimer.running 85 | onTriggered: takeTimer.restart() 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /src/PipeWireLayout.qml: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.0-or-later 2 | // SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez 3 | // SPDX-FileCopyrightText: 2025 Harald Sitter 4 | 5 | pragma ComponentBehavior: Bound 6 | 7 | import QtQuick 8 | import org.kde.kirigami as Kirigami 9 | import org.kde.taskmanager as TaskManager 10 | 11 | Kirigami.CardsLayout { 12 | id: root 13 | 14 | required property ScreenChooserDialogTemplate dialog 15 | required property var model 16 | 17 | readonly property alias view: view 18 | 19 | uniformCellWidths: true 20 | 21 | Repeater { 22 | id: view 23 | 24 | model: root.model 25 | 26 | PipeWireDelegate { 27 | id: delegate 28 | 29 | required property int index 30 | required property var model 31 | 32 | function selectAndAccept(): void { 33 | root.dialog.clearSelection() 34 | view.model.setData(view.model.index(model.row, 0), Qt.Checked, Qt.CheckStateRole) 35 | root.dialog.dialogButtonBox.accepted() 36 | } 37 | 38 | checkable: root.dialog.multiple 39 | itemName : model.display ?? "" 40 | iconSource : model.decoration ?? "" 41 | itemDescription : model.description ?? "" 42 | synthetic: model.isSynthetic ?? false 43 | exclusive: false 44 | autoExclusive: exclusive 45 | checked: model.checked === Qt.Checked 46 | nodeId: waylandItem.nodeId 47 | 48 | activeFocusOnTab: true 49 | highlighted: activeFocus 50 | 51 | Accessible.role: root.dialog.multiple ? Accessible.CheckBox : Accessible.Button 52 | 53 | TaskManager.ScreencastingRequest { 54 | id: waylandItem 55 | outputName: delegate.model.name 56 | uuid: delegate.model.Uuid 57 | } 58 | 59 | // Only active if this is a multi-select dialog 60 | onToggled: { 61 | const to = model.checked !== Qt.Checked ? Qt.Checked : Qt.Unchecked; 62 | view.model.setData(view.model.index(model.row, 0), to, Qt.CheckStateRole) 63 | } 64 | 65 | // If this is isn't a multi-select dialog, accept on click 66 | // since the cards are functioning as buttons 67 | onClicked: { 68 | if (!root.dialog.multiple) { 69 | selectAndAccept() 70 | } 71 | } 72 | 73 | // If this is a multi-select dialog, let people choose just 74 | // one thing quickly by double-clicking 75 | onDoubleClicked: { 76 | if (root.dialog.multiple) { 77 | selectAndAccept() 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/dbushelpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2019 Red Hat Inc 3 | * SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez 4 | * 5 | * SPDX-License-Identifier: LGPL-2.0-or-later 6 | * 7 | * SPDX-FileCopyrightText: 2018-2019 Jan Grulich 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "quickdialog.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "utils.h" 22 | 23 | // not an enum class so it can convert to uint implicitelly when returning from a dbus handling slot 24 | namespace PortalResponse 25 | { 26 | enum Response : unsigned { 27 | Success = 0, 28 | Cancelled = 1, 29 | OtherError = 2 30 | }; 31 | constexpr inline Response fromDialogResult(DialogResult r) 32 | { 33 | return r == DialogResult::Accepted ? Success : Cancelled; 34 | } 35 | constexpr inline Response fromDialogCode(QDialog::DialogCode c) 36 | { 37 | return c == QDialog::Accepted ? Success : Cancelled; 38 | } 39 | } 40 | 41 | /// a{sa{sv}} 42 | using VariantMapMap = QMap>; 43 | 44 | /// sa{sv} 45 | using Shortcut = QPair; 46 | 47 | /// a(sa{sv}) 48 | using Shortcuts = QList; 49 | 50 | // as 51 | using Permissions = QStringList; 52 | 53 | // a{sas} 54 | using AppIdPermissionsMap = QMap; 55 | 56 | Q_DECLARE_METATYPE(VariantMapMap) 57 | Q_DECLARE_METATYPE(Shortcuts) 58 | 59 | struct Choice { 60 | Q_GADGET 61 | Q_PROPERTY(QString id MEMBER id CONSTANT) 62 | Q_PROPERTY(QString value MEMBER value CONSTANT) 63 | public: 64 | QString id; 65 | QString value; 66 | }; 67 | using Choices = QList; 68 | QDBusArgument &operator<<(QDBusArgument &arg, const Choice &choice); 69 | const QDBusArgument &operator>>(const QDBusArgument &arg, Choice &choice); 70 | 71 | struct Option { 72 | Q_GADGET 73 | Q_PROPERTY(QString id MEMBER id CONSTANT) 74 | Q_PROPERTY(QString label MEMBER label CONSTANT) 75 | Q_PROPERTY(Choices choices MEMBER choices CONSTANT) 76 | Q_PROPERTY(QString initialChoiceId MEMBER initialChoiceId CONSTANT) 77 | public: 78 | QString id; 79 | QString label; 80 | Choices choices; 81 | QString initialChoiceId; 82 | }; 83 | using OptionList = QList