@@ -36,11 +36,11 @@ AccountsService::AccountsService(QObject* parent)
36 connection, this);
36 connection, this);
39−QVariant AccountsService::getUserProperty(const QString &user, const QString &property)
39+QVariant AccountsService::getUserProperty(const QString &user, const QString &interface, const QString &property)
41 auto iface = getUserInterface(user);
41 auto iface = getUserInterface(user);
42 if (iface != nullptr && iface->isValid()) {
42 if (iface != nullptr && iface->isValid()) {
43− auto answer = iface->call("Get", "com.canonical.unity.AccountsService", property);
43+ auto answer = iface->call("Get", interface, property);
44 if (answer.type() == QDBusMessage::ReplyMessage) {
44 if (answer.type() == QDBusMessage::ReplyMessage) {
45 return answer.arguments()[0].value<QDBusVariant>().variant();
45 return answer.arguments()[0].value<QDBusVariant>().variant();
@@ -48,25 +48,77 @@ QVariant AccountsService::getUserProperty(const QString &user, const QString &pr
48 return QVariant();
48 return QVariant();
51−void AccountsService::setUserProperty(const QString &user, const QString &property, const QVariant &value)
51+void AccountsService::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
53 auto iface = getUserInterface(user);
53 auto iface = getUserInterface(user);
54 if (iface != nullptr && iface->isValid()) {
54 if (iface != nullptr && iface->isValid()) {
55 // The value needs to be carefully wrapped
55 // The value needs to be carefully wrapped
56− iface->call("Set", "com.canonical.unity.AccountsService", property, QVariant::fromValue(QDBusVariant(value)));
56+ iface->call("Set", interface, property, QVariant::fromValue(QDBusVariant(value)));
60+void AccountsService::propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
62+ // Merge changed and invalidated together
63+ QStringList combined;
65+ combined << changed.keys();
66+ combined.removeDuplicates();
68+ Q_EMIT propertiesChanged(getUserForPath(message().path()), interface, combined);
71+void AccountsService::maybeChangedSlot()
73+ Q_EMIT maybeChanged(getUserForPath(message().path()));
76+QString AccountsService::getUserForPath(const QString &path)
78+ QMap<QString, QDBusInterface *>::const_iterator i;
79+ for (i = users.constBegin(); i != users.constEnd(); ++i) {
80+ if (i.value()->path() == path) {
60QDBusInterface *AccountsService::getUserInterface(const QString &user)
87QDBusInterface *AccountsService::getUserInterface(const QString &user)
62 auto iface = users.value(user);
89 auto iface = users.value(user);
63 if (iface == nullptr && accounts_manager->isValid()) {
90 if (iface == nullptr && accounts_manager->isValid()) {
64 auto answer = accounts_manager->call("FindUserByName", user);
91 auto answer = accounts_manager->call("FindUserByName", user);
65 if (answer.type() == QDBusMessage::ReplyMessage) {
92 if (answer.type() == QDBusMessage::ReplyMessage) {
93+ auto path = answer.arguments()[0].value<QDBusObjectPath>().path();
66 iface = new QDBusInterface("org.freedesktop.Accounts",
95 iface = new QDBusInterface("org.freedesktop.Accounts",
67− answer.arguments()[0].value<QDBusObjectPath>().path(),
96+ path,
68 "org.freedesktop.DBus.Properties",
97 "org.freedesktop.DBus.Properties",
69 accounts_manager->connection(), this);
98 accounts_manager->connection(), this);
100+ // With its own pre-defined properties, AccountsService is oddly
101+ // close-lipped. It won't send out proper DBus.Properties notices,
102+ // but it does have one catch-all Changed() signal. So let's
104+ iface->connection().connect(
107+ "org.freedesktop.Accounts.User",
110+ SLOT(maybeChangedSlot()));
112+ // But custom properties do send out the right notifications, so
113+ // let's still listen there.
114+ iface->connection().connect(
117+ "org.freedesktop.DBus.Properties",
118+ "PropertiesChanged",
120+ SLOT(propertiesChangedSlot(QString, QVariantMap, QStringList)));
70 users.insert(user, iface);
122 users.insert(user, iface);