summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMavridis Philippe <mavridisf@gmail.com>2024-02-01 16:44:26 +0200
committerMavridis Philippe <mavridisf@gmail.com>2024-02-01 16:53:20 +0200
commit4acb982e2d5b82ddfe603414665256323a25ad5e (patch)
treeb137112d00a4340f0cf25b64ebe5926f505c3de2
downloadxdg-desktop-portal-tde-4acb982e2d5b82ddfe603414665256323a25ad5e.tar.gz
xdg-desktop-portal-tde-4acb982e2d5b82ddfe603414665256323a25ad5e.zip
Initial commit
Adds implementation of FileChooser interface Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
-rw-r--r--.gitignore4
-rw-r--r--CMakeLists.txt54
-rw-r--r--ConfigureChecks.cmake23
-rw-r--r--config.h.cmake6
-rw-r--r--interfaces/CMakeLists.txt45
-rw-r--r--interfaces/filechooser.xml32
-rw-r--r--interfaces/org.freedesktop.impl.portal.desktop.tde.service.cmake3
-rw-r--r--interfaces/tde.portal4
-rw-r--r--interfaces/xdg-desktop-portal-tde.desktop.cmake5
-rw-r--r--src/CMakeLists.txt42
-rw-r--r--src/file_chooser_portal.cpp269
-rw-r--r--src/file_chooser_portal.h114
-rw-r--r--src/main.cpp65
-rw-r--r--src/portal.cpp37
-rw-r--r--src/portal.h48
-rw-r--r--src/portal_service.cpp75
-rw-r--r--src/portal_service.h47
-rw-r--r--src/util.h126
18 files changed, 999 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9d4e3ee
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.~
+*~
+build
+*.kdev*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..93a23f2
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,54 @@
+################################################################################
+# XDG Desktop Portal implementation for TDE #
+# Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com> #
+# #
+# Improvements and feedback are welcome! #
+# This software is licensed under the terms of the GNU GPL v3 license. #
+################################################################################
+
+cmake_minimum_required( VERSION 3.1 )
+
+project( xdg-desktop-portal-tde )
+
+### Required modules ###########################################################
+include( FindPkgConfig )
+include( CheckFunctionExists )
+include( CheckSymbolExists )
+include( CheckIncludeFile )
+include( CheckLibraryExists )
+include( CheckCSourceCompiles )
+include( CheckCXXSourceCompiles )
+
+### TDE macros #################################################################
+include( TDEMacros )
+tde_set_project_version( )
+
+include( TDESetupPaths )
+tde_setup_paths( )
+
+### Optional support ###########################################################
+# option( WITH_ALL_OPTIONS "Enable all optional support" OFF )
+
+### Modules to build ###########################################################
+option( BUILD_ALL "Build all" ON )
+option( BUILD_DOC "Build documentation" ${BUILD_ALL} )
+# option( BUILD_TRANSLATIONS "Build translations" ${BUILD_ALL} )
+
+### Configure checks ###########################################################
+include( ConfigureChecks.cmake )
+
+### Compiler settings ##########################################################
+add_definitions( -DHAVE_CONFIG_H )
+
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TQT_CXX_FLAGS}" )
+set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined" )
+set( CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined" )
+
+### Add subdirectories #########################################################
+add_subdirectory( src )
+add_subdirectory( interfaces )
+tde_conditional_add_project_docs( BUILD_DOC )
+# tde_conditional_add_project_translations( BUILD_TRANSLATIONS )
+
+### Write configuration ########################################################
+configure_file( config.h.cmake config.h @ONLY ) \ No newline at end of file
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
new file mode 100644
index 0000000..8a2c606
--- /dev/null
+++ b/ConfigureChecks.cmake
@@ -0,0 +1,23 @@
+################################################################################
+# XDG Desktop Portal implementation for TDE #
+# Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com> #
+# #
+# Improvements and feedback are welcome! #
+# This software is licensed under the terms of the GNU GPL v3 license. #
+################################################################################
+
+find_package( TQt )
+find_package( TDE )
+
+tde_setup_architecture_flags( )
+
+include( TestBigEndian )
+test_big_endian( WORDS_BIGENDIAN )
+
+tde_setup_largefiles( )
+
+if( WITH_GCC_VISIBILITY )
+ tde_setup_gcc_visibility( )
+endif( WITH_GCC_VISIBILITY )
+
+tde_setup_dbus( dbus-1-tqt ) \ No newline at end of file
diff --git a/config.h.cmake b/config.h.cmake
new file mode 100644
index 0000000..2031ece
--- /dev/null
+++ b/config.h.cmake
@@ -0,0 +1,6 @@
+// Defined if you have fvisibility and fvisibility-inlines-hidden support.
+#cmakedefine __KDE_HAVE_GCC_VISIBILITY 1
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#cmakedefine WORDS_BIGENDIAN @WORDS_BIGENDIAN@ \ No newline at end of file
diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt
new file mode 100644
index 0000000..df05b75
--- /dev/null
+++ b/interfaces/CMakeLists.txt
@@ -0,0 +1,45 @@
+################################################################################
+# XDG Desktop Portal implementation for TDE #
+# Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com> #
+# #
+# Improvements and feedback are welcome! #
+# This software is licensed under the terms of the GNU GPL v3 license. #
+################################################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${DBUS_TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${DBUS_TQT_LIBRARY_DIRS}
+)
+
+set(filechooser_HDRS filechooserInterface.h filechooserProxy.h introspectableInterface.h)
+set(filechooser_SRCS filechooserInterface.cpp filechooserProxy.cpp introspectableInterface.cpp)
+
+add_custom_command(
+ OUTPUT ${filechooser_HDRS} ${filechooser_SRCS}
+ COMMAND ${DBUSXML2QT3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/filechooser.xml
+ DEPENDS filechooser.xml
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+tde_add_library(portalinterfaces STATIC_PIC AUTOMOC
+ SOURCES ${filechooser_SRCS}
+ LINK ${DBUS_TQT_LIBRARIES}
+)
+
+configure_file(org.freedesktop.impl.portal.desktop.tde.service.cmake
+ org.freedesktop.impl.portal.desktop.tde.service @ONLY)
+
+configure_file(xdg-desktop-portal-tde.desktop.cmake
+ xdg-desktop-portal-tde.desktop @ONLY)
+
+install(FILES tde.portal DESTINATION ${SHARE_INSTALL_PREFIX}/xdg-desktop-portal/portals)
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.impl.portal.desktop.tde.service
+ DESTINATION ${DBUS_SESSION_DIRECTORY})
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xdg-desktop-portal-tde.desktop
+ DESTINATION ${SHARE_INSTALL_PREFIX}/applications) \ No newline at end of file
diff --git a/interfaces/filechooser.xml b/interfaces/filechooser.xml
new file mode 100644
index 0000000..da6bed2
--- /dev/null
+++ b/interfaces/filechooser.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+ <interface name="org.freedesktop.impl.portal.FileChooser">
+ <method name="OpenFile">
+ <arg name="handle" type="o" direction="in" />
+ <arg name="app_id" type="s" direction="in" />
+ <arg name="parent_window" type="s" direction="in" />
+ <arg name="title" type="s" direction="in" />
+ <arg name="options" type="a{sv}" direction="in" />
+ <arg name="response" type="u" direction="out" />
+ <arg name="results" type="a{sv}" direction="out" />
+ </method>
+ <method name="SaveFile">
+ <arg name="handle" type="o" direction="in" />
+ <arg name="app_id" type="s" direction="in" />
+ <arg name="parent_window" type="s" direction="in" />
+ <arg name="title" type="s" direction="in" />
+ <arg name="options" type="a{sv}" direction="in" />
+ <arg name="response" type="u" direction="out" />
+ <arg name="results" type="a{sv}" direction="out" />
+ </method>
+ <method name="SaveFiles">
+ <arg name="handle" type="o" direction="in" />
+ <arg name="app_id" type="s" direction="in" />
+ <arg name="parent_window" type="s" direction="in" />
+ <arg name="title" type="s" direction="in" />
+ <arg name="options" type="a{sv}" direction="in" />
+ <arg name="response" type="u" direction="out" />
+ <arg name="results" type="a{sv}" direction="out" />
+ </method>
+ </interface>
+</node> \ No newline at end of file
diff --git a/interfaces/org.freedesktop.impl.portal.desktop.tde.service.cmake b/interfaces/org.freedesktop.impl.portal.desktop.tde.service.cmake
new file mode 100644
index 0000000..eb697a1
--- /dev/null
+++ b/interfaces/org.freedesktop.impl.portal.desktop.tde.service.cmake
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.impl.portal.desktop.tde
+Exec=@LIBEXEC_INSTALL_DIR@/xdg-desktop-portal-tde \ No newline at end of file
diff --git a/interfaces/tde.portal b/interfaces/tde.portal
new file mode 100644
index 0000000..5bcf81a
--- /dev/null
+++ b/interfaces/tde.portal
@@ -0,0 +1,4 @@
+[portal]
+DBusName=org.freedesktop.impl.portal.desktop.tde
+Interfaces=org.freedesktop.impl.portal.FileChooser
+UseIn=Trinity
diff --git a/interfaces/xdg-desktop-portal-tde.desktop.cmake b/interfaces/xdg-desktop-portal-tde.desktop.cmake
new file mode 100644
index 0000000..267f91d
--- /dev/null
+++ b/interfaces/xdg-desktop-portal-tde.desktop.cmake
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Name=Portal
+NoDisplay=true
+Exec=@LIBEXEC_INSTALL_DIR@/xdg-desktop-portal-tde \ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..afcd9fd
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,42 @@
+################################################################################
+# XDG Desktop Portal implementation for TDE #
+# Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com> #
+# #
+# Improvements and feedback are welcome! #
+# This software is licensed under the terms of the GNU GPL v3 license. #
+################################################################################
+
+include_directories(
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+ ${DBUS_TQT_INCLUDE_DIRS}
+ ${CMAKE_BINARY_DIR}/interfaces
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+ ${DBUS_TQT_LIBRARY_DIRS}
+ ${CMAKE_BINARY_DIR}/interfaces
+)
+
+tde_add_executable(
+ xdg-desktop-portal-tde AUTOMOC
+
+ SOURCES
+ main.cpp
+ portal_service.cpp
+ file_chooser_portal.cpp
+
+ LINK
+ tdecore-shared
+ tdeio-shared
+ ${DBUS_TQT_LIBRARIES}
+ portalinterfaces-static
+
+ DESTINATION ${LIBEXEC_INSTALL_DIR}
+)
+
+# kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/file_chooser_portal.cpp b/src/file_chooser_portal.cpp
new file mode 100644
index 0000000..1d037ec
--- /dev/null
+++ b/src/file_chooser_portal.cpp
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+// TQt
+#include <tqregexp.h>
+#include <tqdbusobjectpath.h>
+
+// TDE
+#include <tdefiledialog.h>
+#include <kpushbutton.h>
+#include <twin.h>
+#include <kdebug.h>
+
+// Portal
+#include "file_chooser_portal.h"
+#include "file_chooser_portal.moc"
+#include "util.h"
+
+#define OPTION_VALID(opt, sig) \
+ options.keys().contains(opt) && check_variant(options[opt], sig)
+
+
+TDEFileChooserPortal::TDEFileChooserPortal(TQT_DBusConnection &connection)
+ : m_connection(connection)
+{}
+
+TDEFileChooserPortal::~TDEFileChooserPortal()
+{}
+
+bool TDEFileChooserPortal::OpenFile(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error)
+{
+ FileDialogOpts opts;
+
+ opts.caption = title;
+
+ if (OPTION_VALID("accept_label", "s"))
+ opts.okButtonText = options["accept_label"].value.toString();
+
+ if (OPTION_VALID("directory", "b"))
+ opts.directory = options["directory"].value.toBool();
+
+ if (OPTION_VALID("multiple", "b"))
+ opts.multiple = options["multiple"].value.toBool();
+
+ if (OPTION_VALID("modal", "b"))
+ opts.modal = options["modal"].value.toBool();
+
+ if (OPTION_VALID("filters", "a(sa(us))"))
+ opts.filters = parseFilterList(options["filters"], options["current_filter"]);
+
+ opts.windowId = parseWindowId(parent_window);
+
+ return execFileDialog(opts, handle, response, results, error);
+}
+
+bool TDEFileChooserPortal::SaveFile(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error)
+{
+ FileDialogOpts opts;
+
+ opts.caption = title;
+
+ if (OPTION_VALID("accept_label", "s"))
+ opts.okButtonText = options["accept_label"].value.toString();
+
+ if (OPTION_VALID("directory", "b"))
+ opts.directory = options["directory"].value.toBool();
+
+ if (OPTION_VALID("multiple", "b"))
+ opts.multiple = options["multiple"].value.toBool();
+
+ if (OPTION_VALID("modal", "b"))
+ opts.modal = options["modal"].value.toBool();
+
+ if (OPTION_VALID("filters", "a(sa(us))"))
+ opts.filters = parseFilterList(options["filters"], options["current_filter"]);
+
+ if (OPTION_VALID("current_folder", "ay"))
+ opts.startDir = bytelist_to_string(options["current_folder"].value.toList().toByteList());
+
+ if (OPTION_VALID("current_name", "s"))
+ opts.startName = options["current_name"].value.toString();
+
+ opts.windowId = parseWindowId(parent_window);
+
+ return execFileDialog(opts, handle, response, results, error);
+}
+
+bool TDEFileChooserPortal::SaveFiles(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error)
+{
+ return false;
+}
+
+void TDEFileChooserPortal::handleMethodReply(const TQT_DBusMessage &reply)
+{
+ m_connection.send(reply);
+}
+
+bool TDEFileChooserPortal::execFileDialog(FileDialogOpts options,
+ const TQT_DBusObjectPath& handle,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error)
+{
+ KFileDialog *dialog = new KFileDialog(options.startDir, TQString::null,
+ nullptr, "xdg-tde-file-chooser",
+ options.modal);
+ uint mode = KFile::LocalOnly;
+ if (options.savingMode)
+ {
+ dialog->setOperationMode(KFileDialog::Saving);
+ }
+ else {
+ mode |= KFile::ExistingOnly;
+ }
+ dialog->setMode(mode | options.mode());
+
+ if (!options.caption.isNull())
+ dialog->setPlainCaption(options.caption);
+
+ if (!options.okButtonText.isNull())
+ dialog->okButton()->setText(options.okButtonText);
+
+ if (!options.filters.isNull())
+ dialog->setFilter(options.filters);
+
+ dialog->setSelection(options.startName);
+
+ if (options.windowId > 0) KWin::setMainWindow(dialog, options.windowId);
+
+ if (dialog->exec() == TQDialog::Accepted)
+ {
+ response = 0;
+ TQT_DBusDataList urls = kurl_list_to_datalist(dialog->selectedURLs());
+ TQT_DBusVariant var = TQT_DBusData::fromList(urls).getAsVariantData().toVariant();
+ results.insert("uris", var);
+ }
+ else response = 1;
+ return true;
+}
+
+WId TDEFileChooserPortal::parseWindowId(const TQString data)
+{
+ if (!data.startsWith("x11:"))
+ {
+ kdWarning() << "[FileChooser] Window Identifiers are currently only "
+ << "supported for X11. Created dialog will be parentless."
+ << endl;
+ return 0;
+ }
+
+ bool ok;
+ WId wid = data.mid(4).toInt(&ok, 16);
+ return ok ? wid : 0;
+}
+
+TQString TDEFileChooserPortal::parseFilter(const TQT_DBusData data)
+{
+ TQStringList patternList;
+
+ TQValueList<TQT_DBusData> filterData = data.toStruct();
+
+ TQString label = filterData[0].toString();
+ TQValueList<TQT_DBusData> patterns = filterData[1].toTQValueList();
+
+ TQValueList<TQT_DBusData>::iterator fp;
+ for (fp = patterns.begin(); fp != patterns.end(); ++fp)
+ {
+ TQValueList<TQT_DBusData> patternData = (*fp).toStruct();
+ bool isMime = (patternData[0].toUInt32() == 1);
+ if (isMime) {
+ // KFileDialog cannot handle both a mime and a simple
+ // extension filter, so in case we get a mimetype,
+ // we just get the associated extensions from the
+ // MIME system
+ TQString mime = patternData[1].toString();
+ patternList += KMimeType::mimeType(mime)->patterns();
+ }
+ else {
+ TQString patternString = patternData[1].toString();
+
+ // Regex patterns like *.[hH][tT][mM][lL] are unnecessary for us
+ // and causes a problem with the save dialog's extension autoselection
+ TQString finalPattern = patternString;
+ if (TQRegExp("[*.](?:[[](?:[A-Za-z]{2})[]])+").search(patternString) != -1)
+ {
+ finalPattern = "*.";
+ int pos = patternString.find('[');
+ while (pos != -1)
+ {
+ finalPattern += patternString[pos + 1];
+ pos = patternString.find('[', patternString.find(']', pos));
+ }
+ }
+ patternList += finalPattern;
+ }
+ }
+
+ TQString patternString = patternList.join(" ");
+
+ return TQString("%1|%2 (%3)").arg(patternString, label, patternString);
+}
+
+TQString TDEFileChooserPortal::parseFilterList(const TQT_DBusVariant filterData,
+ const TQT_DBusVariant currentFilterData)
+{
+ TQStringList filterList;
+ TQValueList<TQT_DBusData> filters = filterData.value.toTQValueList();
+ if (filters.count() > 0) {
+ TQValueList<TQT_DBusData>::iterator f;
+ for (f = filters.begin(); f != filters.end(); ++f)
+ filterList += parseFilter((*f));
+ }
+
+ if (check_variant(currentFilterData, "(sa(us))"))
+ {
+ TQString currentFilter = parseFilter(currentFilterData.value);
+ if (filterList.contains(currentFilter))
+ {
+ // We have no way to affect the filter selection of the dialog,
+ // so we just move the current filter to the top of the list
+ // to get it selected automatically
+ filterList.remove(currentFilter);
+ filterList.prepend(currentFilter);
+ }
+ }
+
+ return filterList.join("\n");
+}
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/file_chooser_portal.h b/src/file_chooser_portal.h
new file mode 100644
index 0000000..375b7c8
--- /dev/null
+++ b/src/file_chooser_portal.h
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+#ifndef __FILE_CHOOSER_PORTAL_H
+#define __FILE_CHOOSER_PORTAL_H
+
+// TQt
+#include <tqdbusconnection.h>
+#include <tqdbusmessage.h>
+#include <tqdbusvariant.h>
+#include <tqdbuserror.h>
+#include <tqobject.h>
+
+// TDE
+#include <tdefile.h>
+
+// Portal
+#include "filechooserInterface.h"
+
+struct FileDialogOpts
+{
+ TQString caption;
+ TQString okButtonText;
+ TQString startDir;
+ TQString startName;
+ TQString filters;
+ bool multiple = false;
+ bool directory = false;
+ bool savingMode = false;
+ bool modal = true;
+ WId windowId = 0;
+
+ inline KFile::Mode mode()
+ {
+ if (directory) return KFile::Directory;
+ return multiple ? KFile::Files : KFile::File;
+ }
+};
+
+class KFileDialog;
+
+class TDEFileChooserPortal : public TQObject,
+ public org::freedesktop::impl::portal::FileChooserInterface
+{
+ public:
+ TDEFileChooserPortal(TQT_DBusConnection &connection);
+ virtual ~TDEFileChooserPortal();
+
+ protected:
+ virtual bool OpenFile(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error);
+
+ virtual bool SaveFile(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error);
+
+ virtual bool SaveFiles(const TQT_DBusObjectPath& handle,
+ const TQString& app_id,
+ const TQString& parent_window,
+ const TQString& title,
+ const TQMap<TQString, TQT_DBusVariant> &options,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error);
+
+ virtual void handleMethodReply(const TQT_DBusMessage &reply);
+
+ private:
+ TQT_DBusConnection m_connection;
+
+ WId parseWindowId(const TQString data);
+ TQString parseFilter(const TQT_DBusData data);
+ TQString parseFilterList(const TQT_DBusVariant filterData,
+ const TQT_DBusVariant currentFilterData);
+
+ bool execFileDialog(FileDialogOpts options,
+ const TQT_DBusObjectPath& handle,
+ TQ_UINT32& response,
+ TQMap<TQString, TQT_DBusVariant> &results,
+ TQT_DBusError& error);
+};
+
+#endif // __FILE_CHOOSER_PORTAL_H
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..278d754
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+// TQt
+#include <tqdbusconnection.h>
+
+// TDE
+#include <kuniqueapplication.h>
+#include <tdeaboutdata.h>
+#include <tdecmdlineargs.h>
+#include <tdelocale.h>
+
+// Portal
+#include "portal_service.h"
+
+
+static const char description[] = I18N_NOOP("TDE XDG desktop portal");
+static TDECmdLineOptions options[] = {};
+
+int main(int argc, char **argv)
+{
+ TDEAboutData about("xdg-desktop-portal-tde", "xdg-desktop-portal-tde", "1.0",
+ description, TDEAboutData::License_LGPL,
+ I18N_NOOP("Copyright © 2024 Mavridis Philippe"));
+
+ TDECmdLineArgs::init(argc, argv, &about);
+ TDECmdLineArgs::addCmdLineOptions(options);
+ KUniqueApplication::addCmdLineOptions();
+
+ if (!KUniqueApplication::start())
+ return 0;
+
+ KUniqueApplication app;
+
+ TQT_DBusConnection connection = TQT_DBusConnection::sessionBus();
+ if (!connection.isConnected())
+ tqFatal("Failed to connect to session bus!");
+
+ if (!connection.requestName("org.freedesktop.impl.portal.desktop.tde"))
+ tqFatal("Failed to register XDG portal service!");
+
+ TDEPortalService portal(connection);
+
+ return app.exec();
+}
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/portal.cpp b/src/portal.cpp
new file mode 100644
index 0000000..e69a1d8
--- /dev/null
+++ b/src/portal.cpp
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+// Portal
+#include "portal.h"
+#include "portal.moc"
+
+
+Portal::Portal(const TQT_DBusConnection &connection)
+: m_connection(connection)
+{}
+
+Portal::~Portal()
+{}
+
+bool Portal::handleMethodCall(const TQT_DBusMessage &message)
+{
+ return false;
+} \ No newline at end of file
diff --git a/src/portal.h b/src/portal.h
new file mode 100644
index 0000000..ee30d0d
--- /dev/null
+++ b/src/portal.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+#ifndef __PORTAL_H
+#define __PORTAL_H
+
+// TQt
+#include <tqdbusconnection.h>
+#include <tqdbusobject.h>
+#include <tqobject.h>
+
+
+class Portal : public TQObject, public TQT_DBusObjectBase
+{
+ TQ_OBJECT
+
+ public:
+ Portal(const TQT_DBusConnection &connection);
+ virtual ~Portal();
+
+ const TQT_DBusConnection connection() { return m_connection; }
+
+ protected:
+ virtual bool handleMethodCall(const TQT_DBusMessage &message);
+
+ private:
+ TQT_DBusConnection m_connection;
+};
+
+#endif // __PORTAL_H \ No newline at end of file
diff --git a/src/portal_service.cpp b/src/portal_service.cpp
new file mode 100644
index 0000000..86baa63
--- /dev/null
+++ b/src/portal_service.cpp
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+// TQt
+#include <tqdbusmessage.h>
+
+// TDE
+#include <tdemessagebox.h>
+#include <kdebug.h>
+
+// Portal
+#include "file_chooser_portal.h"
+#include "portal_service.h"
+
+
+static const char *dbusObjectPath = "/org/freedesktop/portal/desktop";
+static const char *dbusInterfaceRoot = "org.freedesktop.impl.portal";
+
+TDEPortalService::TDEPortalService(TQT_DBusConnection &connection)
+: m_connection(connection)
+{
+ if (!m_connection.registerObject(dbusObjectPath, this))
+ kdFatal() << "Unable to register XDG desktop portal object " << dbusObjectPath << endl;
+ else
+ kdDebug() << "Registered XDG desktop portal object " << dbusObjectPath << endl;
+}
+
+TDEPortalService::~TDEPortalService()
+{
+ m_connection.unregisterObject(dbusObjectPath);
+}
+
+TQT_DBusObjectBase* TDEPortalService::getPortalInterface(TQCString portal)
+{
+ if (portal == "FileChooser")
+ return new TDEFileChooserPortal(m_connection);
+
+ return nullptr;
+}
+
+bool TDEPortalService::handleMethodCall(const TQT_DBusMessage &message)
+{
+ if (!message.interface().startsWith(dbusInterfaceRoot))
+ return false;
+
+ TQCString portal = message.interface().mid(TQString(dbusInterfaceRoot).length() + 1).local8Bit();
+ TQT_DBusObjectBase *iface = getPortalInterface(portal);
+ if (!iface)
+ {
+ kdWarning() << "Unsupported XDG portal requested: " << portal << endl;
+ return false;
+ }
+
+ return delegateMethodCall(message, iface);
+}
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/portal_service.h b/src/portal_service.h
new file mode 100644
index 0000000..8e7c400
--- /dev/null
+++ b/src/portal_service.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+#ifndef __PORTAL_SERVICE_H
+#define __PORTAL_SERVICE_H
+
+// TQt
+#include <tqdbusconnection.h>
+#include <tqdbusobject.h>
+
+class TDEFileChooserPortal;
+
+class TDEPortalService : public TQT_DBusObjectBase
+{
+ public:
+ TDEPortalService(TQT_DBusConnection &connection);
+ ~TDEPortalService();
+
+ protected:
+ bool handleMethodCall(const TQT_DBusMessage &message);
+
+ private:
+ TQT_DBusConnection m_connection;
+ TQT_DBusObjectBase* getPortalInterface(TQCString portal);
+};
+
+#endif // __DESTKOP_PORTAL_H
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..656bfff
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ XDG desktop portal implementation for TDE
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ This program or library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Improvements and feedback are welcome!
+*******************************************************************************/
+
+#ifndef __UTIL_H
+#define __UTIL_H
+
+// TQt
+#include <tqdbusvariant.h>
+#include <tqdbusdatalist.h>
+#include <tqvariant.h>
+
+// TDE
+#include <kurl.h>
+
+inline bool check_variant(TQT_DBusVariant variant, TQString signature)
+{
+ return !variant.signature.isNull() && variant.signature == signature;
+}
+
+inline TQString bytelist_to_string(TQT_DBusDataList list)
+{
+ if (list.type() != TQT_DBusData::Byte) return TQString::null;
+ TQCString bytes;
+ TQValueList<TQ_UINT8> vl = list.toByteList();
+ TQValueList<TQ_UINT8>::iterator vlit;
+ for (vlit = vl.begin(); vlit != vl.end(); ++vlit)
+ {
+ bytes += (*vlit);
+ }
+ return TQString::fromLocal8Bit(bytes.data(), bytes.size());
+}
+
+inline TQT_DBusDataList string_to_bytelist(TQString str)
+{
+ TQCString bytes = str.latin1();
+ TQValueList<TQ_UINT8> vl;
+ char *bit;
+ for (bit = bytes.begin(); bit != bytes.end(); ++bit)
+ {
+ vl << (TQ_UINT8)(*bit);
+ }
+ return TQT_DBusDataList(vl);
+}
+
+inline TQT_DBusDataList kurl_list_to_datalist(KURL::List urls)
+{
+ return TQT_DBusDataList(urls.toStringList());
+}
+
+inline bool make_variant(TQVariant variant, TQT_DBusVariant &other)
+{
+ TQString signature;
+ switch (variant.type()) {
+ case TQVariant::String:
+ case TQVariant::Color:
+ case TQVariant::Font:
+ case TQVariant::Date:
+ case TQVariant::DateTime:
+ case TQVariant::Time:
+ case TQVariant::KeySequence:
+ other.signature = "s";
+ other.value = TQT_DBusData::fromString(variant.toString());
+ break;
+
+ case TQVariant::Int:
+ other.signature = "i";
+ other.value = TQT_DBusData::fromInt32(variant.toInt());
+ break;
+
+ case TQVariant::UInt:
+ other.signature = "u";
+ other.value = TQT_DBusData::fromUInt32(variant.toUInt());
+ break;
+
+ case TQVariant::Double:
+ case TQVariant::LongLong:
+ case TQVariant::ULongLong:
+ other.signature = "d";
+ other.value = TQT_DBusData::fromDouble(variant.toDouble());
+ break;
+
+ case TQVariant::Bool:
+ other.signature = "b";
+ other.value = TQT_DBusData::fromBool(variant.toBool());
+ break;
+
+ case TQVariant::StringList:
+ other.signature = "as";
+ other.value = TQT_DBusData::fromList(TQT_DBusDataList(variant.toStringList()));
+ break;
+
+ default:
+ if (variant.canCast(TQVariant::String)) {
+ other.signature = "s";
+ other.value = TQT_DBusData::fromString(variant.toString());
+ }
+ else {
+ kdDebug() << "Cannot cast TQVariant of type " << variant.type()
+ << "to TQT_DBusVariant!" << endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+#endif // __UTIL_H
+
+// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file