@@ -36,11 +36,11 @@ AccountsService::AccountsService(QObject* parent)
3636 connection, this);
3737}
3838
39−QVariant AccountsService::getUserProperty(const QString &user, const QString &property)
39+QVariant AccountsService::getUserProperty(const QString &user, const QString &interface, const QString &property)
4040{
4141 auto iface = getUserInterface(user);
4242 if (iface != nullptr && iface->isValid()) {
43− auto answer = iface->call("Get", "com.canonical.unity.AccountsService", property);
43+ auto answer = iface->call("Get", interface, property);
4444 if (answer.type() == QDBusMessage::ReplyMessage) {
4545 return answer.arguments()[0].value<QDBusVariant>().variant();
4646 }
@@ -48,25 +48,77 @@ QVariant AccountsService::getUserProperty(const QString &user, const QString &pr
4848 return QVariant();
4949}
5050
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)
5252{
5353 auto iface = getUserInterface(user);
5454 if (iface != nullptr && iface->isValid()) {
5555 // 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)));
5757 }
5858}
5959
60+void AccountsService::propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
61+{
62+ // Merge changed and invalidated together
63+ QStringList combined;
64+ combined << invalid;
65+ combined << changed.keys();
66+ combined.removeDuplicates();
67+
68+ Q_EMIT propertiesChanged(getUserForPath(message().path()), interface, combined);
69+}
70+
71+void AccountsService::maybeChangedSlot()
72+{
73+ Q_EMIT maybeChanged(getUserForPath(message().path()));
74+}
75+
76+QString AccountsService::getUserForPath(const QString &path)
77+{
78+ QMap<QString, QDBusInterface *>::const_iterator i;
79+ for (i = users.constBegin(); i != users.constEnd(); ++i) {
80+ if (i.value()->path() == path) {
81+ return i.key();
82+ }
83+ }
84+ return QString();
85+}
86+
6087QDBusInterface *AccountsService::getUserInterface(const QString &user)
6188{
6289 auto iface = users.value(user);
6390 if (iface == nullptr && accounts_manager->isValid()) {
6491 auto answer = accounts_manager->call("FindUserByName", user);
6592 if (answer.type() == QDBusMessage::ReplyMessage) {
93+ auto path = answer.arguments()[0].value<QDBusObjectPath>().path();
94+
6695 iface = new QDBusInterface("org.freedesktop.Accounts",
67− answer.arguments()[0].value<QDBusObjectPath>().path(),
96+ path,
6897 "org.freedesktop.DBus.Properties",
6998 accounts_manager->connection(), this);
99+
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
103+ // listen to that.
104+ iface->connection().connect(
105+ iface->service(),
106+ path,
107+ "org.freedesktop.Accounts.User",
108+ "Changed",
109+ this,
110+ SLOT(maybeChangedSlot()));
111+
112+ // But custom properties do send out the right notifications, so
113+ // let's still listen there.
114+ iface->connection().connect(
115+ iface->service(),
116+ path,
117+ "org.freedesktop.DBus.Properties",
118+ "PropertiesChanged",
119+ this,
120+ SLOT(propertiesChangedSlot(QString, QVariantMap, QStringList)));
121+
70122 users.insert(user, iface);
71123 }
72124 }