From 2397c7e9cb9eba2b2b7934ef7d59e1bd3035c67d Mon Sep 17 00:00:00 2001 From: Mavridis Philippe Date: Wed, 2 Oct 2024 14:42:05 +0300 Subject: [PATCH] FileDialog: Use Async methods and result sender thread The thread waits until the non-modal dialog is done and then sends the result without blocking the main thread. The dialog itself is initialized in the main thread. This should fix high CPU usage while a dialog is open, not being able to open multiple instances of a dialog at once and the DBus service locking down while a dialog is open. xdg-desktop-portal-tde might yet make it into R14.1.3 ;-) Signed-off-by: Mavridis Philippe --- interfaces/interfaces.xml | 2 + src/file_chooser_portal.cpp | 100 ++++++++++++++++++++++++------------ src/file_chooser_portal.h | 42 ++++++++------- src/portal_daemon.cpp | 11 ++-- src/portal_daemon.h | 2 - src/util.h | 2 + 6 files changed, 98 insertions(+), 61 deletions(-) diff --git a/interfaces/interfaces.xml b/interfaces/interfaces.xml index c6f5357..e86379f 100644 --- a/interfaces/interfaces.xml +++ b/interfaces/interfaces.xml @@ -28,6 +28,7 @@ + @@ -37,6 +38,7 @@ + diff --git a/src/file_chooser_portal.cpp b/src/file_chooser_portal.cpp index 9b8f6e7..246ad1a 100644 --- a/src/file_chooser_portal.cpp +++ b/src/file_chooser_portal.cpp @@ -22,6 +22,8 @@ // TQt #include #include +#include +#include // TDE #include @@ -33,6 +35,48 @@ #include "file_chooser_portal.h" #include "file_chooser_portal.moc" +class DialogResultSender : public TQThread +{ + public: + DialogResultSender(KFileDialog *dlg, int asyncCallId, TDEFileChooserPortal *portal, TQT_DBusAsyncCallback callback) + : TQThread(), m_dlg(dlg), m_asyncCallId(asyncCallId), m_portal(portal), m_callback(callback) + {} + + ~DialogResultSender() + { + wait(); + } + + void run() + { + if (!m_dlg) return; + + while (m_dlg->isVisible()) + { + usleep(1000); + } + + KURL::List urllist = m_dlg->selectedURLs(); + + TQMap results; + TQT_DBusDataList urls = kurl_list_to_datalist(urllist); + TQT_DBusVariant var = TQT_DBusData::fromList(urls).getAsVariantData().toVariant(); + results.insert("uris", var); + + TQ_UINT32 response = urllist.isEmpty() ? 1 : 0; + + (m_portal->*m_callback)(m_asyncCallId, response, results); + + m_dlg->deleteLater(); + } + + private: + KFileDialog *m_dlg; + int m_asyncCallId; + TDEFileChooserPortal *m_portal; + TQT_DBusAsyncCallback m_callback; +}; + TDEFileChooserPortal::TDEFileChooserPortal(TQT_DBusConnection &connection) : m_connection(connection) {} @@ -40,14 +84,12 @@ TDEFileChooserPortal::TDEFileChooserPortal(TQT_DBusConnection &connection) TDEFileChooserPortal::~TDEFileChooserPortal() {} -bool TDEFileChooserPortal::OpenFile(const TQT_DBusObjectPath& handle, - const TQString& app_id, - const TQString& parent_window, - const TQString& title, - const TQMap &options, - TQ_UINT32& response, - TQMap &results, - TQT_DBusError& error) +void TDEFileChooserPortal::OpenFileAsync(int asyncCallId, + const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQString& title, + const TQT_DBusVariantMap &options) { FileDialogOpts opts; @@ -70,17 +112,16 @@ bool TDEFileChooserPortal::OpenFile(const TQT_DBusObjectPath& handle, opts.windowId = parse_window_id(parent_window); - return execFileDialog(opts, handle, response, results, error); + // Execute dialog + execFileDialog(&TDEFileChooserPortal::OpenFileAsyncReply, asyncCallId, opts, handle); } -bool TDEFileChooserPortal::SaveFile(const TQT_DBusObjectPath& handle, - const TQString& app_id, - const TQString& parent_window, - const TQString& title, - const TQMap &options, - TQ_UINT32& response, - TQMap &results, - TQT_DBusError& error) +void TDEFileChooserPortal::SaveFileAsync(int asyncCallId, + const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQString& title, + const TQT_DBusVariantMap &options) { FileDialogOpts opts; @@ -109,7 +150,7 @@ bool TDEFileChooserPortal::SaveFile(const TQT_DBusObjectPath& handle, opts.windowId = parse_window_id(parent_window); - return execFileDialog(opts, handle, response, results, error); + execFileDialog(&TDEFileChooserPortal::SaveFileAsyncReply, asyncCallId, opts, handle); } bool TDEFileChooserPortal::SaveFiles(const TQT_DBusObjectPath& handle, @@ -211,11 +252,10 @@ bool TDEFileChooserPortal::handleSignalSend(const TQT_DBusMessage& reply) { return true; } -bool TDEFileChooserPortal::execFileDialog(FileDialogOpts options, - const TQT_DBusObjectPath& handle, - TQ_UINT32& response, - TQMap &results, - TQT_DBusError& error) +void TDEFileChooserPortal::execFileDialog(TQT_DBusAsyncCallback callback, + int asyncCallId, + FileDialogOpts options, + const TQT_DBusObjectPath& handle) { KFileDialog *dialog = new KFileDialog(options.startDir, TQString::null, nullptr, "xdg-tde-file-chooser", @@ -243,15 +283,11 @@ bool TDEFileChooserPortal::execFileDialog(FileDialogOpts options, 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; +// return dialog->selectedURLs(); + + DialogResultSender *sender = new DialogResultSender(dialog, asyncCallId, this, callback); + dialog->show(); + sender->start(); } TQString TDEFileChooserPortal::parseFilter(const TQT_DBusData data) diff --git a/src/file_chooser_portal.h b/src/file_chooser_portal.h index 9732b8d..383d219 100644 --- a/src/file_chooser_portal.h +++ b/src/file_chooser_portal.h @@ -29,6 +29,9 @@ #include "interfaces/filechooserInterface.h" #include "interface.h" +class TDEFileChooserPortal; +typedef void(TDEFileChooserPortal::*TQT_DBusAsyncCallback)(int, TQ_UINT32, const TQT_DBusVariantMap&); + struct FileDialogOpts { TQString caption; @@ -61,23 +64,19 @@ class TDEFileChooserPortal : public TQObject, virtual ~TDEFileChooserPortal(); protected: - virtual bool OpenFile(const TQT_DBusObjectPath& handle, - const TQString& app_id, - const TQString& parent_window, - const TQString& title, - const TQT_DBusVariantMap &options, - TQ_UINT32& response, - 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 TQT_DBusVariantMap &options, - TQ_UINT32& response, - TQT_DBusVariantMap &results, - TQT_DBusError& error); + void OpenFileAsync(int asyncCallId, + const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQString& title, + const TQT_DBusVariantMap &options); + + void SaveFileAsync(int asyncCallId, + const TQT_DBusObjectPath& handle, + const TQString& app_id, + const TQString& parent_window, + const TQString& title, + const TQT_DBusVariantMap &options); virtual bool SaveFiles(const TQT_DBusObjectPath& handle, const TQString& app_id, @@ -99,11 +98,10 @@ class TDEFileChooserPortal : public TQObject, TQString parseFilterList(const TQT_DBusVariant filterData, const TQT_DBusVariant currentFilterData); - bool execFileDialog(FileDialogOpts options, - const TQT_DBusObjectPath& handle, - TQ_UINT32& response, - TQT_DBusVariantMap &results, - TQT_DBusError& error); + void execFileDialog(TQT_DBusAsyncCallback callback, + int asyncCallId, + FileDialogOpts options, + const TQT_DBusObjectPath& handle); }; #endif // __FILE_CHOOSER_PORTAL_H diff --git a/src/portal_daemon.cpp b/src/portal_daemon.cpp index f533791..7b2749d 100644 --- a/src/portal_daemon.cpp +++ b/src/portal_daemon.cpp @@ -31,6 +31,7 @@ // Portal #include "portal_daemon.h" #include "portal_daemon.moc" +#include "util.h" PortalDaemon::PortalDaemon() : KUniqueApplication(), @@ -83,11 +84,11 @@ void PortalDaemon::connectDBus() void PortalDaemon::disconnectDBus() { - ZAP(d_root) - ZAP(d_org) - ZAP(d_freedesktop) - ZAP(d_portal) - ZAP(d_desktop) + DEL(d_root) + DEL(d_org) + DEL(d_freedesktop) + DEL(d_portal) + DEL(d_desktop) if (m_connection.isConnected()) { diff --git a/src/portal_daemon.h b/src/portal_daemon.h index 974f234..4b52612 100644 --- a/src/portal_daemon.h +++ b/src/portal_daemon.h @@ -40,8 +40,6 @@ #define DBUS_RETRY_TIMEOUT 5000 #define DBUS_RETRY_COUNT 3 -#define ZAP(x) if (x) { delete x; x = nullptr; } - class PortalDaemon : public KUniqueApplication { TQ_OBJECT diff --git a/src/util.h b/src/util.h index e5a2040..64df0ee 100644 --- a/src/util.h +++ b/src/util.h @@ -31,6 +31,8 @@ // TDE #include +#define DEL(x) if (x) { delete x; x = nullptr; } + typedef TQMap TQT_DBusVariantMap; typedef TQValueList TQT_DBusValueList;