Added Account portal, permission dialog class, moved some code to util

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
pull/6/head
Mavridis Philippe 5 months ago
parent 87769ed51d
commit a5eb53fcbc
No known key found for this signature in database
GPG Key ID: F8D2D7E2F989A494

@ -20,6 +20,7 @@ if they are set to 2, set them to 1.
## State of implementation ## State of implementation
Currently implemented are the following interfaces: Currently implemented are the following interfaces:
* Account - request user information (user ID, full name, user icon)
* Email - request to send an e-mail via the system e-mail client * Email - request to send an e-mail via the system e-mail client
* FileChooser - request a file dialog * FileChooser - request a file dialog
@ -29,7 +30,6 @@ The following implementations are planned (listed in no particular order):
* Clipboard - request clipboard access (*) * Clipboard - request clipboard access (*)
* OpenURI - request to open a URL * OpenURI - request to open a URL
* Secret - integration with TDEWallet * Secret - integration with TDEWallet
* Account - request user information (username, full name, user icon)
* Access - show a grant access dialog * Access - show a grant access dialog
* Wallpaper - request to change the user's wallpaper * Wallpaper - request to change the user's wallpaper
* Print - request a file to be printed * Print - request a file to be printed

@ -15,7 +15,7 @@ link_directories(
${DBUS_TQT_LIBRARY_DIRS} ${DBUS_TQT_LIBRARY_DIRS}
) )
set(interfaces filechooser email) set(interfaces account email filechooser)
set(interface_HDRS introspectableInterface.h desktopNode.h dbusbaseNode.h) set(interface_HDRS introspectableInterface.h desktopNode.h dbusbaseNode.h)
set(interface_SRCS introspectableInterface.cpp desktopNode.cpp dbusbaseNode.cpp) set(interface_SRCS introspectableInterface.cpp desktopNode.cpp dbusbaseNode.cpp)

@ -1,5 +1,17 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedesktop/portal/desktop"> <node name="/org/freedesktop/portal/desktop">
<!-- Account -->
<interface name="org.freedesktop.impl.portal.Account">
<method name="GetUserInformation">
<arg type="o" name="handle" direction="in"/>
<arg type="s" name="app_id" direction="in"/>
<arg type="s" name="window" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="u" name="response" direction="out"/>
<arg type="a{sv}" name="results" direction="out"/>
</method>
</interface>
<!-- Email --> <!-- Email -->
<interface name="org.freedesktop.impl.portal.Email"> <interface name="org.freedesktop.impl.portal.Email">
<method name="ComposeEmail">+ <method name="ComposeEmail">+

@ -28,8 +28,10 @@ tde_add_executable(
main.cpp main.cpp
portal_daemon.cpp portal_daemon.cpp
portal_service.cpp portal_service.cpp
file_chooser_portal.cpp account_portal.cpp
email_portal.cpp email_portal.cpp
file_chooser_portal.cpp
permission_dialog.cpp
util.cpp util.cpp
LINK LINK

@ -0,0 +1,209 @@
/*******************************************************************************
XDG desktop portal implementation for TDE
Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
Avatar detection code is based on code from the Redmond KSplash theme
Copyright © 2001-2003 Brian Ledbetter 2001-2003 <brian@shadowcom.net>
Copyright © 2003 Ravikiran Rajagopal 2003 <ravi@kde.org>
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 <tqfile.h>
#include <tqhbox.h>
#include <tqlabel.h>
#include <tqdbusdata.h>
// TDE
#include <kstandarddirs.h>
#include <ksimpleconfig.h>
#include <tdelocale.h>
#include <twin.h>
#include <kuser.h>
#include <kdebug.h>
// Portal
#include "permission_dialog.h"
#include "account_portal.h"
#include "account_portal.moc"
#define TQSTRING_TO_DBUS_VARIANT(x) \
TQT_DBusData::fromString(x).getAsVariantData().toVariant()
TDEAccountPortal::TDEAccountPortal(TQT_DBusConnection &connection)
: m_connection(connection)
{
}
TDEAccountPortal::~TDEAccountPortal()
{
}
void TDEAccountPortal::handleMethodReply(const TQT_DBusMessage &reply)
{
m_connection.send(reply);
}
bool TDEAccountPortal::handleSignalSend(const TQT_DBusMessage& reply) {
handleMethodReply(reply);
return true;
}
bool TDEAccountPortal::GetUserInformation(const TQT_DBusObjectPath& handle,
const TQString& app_id,
const TQString& window,
const TQT_DBusVariantMap& options,
TQ_UINT32& response,
TQT_DBusVariantMap& results,
TQT_DBusError& error)
{
Dictionary details;
if (OPTION_VALID("reason", "s"))
{
TQString reason(options["reason"].value.toString());
if (!reason.isEmpty())
{
details[i18n("Reason")] = reason;
}
}
// Try to detect which application requested the permission
WId wid = parse_window_id(window);
ApplicationInfo app = application_info_from_wid(wid);
if (!app.path.isEmpty())
details[i18n("Path")] = app.path;
// Run the dialog
TDEPermissionDialog *dialog = new TDEPermissionDialog(
app.name,
i18n("Account information"),
"user-info",
details
);
AccountInfo info = getAccountInfo();
appendDataPreview(dialog, info);
if (wid > 0) KWin::setMainWindow(dialog, wid);
if (dialog->exec() == KDialogBase::Yes)
{
response = 0;
results.insert("id", TQSTRING_TO_DBUS_VARIANT(info.userId));
results.insert("name", TQSTRING_TO_DBUS_VARIANT(info.realName));
results.insert("image", TQSTRING_TO_DBUS_VARIANT(info.avatarPath));
}
else response = 1;
delete dialog;
return true;
}
AccountInfo TDEAccountPortal::getAccountInfo()
{
AccountInfo info;
KUser user;
info.userId = TQString::number(user.uid());
info.loginName = user.loginName();
info.realName = user.fullName();
info.homeDirectory = user.homeDir();
findUserAvatar(info);
return info;
}
void TDEAccountPortal::findUserAvatar(AccountInfo &info)
{
// Parse tdmrc settings to determine face source and system location
const int fAdminOnly = 1;
const int fAdminFirst = fAdminOnly + 1;
const int fUserFirst = fAdminFirst + 1;
const int fUserOnly = fUserFirst + 1;
int faceSource = fAdminOnly;
TDEConfig *tdmconfig = new TDEConfig("tdm/tdmrc", true);
tdmconfig->setGroup("X-*-Greeter");
TQString fs = tdmconfig->readEntry("FaceSource");
if (fs == TQString::fromLatin1("UserOnly"))
faceSource = fUserOnly;
else if (fs == TQString::fromLatin1("PreferUser"))
faceSource = fUserFirst;
else if (fs == TQString::fromLatin1("PreferAdmin"))
faceSource = fAdminFirst;
else
faceSource = fAdminOnly;
TQString userPicsDir = tdmconfig->readEntry("FaceDir",
TDEGlobal::dirs()->resourceDirs("data").last() + "tdm/faces") + '/';
delete tdmconfig;
// Faces provided by administrator (default and per user)
const TQString systemDefault(userPicsDir + ".default.face.icon");
const TQString systemUser(userPicsDir + info.loginName + ".face.icon");
TQString avatar;
if (faceSource == fAdminFirst)
{
avatar = systemUser;
if (!TQFile::exists(avatar))
faceSource = fUserOnly;
}
if (faceSource >= fUserFirst)
{
avatar = info.homeDirectory + "/.face.icon";
if (!TQFile::exists(avatar) && faceSource == fUserFirst)
avatar = systemUser;
if (!TQFile::exists(avatar))
avatar = systemDefault;
}
if (faceSource <= fAdminOnly)
{
avatar = systemUser;
if (!TQFile::exists(avatar))
avatar = systemDefault;
}
info.avatarPath = avatar;
}
void TDEAccountPortal::appendDataPreview(TDEPermissionDialog *dlg, AccountInfo info)
{
TQHBox *frame = new TQHBox(dlg);
frame->setFrameStyle(TQFrame::StyledPanel | TQFrame::Sunken);
TQLabel *avatar = new TQLabel(frame);
avatar->setPixmap(TQPixmap(info.avatarPath));
TQString userDataStr = "<qt><h1>%1</h1><hr>ID: %2</qt>";
userDataStr = userDataStr.arg(info.realName, info.userId);
TQLabel *userData = new TQLabel(userDataStr, frame);
avatar->setMargin(TDEPermissionDialog::spacingHint());
userData->setMargin(TDEPermissionDialog::spacingHint());
frame->setSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed);
dlg->appendWidget(frame);
}
// kate: replace-tabs true; tab-width 4; indent-width 4;

@ -0,0 +1,73 @@
/*******************************************************************************
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 __ACCOUNT_PORTAL_H
#define __ACCOUNT_PORTAL_H
// Portal
#include "interfaces/accountInterface.h"
#include "interface.h"
struct AccountInfo
{
TQString userId;
TQString loginName;
TQString realName;
TQString homeDirectory;
TQString avatarPath;
};
class TDEPermissionDialog;
class TDEAccountPortal : public TQObject,
public org::freedesktop::impl::portal::AccountInterface
{
public:
INTERFACE("org.freedesktop.impl.portal.Account")
TDEAccountPortal(TQT_DBusConnection &connection);
virtual ~TDEAccountPortal();
protected:
virtual void handleMethodReply(const TQT_DBusMessage& reply);
virtual bool handleSignalSend(const TQT_DBusMessage& reply);
virtual bool GetUserInformation(const TQT_DBusObjectPath& handle,
const TQString& app_id,
const TQString& window,
const TQT_DBusVariantMap& options,
TQ_UINT32& response,
TQT_DBusVariantMap& results,
TQT_DBusError& error);
AccountInfo getAccountInfo();
void appendDataPreview(TDEPermissionDialog *dlg, AccountInfo info);
private:
void findUserAvatar(AccountInfo &info);
private:
TQT_DBusConnection m_connection;
};
#endif // __ACCOUNT_PORTAL_H
// kate: replace-tabs true; tab-width 4; indent-width 4;

@ -53,7 +53,6 @@ bool TDEEmailPortal::ComposeEmail(const TQT_DBusObjectPath& handle,
TQT_DBusVariantMap &results, TQT_DBusVariantMap &results,
TQT_DBusError& error) 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; EmailOpts opts;
if (OPTION_VALID("address", "s")) if (OPTION_VALID("address", "s"))
opts.rcpt << options["address"].value.toString(); opts.rcpt << options["address"].value.toString();

@ -27,7 +27,6 @@
#include <tdeio/renamedlg.h> #include <tdeio/renamedlg.h>
#include <tdefiledialog.h> #include <tdefiledialog.h>
#include <kpushbutton.h> #include <kpushbutton.h>
#include <twin.h>
#include <kdebug.h> #include <kdebug.h>
// Portal // Portal
@ -69,7 +68,7 @@ bool TDEFileChooserPortal::OpenFile(const TQT_DBusObjectPath& handle,
if (OPTION_VALID("filters", "a(sa(us))")) if (OPTION_VALID("filters", "a(sa(us))"))
opts.filters = parseFilterList(options["filters"], options["current_filter"]); opts.filters = parseFilterList(options["filters"], options["current_filter"]);
opts.windowId = parseWindowId(parent_window); opts.windowId = parse_window_id(parent_window);
return execFileDialog(opts, handle, response, results, error); return execFileDialog(opts, handle, response, results, error);
} }
@ -108,7 +107,7 @@ bool TDEFileChooserPortal::SaveFile(const TQT_DBusObjectPath& handle,
if (OPTION_VALID("current_name", "s")) if (OPTION_VALID("current_name", "s"))
opts.startName = options["current_name"].value.toString(); opts.startName = options["current_name"].value.toString();
opts.windowId = parseWindowId(parent_window); opts.windowId = parse_window_id(parent_window);
return execFileDialog(opts, handle, response, results, error); return execFileDialog(opts, handle, response, results, error);
} }
@ -255,21 +254,6 @@ bool TDEFileChooserPortal::execFileDialog(FileDialogOpts options,
return true; 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) TQString TDEFileChooserPortal::parseFilter(const TQT_DBusData data)
{ {
TQStringList patternList; TQStringList patternList;

@ -0,0 +1,100 @@
/*******************************************************************************
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 <tqvbox.h>
#include <tqhbox.h>
#include <tqlayout.h>
#include <tqlabel.h>
// TDE
#include <tdelocale.h>
#include <kiconloader.h>
#include <twin.h>
// Portal
#include "permission_dialog.h"
#include "permission_dialog.moc"
TDEPermissionDialog::TDEPermissionDialog(TQString application, TQString feature,
TQString icon, Dictionary details)
: KDialogBase(TQString::null, /* we set plain caption below */
KDialogBase::Yes | KDialogBase::No | KDialogBase::Details,
KDialogBase::NoDefault, KDialogBase::No,
nullptr, "permissiondlg", true, true,
KGuiItem(i18n("&Allow"), "button_ok"),
KGuiItem(i18n("&Deny"), "button_cancel")),
m_vbox(new TQVBox(this)),
m_hbox(new TQHBox(m_vbox)),
m_icon(new TQLabel(m_hbox)),
m_text(new TQLabel(m_hbox)),
m_detail(new TQLabel(this))
{
setPlainCaption(i18n("Permission request"));
TQString text;
if (!application.isEmpty())
{
text = "<qt>Application \"%1\" has requested the following permission: <b>%2</b></qt>";
text = text.arg(application);
}
else
text = "<qt>An unknown application has requested the following permission: <b>%1</b></qt>";
m_text->setText(text.arg(feature));
m_icon->setPixmap(DesktopIcon(icon));
m_icon->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed);
m_text->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed);
TQString detailStr = "<qt><table><tbody>";
for (Dictionary::iterator it = details.begin(); it != details.end(); ++it)
{
detailStr += TQString("<tr><td>%1:</td><td><b>%2</b></td></tr>")
.arg(it.key(), it.data());
}
detailStr += "</tbody></table></qt>";
m_detail->setText(detailStr);
setMainWidget(m_vbox);
setDetailsWidget(m_detail);
m_hbox->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed);
// m_vbox->setMargin(KDialogBase::marginHint());
m_icon->setMargin(KDialogBase::spacingHint());
m_text->setMargin(KDialogBase::spacingHint());
raise();
}
TDEPermissionDialog::~TDEPermissionDialog()
{
}
void TDEPermissionDialog::appendWidget(TQWidget *widget)
{
m_vbox->hide();
widget->reparent(m_vbox, TQPoint());
m_vbox->show();
}

@ -0,0 +1,54 @@
/*******************************************************************************
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 __PERMISSION_DIALOG_H
#define __PERMISSION_DIALOG_H
// TDE
#include <kdialogbase.h>
typedef TQMap<TQString, TQString> Dictionary;
class TQVBox;
class TQHBox;
class TQLabel;
class TDEPermissionDialog : public KDialogBase
{
TQ_OBJECT
public:
TDEPermissionDialog(TQString application, TQString feature,
TQString icon = "messagebox_question",
Dictionary details = {});
virtual ~TDEPermissionDialog();
void appendWidget(TQWidget *widget);
private:
TQVBox *m_vbox;
TQHBox *m_hbox;
TQLabel *m_icon;
TQLabel *m_text;
TQLabel *m_detail;
};
#endif // __PERMISSION_DIALOG_H

@ -30,8 +30,9 @@
#include <kdebug.h> #include <kdebug.h>
// Portal // Portal
#include "file_chooser_portal.h" #include "account_portal.h"
#include "email_portal.h" #include "email_portal.h"
#include "file_chooser_portal.h"
#include "portal_service.h" #include "portal_service.h"
@ -44,16 +45,18 @@ DesktopNodeService::DesktopNodeService(TQT_DBusConnection &connection)
{ {
m_interfaces.insert("org.freedesktop.DBus.Introspectable", this); m_interfaces.insert("org.freedesktop.DBus.Introspectable", this);
REGISTER_PORTAL(TDEFileChooserPortal) REGISTER_PORTAL(TDEAccountPortal)
REGISTER_PORTAL(TDEEmailPortal) REGISTER_PORTAL(TDEEmailPortal)
REGISTER_PORTAL(TDEFileChooserPortal)
registerObject(connection, dbusObjectPath); registerObject(connection, dbusObjectPath);
} }
DesktopNodeService::~DesktopNodeService() DesktopNodeService::~DesktopNodeService()
{ {
DESTROY_PORTAL(TDEFileChooserPortal) DESTROY_PORTAL(TDEAccountPortal)
DESTROY_PORTAL(TDEEmailPortal) DESTROY_PORTAL(TDEEmailPortal)
DESTROY_PORTAL(TDEFileChooserPortal)
} }
TQT_DBusObjectBase* DesktopNodeService::createInterface(const TQString& iface) TQT_DBusObjectBase* DesktopNodeService::createInterface(const TQString& iface)

@ -19,12 +19,66 @@
Improvements and feedback are welcome! Improvements and feedback are welcome!
*******************************************************************************/ *******************************************************************************/
// TQt
#include <tqfileinfo.h>
// TDE // TDE
#include <kservice.h>
#include <kdebug.h> #include <kdebug.h>
// Portal // Portal
#include "util.h" #include "util.h"
WId parse_window_id(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;
}
ApplicationInfo application_info_from_wid(WId wid)
{
ApplicationInfo app;
if (wid)
{
// we need to get the pid but only deprecated KWin::Info has it
KWin::Info info = KWin::info(wid);
TQFileInfo fi(TQString("/proc/%1/exe").arg(info.pid));
if (fi.exists() && fi.isSymLink()) {
fi = TQFileInfo(fi.readLink());
app.path = fi.filePath();
// try to find corresponding desktop file
KService::List all = KService::allServices();
KService::List::ConstIterator svc;
for (svc = all.begin(); svc != all.end(); ++svc) {
TQString exec((*svc)->exec());
if (exec.startsWith(fi.filePath()) ||
exec.startsWith(fi.fileName()))
{
app.desktopFile = (*svc)->desktopEntryPath();
app.name = (*svc)->name();
break;
}
}
// Last resort
if (app.name.isEmpty())
app.name = fi.fileName();
}
}
return app;
}
bool check_variant(TQT_DBusVariant variant, TQString signature) bool check_variant(TQT_DBusVariant variant, TQString signature)
{ {
return !variant.signature.isNull() && variant.signature == signature; return !variant.signature.isNull() && variant.signature == signature;

@ -26,6 +26,7 @@
#include <tqdbusvariant.h> #include <tqdbusvariant.h>
#include <tqdbusdatalist.h> #include <tqdbusdatalist.h>
#include <tqvariant.h> #include <tqvariant.h>
#include <twin.h>
// TDE // TDE
#include <kurl.h> #include <kurl.h>
@ -33,6 +34,18 @@
typedef TQMap<TQString, TQT_DBusVariant> TQT_DBusVariantMap; typedef TQMap<TQString, TQT_DBusVariant> TQT_DBusVariantMap;
typedef TQValueList<TQT_DBusData> TQT_DBusValueList; typedef TQValueList<TQT_DBusData> TQT_DBusValueList;
struct ApplicationInfo
{
TQString name;
TQString path;
TQString desktopFile;
int pid;
};
extern WId parse_window_id(const TQString data);
extern ApplicationInfo application_info_from_wid(WId wid);
extern bool check_variant(TQT_DBusVariant variant, TQString signature); extern bool check_variant(TQT_DBusVariant variant, TQString signature);
extern TQString bytelist_to_string(TQT_DBusDataList list); extern TQString bytelist_to_string(TQT_DBusDataList list);

Loading…
Cancel
Save