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 <mavridisf@gmail.com>
pull/6/head
Mavridis Philippe 2 months ago
parent acdd7db26e
commit 2397c7e9cb
No known key found for this signature in database
GPG Key ID: F8D2D7E2F989A494

@ -28,6 +28,7 @@
<!-- FileChooser -->
<interface name="org.freedesktop.impl.portal.FileChooser">
<method name="OpenFile">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg name="handle" type="o" direction="in" />
<arg name="app_id" type="s" direction="in" />
<arg name="parent_window" type="s" direction="in" />
@ -37,6 +38,7 @@
<arg name="results" type="a{sv}" direction="out" />
</method>
<method name="SaveFile">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg name="handle" type="o" direction="in" />
<arg name="app_id" type="s" direction="in" />
<arg name="parent_window" type="s" direction="in" />

@ -22,6 +22,8 @@
// TQt
#include <tqregexp.h>
#include <tqdbusobjectpath.h>
#include <tqapplication.h>
#include <tqthread.h>
// TDE
#include <tdeio/renamedlg.h>
@ -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<TQString, TQT_DBusVariant> 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,
void TDEFileChooserPortal::OpenFileAsync(int asyncCallId,
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)
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,
void TDEFileChooserPortal::SaveFileAsync(int asyncCallId,
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)
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<TQString, TQT_DBusVariant> &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)

@ -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,
void OpenFileAsync(int asyncCallId,
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);
const TQT_DBusVariantMap &options);
virtual bool SaveFile(const TQT_DBusObjectPath& handle,
void SaveFileAsync(int asyncCallId,
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);
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

@ -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())
{

@ -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

@ -31,6 +31,8 @@
// TDE
#include <kurl.h>
#define DEL(x) if (x) { delete x; x = nullptr; }
typedef TQMap<TQString, TQT_DBusVariant> TQT_DBusVariantMap;
typedef TQValueList<TQT_DBusData> TQT_DBusValueList;

Loading…
Cancel
Save