on xenial help sign in
Watch for user real name updates in greeter
9aee0c9Michael Terry
plugins/IntegratedLightDM/liblightdm/CMakeLists.txt+6−2
@@ -1,10 +1,13 @@
1pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
1pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2
2
3+add_definitions(-DSM_BUSNAME=systemBus)
4+
3set(LibLightDM_SOURCES
5set(LibLightDM_SOURCES
4 Greeter.cpp
6 Greeter.cpp
5 UsersModel.cpp
7 UsersModel.cpp
6 GreeterPrivate.cpp
8 GreeterPrivate.cpp
7 UsersModelPrivate.cpp
9 UsersModelPrivate.cpp
10+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
11 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
12 )
10
13
@@ -12,6 +15,7 @@ add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
12add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
15add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
13
16
14include_directories(
17include_directories(
18+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
15 ${CMAKE_CURRENT_BINARY_DIR}
19 ${CMAKE_CURRENT_BINARY_DIR}
16 ${GLIB_INCLUDE_DIRS}
20 ${GLIB_INCLUDE_DIRS}
17 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
21 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
@@ -28,8 +32,8 @@ target_link_libraries(MockLightDM-demo-shared
28 -lpam
32 -lpam
29)
33)
30
34
31−qt5_use_modules(integratedLightDM Concurrent Gui)
35+qt5_use_modules(integratedLightDM Concurrent DBus Gui)
32−qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
36+qt5_use_modules(MockLightDM-demo-shared Concurrent DBus Gui)
33
37
34set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
38set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
35set_target_properties(MockLightDM-demo-shared PROPERTIES
39set_target_properties(MockLightDM-demo-shared PROPERTIES
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp+4−18
@@ -54,24 +54,10 @@ UsersModel::UsersModel(QObject *parent) :
54 roles[ImagePathRole] = "imagePath";
54 roles[ImagePathRole] = "imagePath";
55 setRoleNames(roles);
55 setRoleNames(roles);
56
56
57− // Now modify our mock user backgrounds
57+ connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
58− QDir bgdir = QDir(QStringLiteral("/usr/share/demo-assets/shell/backgrounds/"));
58+ QModelIndex index = createIndex(i, 0);
59− QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
59+ Q_EMIT dataChanged(index, index);
60−
60+ });
61− for (int i = 0, j = 0; i < d->entries.size(); i++) {
62− Entry &entry = d->entries[i];
63− if (entry.background.isNull() && !backgrounds.isEmpty()) {
64− entry.background = bgdir.filePath(backgrounds[j++]);
65− if (j >= backgrounds.length()) {
66− j = 0;
67− }
68− }
69− }
70−}
71−
72−UsersModel::~UsersModel()
73−{
74− delete d_ptr;
75}
61}
76
62
77int UsersModel::rowCount(const QModelIndex &parent) const
63int UsersModel::rowCount(const QModelIndex &parent) const
plugins/IntegratedLightDM/liblightdm/UsersModel.h+1−1
@@ -41,7 +41,7 @@ class Q_DECL_EXPORT UsersModel : public QAbstractListModel
41
41
42public:
42public:
43 explicit UsersModel(QObject *parent = 0);
43 explicit UsersModel(QObject *parent = 0);
44− virtual ~UsersModel();
44+ virtual ~UsersModel() = default;
45
45
46 enum UserModelRoles {NameRole = Qt::UserRole,
46 enum UserModelRoles {NameRole = Qt::UserRole,
47 RealNameRole,
47 RealNameRole,
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+43−9
@@ -18,7 +18,10 @@
18
18
19#include "UsersModelPrivate.h"
19#include "UsersModelPrivate.h"
20
20
21+#include "AccountsServiceDBusAdaptor.h"
22+
21#include <glib.h>
23#include <glib.h>
24+#include <QDebug>
22#include <QDir>
25#include <QDir>
23#include <QSettings>
26#include <QSettings>
24#include <QStringList>
27#include <QStringList>
@@ -27,7 +30,9 @@ namespace QLightDM
27{
30{
28
31
29UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
32UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
33+ : QObject((QObject*)parent),
30− : q_ptr(parent)
34+ q_ptr(parent),
35+ m_service(new AccountsServiceDBusAdaptor(this))
31{
36{
32 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
37 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
33 QString currentUser = g_get_user_name();
38 QString currentUser = g_get_user_name();
@@ -43,15 +48,44 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
43 entries.append({user, name, 0, 0, false, false, 0, 0});
48 entries.append({user, name, 0, 0, false, false, 0, 0});
44 }
49 }
45 } else {
50 } else {
46− // If we were using the actual liblightdm, we could just ask it
51+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
47− // for the user's real name. But we aren't. We *should* ask
52+
48− // AccountsService for the real name, like liblightdm does internally,
53+ connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
49− // but this is close enough since AS and passwd are always in sync.
54+ this, [this](const QString &user) {
50− QString realName = QString::fromUtf8(g_get_real_name()); // gets name from passwd entry
55+ if (user == entries[0].username) {
51− if (realName == QStringLiteral("Unknown")) { // glib doesn't translate this string
56+ updateName(true);
52− realName.clear();
57+ }
58+ });
59+ updateName(false);
60+ }
61+}
62+
63+void UsersModelPrivate::updateName(bool async)
64+{
65+ auto pendingReply = m_service->getUserPropertyAsync(entries[0].username,
66+ QStringLiteral("org.freedesktop.Accounts.User"),
67+ QStringLiteral("RealName"));
68+ auto *watcher = new QDBusPendingCallWatcher(pendingReply, this);
69+
70+ connect(watcher, &QDBusPendingCallWatcher::finished,
71+ this, [this](QDBusPendingCallWatcher* watcher) {
72+
73+ QDBusPendingReply<QVariant> reply = *watcher;
74+ watcher->deleteLater();
75+ if (reply.isError()) {
76+ qWarning() << "Failed to get 'RealName' property - " << reply.error().message();
77+ return;
78+ }
79+
80+ const QString realName = reply.value().toString();
81+ if (entries[0].real_name != realName) {
82+ entries[0].real_name = realName;
83+ Q_EMIT dataChanged(0);
53 }
84 }
54− entries.append({currentUser, realName, 0, 0, false, false, 0, 0});
85+ });
86+ if (!async) {
87+ watcher->waitForFinished();
88+ delete watcher;
55 }
89 }
56}
90}
57
91
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h+15−3
@@ -19,8 +19,11 @@
19#ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
19#ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
20#define UNITY_MOCK_USERSMODEL_PRIVATE_H
20#define UNITY_MOCK_USERSMODEL_PRIVATE_H
21
21
22−#include <QtCore/QList>
22+#include <QList>
23−#include <QtCore/QString>
23+#include <QObject>
24+#include <QString>
25+
26+class AccountsServiceDBusAdaptor;
24
27
25namespace QLightDM
28namespace QLightDM
26{
29{
@@ -39,19 +42,28 @@ public:
39 QString infographic;
42 QString infographic;
40};
43};
41
44
42−class UsersModelPrivate
45+class UsersModelPrivate : public QObject
43{
46{
47+ Q_OBJECT
48+
44public:
49public:
45 explicit UsersModelPrivate(UsersModel *parent = 0);
50 explicit UsersModelPrivate(UsersModel *parent = 0);
46 virtual ~UsersModelPrivate() = default;
51 virtual ~UsersModelPrivate() = default;
47
52
48 QList<Entry> entries;
53 QList<Entry> entries;
49
54
55+Q_SIGNALS:
56+ void dataChanged(int);
57+
50protected:
58protected:
51 UsersModel * const q_ptr;
59 UsersModel * const q_ptr;
52
60
53private:
61private:
54 Q_DECLARE_PUBLIC(UsersModel)
62 Q_DECLARE_PUBLIC(UsersModel)
63+
64+ void updateName(bool async);
65+
66+ AccountsServiceDBusAdaptor *m_service;
55};
67};
56
68
57}
69}
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp−14
@@ -47,20 +47,6 @@ UsersModel::UsersModel(QObject *parent) :
47 roles[HasMessagesRole] = "hasMessages";
47 roles[HasMessagesRole] = "hasMessages";
48 roles[ImagePathRole] = "imagePath";
48 roles[ImagePathRole] = "imagePath";
49 setRoleNames(roles);
49 setRoleNames(roles);
50−
51− // Now modify our mock user backgrounds
52− QDir bgdir = QDir("/usr/share/demo-assets/shell/backgrounds/");
53− QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
54−
55− for (int i = 0, j = 0; i < d->entries.size(); i++) {
56− Entry &entry = d->entries[i];
57− if (entry.background.isNull() && !backgrounds.isEmpty()) {
58− entry.background = bgdir.filePath(backgrounds[j++]);
59− if (j >= backgrounds.length()) {
60− j = 0;
61− }
62− }
63− }
64}
50}
65
51
66UsersModel::~UsersModel()
52UsersModel::~UsersModel()