on xenial help sign in
Support the lightdm manual-login hint
3182a1dMichael Terry
plugins/LightDM/Greeter.cpp+14
@@ -114,6 +114,18 @@ bool Greeter::hasGuestAccount() const
114 return d->m_greeter->hasGuestAccountHint();
114 return d->m_greeter->hasGuestAccountHint();
115}
115}
116
116
117+bool Greeter::showManualLoginHint() const
118+{
119+ Q_D(const Greeter);
120+ return d->m_greeter->showManualLoginHint();
121+}
122+
123+bool Greeter::hideUsersHint() const
124+{
125+ Q_D(const Greeter);
126+ return d->m_greeter->hideUsersHint();
127+}
128+
117void Greeter::authenticate(const QString &username)
129void Greeter::authenticate(const QString &username)
118{
130{
119 Q_D(Greeter);
131 Q_D(Greeter);
@@ -125,6 +137,8 @@ void Greeter::authenticate(const QString &username)
125
137
126 if (username == QStringLiteral("*guest")) {
138 if (username == QStringLiteral("*guest")) {
127 d->m_greeter->authenticateAsGuest();
139 d->m_greeter->authenticateAsGuest();
140+ } else if (username == QStringLiteral("*other")) {
141+ d->m_greeter->authenticate(nullptr);
128 } else {
142 } else {
129 d->m_greeter->authenticate(username);
143 d->m_greeter->authenticate(username);
130 }
144 }
plugins/LightDM/Greeter.h+2
@@ -50,6 +50,8 @@ public:
50 bool promptless() const;
50 bool promptless() const;
51 QString selectUser() const;
51 QString selectUser() const;
52 bool hasGuestAccount() const;
52 bool hasGuestAccount() const;
53+ bool showManualLoginHint() const;
54+ bool hideUsersHint() const;
53
55
54public Q_SLOTS:
56public Q_SLOTS:
55 void authenticate(const QString &username=QString());
57 void authenticate(const QString &username=QString());
plugins/LightDM/UsersModel.cpp+59−5
@@ -63,24 +63,70 @@ QVariant MangleModel::data(const QModelIndex &index, int role) const
63
63
64UsersModel::UsersModel(QObject* parent)
64UsersModel::UsersModel(QObject* parent)
65 : UnitySortFilterProxyModelQML(parent)
65 : UnitySortFilterProxyModelQML(parent)
66+ , m_showManual(false)
66{
67{
68+ if (!Greeter::instance()->hideUsersHint()) {
67− setModel(new MangleModel(this));
69+ setModel(new MangleModel(this));
70+ }
68 setSortCaseSensitivity(Qt::CaseInsensitive);
71 setSortCaseSensitivity(Qt::CaseInsensitive);
69 setSortLocaleAware(true);
72 setSortLocaleAware(true);
70 setSortRole(QLightDM::UsersModel::RealNameRole);
73 setSortRole(QLightDM::UsersModel::RealNameRole);
71 sort(0);
74 sort(0);
75+
76+ connect(this, &UnitySortFilterProxyModelQML::countChanged,
77+ this, &UsersModel::updateShowManual);
78+ updateShowManual();
79+}
80+
81+void UsersModel::updateShowManual()
82+{
83+ // Show manual login if we are asked to OR if no other entry exists
84+ bool showManual = Greeter::instance()->showManualLoginHint() ||
85+ (QSortFilterProxyModel::rowCount() == 0 &&
86+ !Greeter::instance()->hasGuestAccount());
87+
88+ if (m_showManual != showManual) {
89+ int row = QSortFilterProxyModel::rowCount();
90+ if (showManual)
91+ beginInsertRows(QModelIndex(), row, row);
92+ else
93+ beginRemoveRows(QModelIndex(), row, row);
94+
95+ m_showManual = showManual;
96+
97+ if (showManual)
98+ endInsertRows();
99+ else
100+ endRemoveRows();
101+ }
102+}
103+
104+int UsersModel::manualRow() const
105+{
106+ if (!m_showManual)
107+ return -1;
108+
109+ return QSortFilterProxyModel::rowCount();
72}
110}
73
111
74int UsersModel::guestRow() const
112int UsersModel::guestRow() const
75{
113{
76− return Greeter::instance()->hasGuestAccount() ?
114+ if (!Greeter::instance()->hasGuestAccount())
77− UnitySortFilterProxyModelQML::rowCount() : -1;
115+ return -1;
116+
117+ int row = QSortFilterProxyModel::rowCount();
118+ if (m_showManual)
119+ row++;
120+
121+ return row;
78}
122}
79
123
80int UsersModel::rowCount(const QModelIndex &parent) const
124int UsersModel::rowCount(const QModelIndex &parent) const
81{
125{
82 auto count = UnitySortFilterProxyModelQML::rowCount(parent);
126 auto count = UnitySortFilterProxyModelQML::rowCount(parent);
83
127
128+ if (m_showManual && !parent.isValid())
129+ count++;
84 if (Greeter::instance()->hasGuestAccount() && !parent.isValid())
130 if (Greeter::instance()->hasGuestAccount() && !parent.isValid())
85 count++;
131 count++;
86
132
@@ -89,7 +135,7 @@ int UsersModel::rowCount(const QModelIndex &parent) const
89
135
90QModelIndex UsersModel::index(int row, int column, const QModelIndex &parent) const
136QModelIndex UsersModel::index(int row, int column, const QModelIndex &parent) const
91{
137{
92− if (row == guestRow() && !parent.isValid()) {
138+ if ((row == manualRow() || row == guestRow()) && !parent.isValid()) {
93 return createIndex(row, column);
139 return createIndex(row, column);
94 } else {
140 } else {
95 return UnitySortFilterProxyModelQML::index(row, column, parent);
141 return UnitySortFilterProxyModelQML::index(row, column, parent);
@@ -98,7 +144,15 @@ QModelIndex UsersModel::index(int row, int column, const QModelIndex &parent) co
98
144
99QVariant UsersModel::data(const QModelIndex &index, int role) const
145QVariant UsersModel::data(const QModelIndex &index, int role) const
100{
146{
147+ if (index.row() == manualRow() && index.column() == 0) {
148+ switch (role) {
149+ case QLightDM::UsersModel::NameRole: return QStringLiteral("*other");
150+ case QLightDM::UsersModel::RealNameRole: return gettext("Login");
151+ case QLightDM::UsersModel::LoggedInRole: return false;
152+ case QLightDM::UsersModel::SessionRole: return Greeter::instance()->defaultSessionHint();
153+ default: return QVariant();
154+ }
101− if (index.row() == guestRow() && index.column() == 0) {
155+ } else if (index.row() == guestRow() && index.column() == 0) {
102 switch (role) {
156 switch (role) {
103 case QLightDM::UsersModel::NameRole: return QStringLiteral("*guest");
157 case QLightDM::UsersModel::NameRole: return QStringLiteral("*guest");
104 case QLightDM::UsersModel::RealNameRole: return gettext("Guest Session");
158 case QLightDM::UsersModel::RealNameRole: return gettext("Guest Session");
plugins/LightDM/UsersModel.h+5
@@ -35,5 +35,10 @@ public:
35 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
35 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
36
36
37private:
37private:
38+ int manualRow() const;
38 int guestRow() const;
39 int guestRow() const;
40+
41+ void updateShowManual();
42+
43+ bool m_showManual;
39};
44};
qml/Greeter/LoginList.qml+4−1
@@ -203,7 +203,10 @@ StyledItem {
203 // Add an offset to bottomMargin for any items below the highlight
203 // Add an offset to bottomMargin for any items below the highlight
204 bottomMargin: -(units.gu(4) + (parent.belowHighlight ? parent.belowOffset : 0))
204 bottomMargin: -(units.gu(4) + (parent.belowHighlight ? parent.belowOffset : 0))
205 }
205 }
206− text: realName
206+ text: userList.currentIndex === index
207+ && name === "*other"
208+ && LightDM.Greeter.authenticationUser !== ""
209+ ? LightDM.Greeter.authenticationUser : realName
207 color: userList.currentIndex !== index ? theme.palette.normal.raised
210 color: userList.currentIndex !== index ? theme.palette.normal.raised
208 : theme.palette.normal.raisedText
211 : theme.palette.normal.raisedText
209
212
tests/mocks/liblightdm/MockController.cpp+28
@@ -67,6 +67,8 @@ void MockController::reset()
67 setUserMode(userMode);
67 setUserMode(userMode);
68 setSessionMode("full");
68 setSessionMode("full");
69 setNumSessions(numFullSessions());
69 setNumSessions(numFullSessions());
70+ setShowManualLoginHint(false);
71+ setHideUsersHint(false);
70}
72}
71
73
72QString MockController::selectUserHint() const
74QString MockController::selectUserHint() const
@@ -108,6 +110,32 @@ void MockController::setHasGuestAccountHint(bool hasGuestAccountHint)
108 }
110 }
109}
111}
110
112
113+bool MockController::showManualLoginHint() const
114+{
115+ return m_showManualLoginHint;
116+}
117+
118+void MockController::setShowManualLoginHint(bool showManualLoginHint)
119+{
120+ if (m_showManualLoginHint != showManualLoginHint) {
121+ m_showManualLoginHint = showManualLoginHint;
122+ Q_EMIT showManualLoginHintChanged();
123+ }
124+}
125+
126+bool MockController::hideUsersHint() const
127+{
128+ return m_hideUsersHint;
129+}
130+
131+void MockController::setHideUsersHint(bool hideUsersHint)
132+{
133+ if (m_hideUsersHint != hideUsersHint) {
134+ m_hideUsersHint = hideUsersHint;
135+ Q_EMIT hideUsersHintChanged();
136+ }
137+}
138+
111QString MockController::userMode() const
139QString MockController::userMode() const
112{
140{
113 return m_userMode;
141 return m_userMode;
tests/mocks/liblightdm/MockController.h+12
@@ -29,6 +29,8 @@ class Q_DECL_EXPORT MockController : public QObject
29 Q_PROPERTY(QString selectUserHint READ selectUserHint WRITE setSelectUserHint NOTIFY selectUserHintChanged)
29 Q_PROPERTY(QString selectUserHint READ selectUserHint WRITE setSelectUserHint NOTIFY selectUserHintChanged)
30 Q_PROPERTY(bool selectGuestHint READ selectGuestHint WRITE setSelectGuestHint NOTIFY selectGuestHintChanged)
30 Q_PROPERTY(bool selectGuestHint READ selectGuestHint WRITE setSelectGuestHint NOTIFY selectGuestHintChanged)
31 Q_PROPERTY(bool hasGuestAccountHint READ hasGuestAccountHint WRITE setHasGuestAccountHint NOTIFY hasGuestAccountHintChanged)
31 Q_PROPERTY(bool hasGuestAccountHint READ hasGuestAccountHint WRITE setHasGuestAccountHint NOTIFY hasGuestAccountHintChanged)
32+ Q_PROPERTY(bool showManualLoginHint READ showManualLoginHint WRITE setShowManualLoginHint NOTIFY showManualLoginHintChanged)
33+ Q_PROPERTY(bool hideUsersHint READ hideUsersHint WRITE setHideUsersHint NOTIFY hideUsersHintChanged)
32
34
33 // single, single-pin, single-passphrase, full
35 // single, single-pin, single-passphrase, full
34 Q_PROPERTY(QString userMode READ userMode WRITE setUserMode NOTIFY userModeChanged)
36 Q_PROPERTY(QString userMode READ userMode WRITE setUserMode NOTIFY userModeChanged)
@@ -54,6 +56,12 @@ public:
54 bool hasGuestAccountHint() const;
56 bool hasGuestAccountHint() const;
55 void setHasGuestAccountHint(bool hasGuestAccountHint);
57 void setHasGuestAccountHint(bool hasGuestAccountHint);
56
58
59+ bool showManualLoginHint() const;
60+ void setShowManualLoginHint(bool showManualLoginHint);
61+
62+ bool hideUsersHint() const;
63+ void setHideUsersHint(bool hideUsersHint);
64+
57 QString userMode() const;
65 QString userMode() const;
58 void setUserMode(const QString &userMode);
66 void setUserMode(const QString &userMode);
59
67
@@ -76,6 +84,8 @@ Q_SIGNALS:
76 void selectUserHintChanged();
84 void selectUserHintChanged();
77 void selectGuestHintChanged();
85 void selectGuestHintChanged();
78 void hasGuestAccountHintChanged();
86 void hasGuestAccountHintChanged();
87+ void showManualLoginHintChanged();
88+ void hideUsersHintChanged();
79 void userModeChanged();
89 void userModeChanged();
80 void sessionModeChanged();
90 void sessionModeChanged();
81 void numSessionsChanged();
91 void numSessionsChanged();
@@ -86,6 +96,8 @@ private:
86 QString m_selectUserHint;
96 QString m_selectUserHint;
87 bool m_selectGuestHint;
97 bool m_selectGuestHint;
88 bool m_hasGuestAccountHint;
98 bool m_hasGuestAccountHint;
99+ bool m_showManualLoginHint;
100+ bool m_hideUsersHint;
89 QString m_userMode;
101 QString m_userMode;
90 QString m_sessionMode;
102 QString m_sessionMode;
91 QList<SessionItem> m_fullSessions;
103 QList<SessionItem> m_fullSessions;
tests/mocks/liblightdm/MockGreeter.cpp+15−3
@@ -67,17 +67,17 @@ QString Greeter::defaultSessionHint() const
67
67
68bool Greeter::hideUsersHint() const
68bool Greeter::hideUsersHint() const
69{
69{
70− return false;
70+ return MockController::instance()->hideUsersHint();
71}
71}
72
72
73bool Greeter::showManualLoginHint() const
73bool Greeter::showManualLoginHint() const
74{
74{
75− return true;
75+ return MockController::instance()->showManualLoginHint();
76}
76}
77
77
78bool Greeter::showRemoteLoginHint() const
78bool Greeter::showRemoteLoginHint() const
79{
79{
80− return true;
80+ return false;
81}
81}
82
82
83QString Greeter::selectUserHint() const
83QString Greeter::selectUserHint() const
@@ -141,6 +141,11 @@ void Greeter::handleAuthenticate()
141{
141{
142 Q_D(Greeter);
142 Q_D(Greeter);
143
143
144+ if (d->authenticationUser.isEmpty()) {
145+ Q_EMIT showPrompt("Username: ", Greeter::PromptTypeQuestion);
146+ return;
147+ }
148+
144 // Send out any messages we need to
149 // Send out any messages we need to
145 if (d->authenticationUser == "info-prompt")
150 if (d->authenticationUser == "info-prompt")
146 Q_EMIT showMessage("Welcome to Unity Greeter", Greeter::MessageTypeInfo);
151 Q_EMIT showMessage("Welcome to Unity Greeter", Greeter::MessageTypeInfo);
@@ -219,6 +224,13 @@ void Greeter::respond(const QString &response)
219{
224{
220 Q_D(Greeter);
225 Q_D(Greeter);
221
226
227+ if (d->authenticationUser.isEmpty()) {
228+ // A manual login, our first question was which username
229+ d->authenticationUser = response;
230+ handleAuthenticate();
231+ return;
232+ }
233+
222 if (d->authenticationUser == "no-response")
234 if (d->authenticationUser == "no-response")
223 return;
235 return;
224 else if (d->authenticationUser == "two-factor") {
236 else if (d->authenticationUser == "two-factor") {