diff --git a/README.md b/README.md index 9b09bad..b2b3d5a 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ if they are set to 2, set them to 1. ## State of implementation Currently implemented are the following interfaces: +* Email - request to send an e-mail via the system e-mail client * FileChooser - request a file dialog The following implementations are planned (listed in no particular order): * Screenshot - request a screenshot * App Chooser - show a "Open with..." dialog for a file * Clipboard - request clipboard access (*) -* Email - request to send an e-mail via the system e-mail client * OpenURI - request to open a URL * Secret - integration with TDEWallet * Account - request user information (username, full name, user icon) diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt index 5a45e9f..d8e44c0 100644 --- a/interfaces/CMakeLists.txt +++ b/interfaces/CMakeLists.txt @@ -15,43 +15,24 @@ link_directories( ${DBUS_TQT_LIBRARY_DIRS} ) -set(interfaces filechooser) +set(interfaces filechooser email) +set(interface_HDRS introspectableInterface.h desktopNode.h dbusbaseNode.h) +set(interface_SRCS introspectableInterface.cpp desktopNode.cpp dbusbaseNode.cpp) foreach(interface IN LISTS interfaces) - set(interface_HDRS - introspectableInterface.h - ${interface}Interface.h - ${interface}Proxy.h - desktopNode.h - dbusbaseNode.h - ) - - set(interface_SRCS - introspectableInterface.cpp - ${interface}Interface.cpp - ${interface}Proxy.cpp - desktopNode.cpp - dbusbaseNode.cpp - ) - - set(interface_xml ${CMAKE_CURRENT_SOURCE_DIR}/${interface}.xml) - - add_custom_command( - OUTPUT ${interface_HDRS} ${interface_SRCS} - COMMAND ${DBUSXML2QT3_EXECUTABLE} ${interface_xml} - DEPENDS ${interface_xml} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - - add_custom_target(${interface} DEPENDS ${interface_SRCS}) - - list(APPEND interfaces_SRCS ${interface_SRCS}) - + list(APPEND interface_HDRS ${interface}Interface.h ${interface}Proxy.h) + list(APPEND interface_SRCS ${interface}Interface.cpp ${interface}Proxy.cpp) endforeach() +add_custom_command( + OUTPUT ${interface_HDRS} ${interface_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + tde_add_library(portalinterfaces STATIC_PIC AUTOMOC - DEPENDENCIES ${interfaces} - SOURCES ${interfaces_SRCS} + SOURCES ${interface_SRCS} LINK ${DBUS_TQT_LIBRARIES} ) diff --git a/interfaces/filechooser.xml b/interfaces/interfaces.xml similarity index 73% rename from interfaces/filechooser.xml rename to interfaces/interfaces.xml index 5524d45..003cdbd 100644 --- a/interfaces/filechooser.xml +++ b/interfaces/interfaces.xml @@ -1,5 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ca6297..0ed40be 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,8 @@ tde_add_executable( portal_daemon.cpp portal_service.cpp file_chooser_portal.cpp + email_portal.cpp + util.cpp LINK tdecore-shared diff --git a/src/email_portal.cpp b/src/email_portal.cpp new file mode 100644 index 0000000..d12ba50 --- /dev/null +++ b/src/email_portal.cpp @@ -0,0 +1,86 @@ +/******************************************************************************* + XDG desktop portal implementation for TDE + Copyright © 2024 Mavridis Philippe + + 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! +*******************************************************************************/ + +// TDE +#include + +// Portal +#include "email_portal.h" +#include "email_portal.moc" + +TDEEmailPortal::TDEEmailPortal(TQT_DBusConnection &connection) +: m_connection(connection) +{ +} + +TDEEmailPortal::~TDEEmailPortal() +{ +} + +void TDEEmailPortal::handleMethodReply(const TQT_DBusMessage &reply) +{ + m_connection.send(reply); +} + +bool TDEEmailPortal::handleSignalSend(const TQT_DBusMessage& reply) { + handleMethodReply(reply); + return true; +} + +bool TDEEmailPortal::ComposeEmail(const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQT_DBusVariantMap& options, + TQ_UINT32& response, + TQT_DBusVariantMap &results, + TQT_DBusError& error) +{ + // void invokeMailer (const TQString &to, const TQString &cc, const TQString &bcc, const TQString &subject, const TQString &body, const TQString &messageFile=TQString::null, const TQStringList &attachURLs=TQStringList()) + EmailOpts opts; + if (OPTION_VALID("address", "s")) + opts.rcpt << options["address"].value.toString(); + + if (OPTION_VALID("addresses", "as")) + opts.rcpt += options["addresses"].value.toList().toTQStringList(); + + if (OPTION_VALID("cc", "as")) + opts.cc += options["cc"].value.toList().toTQStringList(); + + if (OPTION_VALID("bcc", "as")) + opts.bcc += options["bcc"].value.toList().toTQStringList(); + + if (OPTION_VALID("subject", "s")) + opts.subj = options["subject"].value.toString(); + + if (OPTION_VALID("body", "s")) + opts.body = options["body"].value.toString(); + + if (OPTION_VALID("attachments", "as")) + { + opts.attach += options["attachments"].value.toList().toTQStringList(); + } + + kapp->invokeMailer(opts.rcpt.join(";"), opts.cc.join(";"), opts.bcc.join(";"), + opts.subj, opts.body, TQString::null, opts.attach); + return true; +} + +// kate: replace-tabs true; tab-width 4; indent-width 4; \ No newline at end of file diff --git a/src/email_portal.h b/src/email_portal.h new file mode 100644 index 0000000..0a59346 --- /dev/null +++ b/src/email_portal.h @@ -0,0 +1,65 @@ +/******************************************************************************* + XDG desktop portal implementation for TDE + Copyright © 2024 Mavridis Philippe + + 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 __EMAIL_PORTAL_H +#define __EMAIL_PORTAL_H + +// Portal +#include "interfaces/emailInterface.h" +#include "interface.h" + +struct EmailOpts +{ + TQStringList rcpt; + TQStringList cc; + TQStringList bcc; + TQString subj; + TQString body; + TQStringList attach; +}; + +class TDEEmailPortal : public TQObject, + public org::freedesktop::impl::portal::EmailInterface +{ + public: + INTERFACE("org.freedesktop.impl.portal.Email") + + TDEEmailPortal(TQT_DBusConnection &connection); + virtual ~TDEEmailPortal(); + + protected: + virtual void handleMethodReply(const TQT_DBusMessage& reply); + virtual bool handleSignalSend(const TQT_DBusMessage& reply); + + virtual bool ComposeEmail(const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQT_DBusVariantMap& options, + TQ_UINT32& response, + TQT_DBusVariantMap &results, + TQT_DBusError& error); + private: + TQT_DBusConnection m_connection; +}; + +#endif // __EMAIL_PORTAL_H + +// 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 index ee8b0f6..4668abd 100644 --- a/src/file_chooser_portal.cpp +++ b/src/file_chooser_portal.cpp @@ -33,11 +33,6 @@ // 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) @@ -135,8 +130,8 @@ bool TDEFileChooserPortal::SaveFiles(const TQT_DBusObjectPath& handle, return false; } - TQValueList filelist = options["files"].value.toTQValueList(); - TQValueList::iterator fi; + TQT_DBusValueList filelist = options["files"].value.toTQValueList(); + TQT_DBusValueList::iterator fi; TQStringList files; for (fi = filelist.begin(); fi != filelist.end(); ++fi) { @@ -279,15 +274,15 @@ TQString TDEFileChooserPortal::parseFilter(const TQT_DBusData data) { TQStringList patternList; - TQValueList filterData = data.toStruct(); + TQT_DBusValueList filterData = data.toStruct(); TQString label = filterData[0].toString(); - TQValueList patterns = filterData[1].toTQValueList(); + TQT_DBusValueList patterns = filterData[1].toTQValueList(); - TQValueList::iterator fp; + TQT_DBusValueList::iterator fp; for (fp = patterns.begin(); fp != patterns.end(); ++fp) { - TQValueList patternData = (*fp).toStruct(); + TQT_DBusValueList patternData = (*fp).toStruct(); bool isMime = (patternData[0].toUInt32() == 1); if (isMime) { // KFileDialog cannot handle both a mime and a simple @@ -326,9 +321,9 @@ TQString TDEFileChooserPortal::parseFilterList(const TQT_DBusVariant filterData, const TQT_DBusVariant currentFilterData) { TQStringList filterList; - TQValueList filters = filterData.value.toTQValueList(); + TQT_DBusValueList filters = filterData.value.toTQValueList(); if (filters.count() > 0) { - TQValueList::iterator f; + TQT_DBusValueList::iterator f; for (f = filters.begin(); f != filters.end(); ++f) filterList += parseFilter((*f)); } diff --git a/src/file_chooser_portal.h b/src/file_chooser_portal.h index ef7b43a..9732b8d 100644 --- a/src/file_chooser_portal.h +++ b/src/file_chooser_portal.h @@ -22,18 +22,12 @@ #ifndef __FILE_CHOOSER_PORTAL_H #define __FILE_CHOOSER_PORTAL_H -// TQt -#include -#include -#include -#include -#include - // TDE #include // Portal #include "interfaces/filechooserInterface.h" +#include "interface.h" struct FileDialogOpts { @@ -60,44 +54,43 @@ class KFileDialog; class TDEFileChooserPortal : public TQObject, public org::freedesktop::impl::portal::FileChooserInterface { + INTERFACE("org.freedesktop.impl.portal.FileChooser") + public: TDEFileChooserPortal(TQT_DBusConnection &connection); virtual ~TDEFileChooserPortal(); - static const TQString interface() { return "org.freedesktop.impl.portal.FileChooser"; } - protected: virtual bool OpenFile(const TQT_DBusObjectPath& handle, const TQString& app_id, const TQString& parent_window, const TQString& title, - const TQMap &options, + const TQT_DBusVariantMap &options, TQ_UINT32& response, - TQMap &results, + TQT_DBusVariantMap &results, TQT_DBusError& error); virtual bool SaveFile(const TQT_DBusObjectPath& handle, const TQString& app_id, const TQString& parent_window, const TQString& title, - const TQMap &options, + const TQT_DBusVariantMap &options, TQ_UINT32& response, - TQMap &results, + TQT_DBusVariantMap &results, TQT_DBusError& error); virtual bool SaveFiles(const TQT_DBusObjectPath& handle, const TQString& app_id, const TQString& parent_window, const TQString& title, - const TQMap &options, + const TQT_DBusVariantMap &options, TQ_UINT32& response, - TQMap &results, + TQT_DBusVariantMap &results, TQT_DBusError& error); virtual void handleMethodReply(const TQT_DBusMessage& reply); virtual bool handleSignalSend(const TQT_DBusMessage& reply); - private: TQT_DBusConnection m_connection; @@ -109,7 +102,7 @@ class TDEFileChooserPortal : public TQObject, bool execFileDialog(FileDialogOpts options, const TQT_DBusObjectPath& handle, TQ_UINT32& response, - TQMap &results, + TQT_DBusVariantMap &results, TQT_DBusError& error); }; diff --git a/src/interface.h b/src/interface.h new file mode 100644 index 0000000..48ce942 --- /dev/null +++ b/src/interface.h @@ -0,0 +1,46 @@ +/******************************************************************************* + XDG desktop portal implementation for TDE + Copyright © 2024 Mavridis Philippe + + 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! +*******************************************************************************/ + +/* Common definitions and includes for portal interfaces */ +#ifndef __INTERFACE_H_ +#define __INTERFACE_H_ + +// TQt +#include +#include +#include +#include +#include +#include +#include + +// Portal +#include "util.h" + +#define INTERFACE(x) \ + public: \ + static const TQCString interface() { return x; } + + +#define OPTION_VALID(opt, sig) \ + options.keys().contains(opt) && check_variant(options[opt], sig) + +#endif // __INTERFACE_H_ \ No newline at end of file diff --git a/src/portal_service.cpp b/src/portal_service.cpp index 4e0eae3..280078d 100644 --- a/src/portal_service.cpp +++ b/src/portal_service.cpp @@ -31,6 +31,7 @@ // Portal #include "file_chooser_portal.h" +#include "email_portal.h" #include "portal_service.h" @@ -44,6 +45,7 @@ DesktopNodeService::DesktopNodeService(TQT_DBusConnection &connection) m_interfaces.insert("org.freedesktop.DBus.Introspectable", this); REGISTER_PORTAL(TDEFileChooserPortal) + REGISTER_PORTAL(TDEEmailPortal) registerObject(connection, dbusObjectPath); } @@ -51,6 +53,7 @@ DesktopNodeService::DesktopNodeService(TQT_DBusConnection &connection) DesktopNodeService::~DesktopNodeService() { DESTROY_PORTAL(TDEFileChooserPortal) + DESTROY_PORTAL(TDEEmailPortal) } TQT_DBusObjectBase* DesktopNodeService::createInterface(const TQString& iface) diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..7474fa1 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,117 @@ +/******************************************************************************* + XDG desktop portal implementation for TDE + Copyright © 2024 Mavridis Philippe + + 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! +*******************************************************************************/ + +// TDE +#include + +// Portal +#include "util.h" + +bool check_variant(TQT_DBusVariant variant, TQString signature) +{ + return !variant.signature.isNull() && variant.signature == signature; +} + +TQString bytelist_to_string(TQT_DBusDataList list) +{ + if (list.type() != TQT_DBusData::Byte) return TQString::null; + TQCString bytes; + TQValueList vl = list.toByteList(); + TQValueList::iterator vlit; + for (vlit = vl.begin(); vlit != vl.end(); ++vlit) + { + bytes += (*vlit); + } + return TQString::fromLocal8Bit(bytes.data(), bytes.size()); +} + +TQT_DBusDataList string_to_bytelist(TQString str) +{ + TQCString bytes = str.latin1(); + TQValueList vl; + char *bit; + for (bit = bytes.begin(); bit != bytes.end(); ++bit) + { + vl << (TQ_UINT8)(*bit); + } + return TQT_DBusDataList(vl); +} + +TQT_DBusDataList kurl_list_to_datalist(KURL::List urls) +{ + return TQT_DBusDataList(urls.toStringList()); +} + +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; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 656bfff..f27b7b8 100644 --- a/src/util.h +++ b/src/util.h @@ -30,96 +30,18 @@ // TDE #include -inline bool check_variant(TQT_DBusVariant variant, TQString signature) -{ - return !variant.signature.isNull() && variant.signature == signature; -} +typedef TQMap TQT_DBusVariantMap; +typedef TQValueList TQT_DBusValueList; -inline TQString bytelist_to_string(TQT_DBusDataList list) -{ - if (list.type() != TQT_DBusData::Byte) return TQString::null; - TQCString bytes; - TQValueList vl = list.toByteList(); - TQValueList::iterator vlit; - for (vlit = vl.begin(); vlit != vl.end(); ++vlit) - { - bytes += (*vlit); - } - return TQString::fromLocal8Bit(bytes.data(), bytes.size()); -} +extern bool check_variant(TQT_DBusVariant variant, TQString signature); -inline TQT_DBusDataList string_to_bytelist(TQString str) -{ - TQCString bytes = str.latin1(); - TQValueList vl; - char *bit; - for (bit = bytes.begin(); bit != bytes.end(); ++bit) - { - vl << (TQ_UINT8)(*bit); - } - return TQT_DBusDataList(vl); -} +extern TQString bytelist_to_string(TQT_DBusDataList list); -inline TQT_DBusDataList kurl_list_to_datalist(KURL::List urls) -{ - return TQT_DBusDataList(urls.toStringList()); -} +extern TQT_DBusDataList string_to_bytelist(TQString str); -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; +extern TQT_DBusDataList kurl_list_to_datalist(KURL::List urls); - 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; -} +extern bool make_variant(TQVariant variant, TQT_DBusVariant &other); #endif // __UTIL_H