on xenial help sign in
Merge greeter-guest
commitea4893efe8ed27686da50f0cf4d303d1c15a4f8b authorMichael Terry <mike@mterry.name> dateWed 11 Jan 2017, 13:37 (10 years ago) parent217d68c57e7dc8
6 files changed+126−78
plugins/LightDM/UsersModel.cpp+85−58 plugins/LightDM/UsersModel.h+2−11 tests/mocks/AccountsService/AccountsService.cpp+2−2 tests/mocks/liblightdm/MockUsersModel.cpp+2 tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+1−3 tests/plugins/LightDM/IntegratedLightDM/usersmodel.cpp+34−4
plugins/LightDM/UsersModel.cpp+85−58
@@ -12,23 +12,22 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#include "Greeter.h"
2018#include "UsersModel.h"
19+#include <QIdentityProxyModel>
2120#include <QLightDM/UsersModel>
22−#include <QtCore/QSortFilterProxyModel>
2321
2422#include <libintl.h>
2523
2624// First, we define an internal class that wraps LightDM's UsersModel. This
2725// class will modify some of the data coming from LightDM. For example, we
28−// modify any empty Real Names into just normal Names.
26+// modify any empty Real Names into just normal Names. We also add optional
27+// rows, depending on configuration.
2928// (We can't modify the data directly in UsersModel below because it won't sort
3029// using the modified data.)
31−class MangleModel : public QSortFilterProxyModel
30+class MangleModel : public QIdentityProxyModel
3231{
3332 Q_OBJECT
3433
@@ -36,21 +35,66 @@ public:
3635 explicit MangleModel(QObject* parent=0);
3736
3837 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
38+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
39+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
40+
41+private:
42+ int manualRow() const;
43+ int guestRow() const;
44+
45+ void updateShowManual();
46+
47+ bool m_showManual;
3948};
4049
4150MangleModel::MangleModel(QObject* parent)
42− : QSortFilterProxyModel(parent)
51+ : QIdentityProxyModel(parent)
52+ , m_showManual(false)
4353{
44− setSourceModel(new QLightDM::UsersModel(this));
54+ if (!Greeter::instance()->hideUsersHint()) {
55+ setSourceModel(new QLightDM::UsersModel(this));
56+ }
57+
58+ updateShowManual();
59+
60+ connect(this, &QIdentityProxyModel::modelReset,
61+ this, &MangleModel::updateShowManual);
62+ connect(this, &QIdentityProxyModel::rowsInserted,
63+ this, &MangleModel::updateShowManual);
64+ connect(this, &QIdentityProxyModel::rowsRemoved,
65+ this, &MangleModel::updateShowManual);
4566}
4667
4768QVariant MangleModel::data(const QModelIndex &index, int role) const
4869{
49− QVariant variantData = QSortFilterProxyModel::data(index, role);
70+ QVariant variantData;
71+
72+ if (index.row() == manualRow() && index.column() == 0) {
73+ switch (role) {
74+ case QLightDM::UsersModel::NameRole: return QStringLiteral("*other");
75+ case QLightDM::UsersModel::RealNameRole: return gettext("Login");
76+ case QLightDM::UsersModel::LoggedInRole: return false;
77+ case QLightDM::UsersModel::SessionRole: return Greeter::instance()->defaultSessionHint();
78+ default: return QVariant();
79+ }
80+ } else if (index.row() == guestRow() && index.column() == 0) {
81+ switch (role) {
82+ case QLightDM::UsersModel::NameRole:
83+ variantData = QStringLiteral("*guest"); break;
84+ case QLightDM::UsersModel::RealNameRole:
85+ variantData = gettext("Guest Session"); break;
86+ case QLightDM::UsersModel::LoggedInRole:
87+ variantData = false; break;
88+ case QLightDM::UsersModel::SessionRole:
89+ variantData = Greeter::instance()->defaultSessionHint(); break;
90+ }
91+ } else {
92+ variantData = QIdentityProxyModel::data(index, role);
93+ }
5094
5195 // If user's real name is empty, switch to unix name
5296 if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
53− variantData = QSortFilterProxyModel::data(index, QLightDM::UsersModel::NameRole);
97+ variantData = QIdentityProxyModel::data(index, QLightDM::UsersModel::NameRole);
5498 } else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
5599 const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
56100 variantData = stringData;
@@ -59,34 +103,15 @@ QVariant MangleModel::data(const QModelIndex &index, int role) const
59103 return variantData;
60104}
61105
62−// **** Now we continue with actual UsersModel class ****
63−
64−UsersModel::UsersModel(QObject* parent)
65− : UnitySortFilterProxyModelQML(parent)
66− , m_showManual(false)
67−{
68− if (!Greeter::instance()->hideUsersHint()) {
69− setModel(new MangleModel(this));
70− }
71− setSortCaseSensitivity(Qt::CaseInsensitive);
72− setSortLocaleAware(true);
73− setSortRole(QLightDM::UsersModel::RealNameRole);
74− sort(0);
75−
76− connect(this, &UnitySortFilterProxyModelQML::countChanged,
77− this, &UsersModel::updateShowManual);
78− updateShowManual();
79−}
80−
81−void UsersModel::updateShowManual()
106+void MangleModel::updateShowManual()
82107{
83108 // Show manual login if we are asked to OR if no other entry exists
84109 bool showManual = Greeter::instance()->showManualLoginHint() ||
85− (QSortFilterProxyModel::rowCount() == 0 &&
110+ (QIdentityProxyModel::rowCount() == 0 &&
86111 !Greeter::instance()->hasGuestAccount());
87112
88113 if (m_showManual != showManual) {
89− int row = QSortFilterProxyModel::rowCount();
114+ int row = QIdentityProxyModel::rowCount();
90115 if (showManual)
91116 beginInsertRows(QModelIndex(), row, row);
92117 else
@@ -101,29 +126,29 @@ void UsersModel::updateShowManual()
101126 }
102127}
103128
104−int UsersModel::manualRow() const
129+int MangleModel::manualRow() const
105130{
106131 if (!m_showManual)
107132 return -1;
108133
109− return QSortFilterProxyModel::rowCount();
134+ return QIdentityProxyModel::rowCount();
110135}
111136
112−int UsersModel::guestRow() const
137+int MangleModel::guestRow() const
113138{
114139 if (!Greeter::instance()->hasGuestAccount())
115140 return -1;
116141
117− int row = QSortFilterProxyModel::rowCount();
142+ int row = QIdentityProxyModel::rowCount();
118143 if (m_showManual)
119144 row++;
120145
121146 return row;
122147}
123148
124−int UsersModel::rowCount(const QModelIndex &parent) const
149+int MangleModel::rowCount(const QModelIndex &parent) const
125150{
126− auto count = UnitySortFilterProxyModelQML::rowCount(parent);
151+ auto count = QIdentityProxyModel::rowCount(parent);
127152
128153 if (m_showManual && !parent.isValid())
129154 count++;
@@ -133,36 +158,38 @@ int UsersModel::rowCount(const QModelIndex &parent) const
133158 return count;
134159}
135160
136−QModelIndex UsersModel::index(int row, int column, const QModelIndex &parent) const
161+QModelIndex MangleModel::index(int row, int column, const QModelIndex &parent) const
137162{
138163 if ((row == manualRow() || row == guestRow()) && !parent.isValid()) {
139164 return createIndex(row, column);
140165 } else {
141− return UnitySortFilterProxyModelQML::index(row, column, parent);
166+ return QIdentityProxyModel::index(row, column, parent);
142167 }
143168}
144169
145−QVariant UsersModel::data(const QModelIndex &index, int role) const
170+// **** Now we continue with actual UsersModel class ****
171+
172+UsersModel::UsersModel(QObject* parent)
173+ : UnitySortFilterProxyModelQML(parent)
146174{
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− }
155− } else if (index.row() == guestRow() && index.column() == 0) {
156− switch (role) {
157− case QLightDM::UsersModel::NameRole: return QStringLiteral("*guest");
158− case QLightDM::UsersModel::RealNameRole: return gettext("Guest Session");
159− case QLightDM::UsersModel::LoggedInRole: return false;
160− case QLightDM::UsersModel::SessionRole: return Greeter::instance()->defaultSessionHint();
161− default: return QVariant();
162− }
163− }
175+ setModel(new MangleModel(this));
176+ setSortCaseSensitivity(Qt::CaseInsensitive);
177+ setSortLocaleAware(true);
178+ setSortRole(QLightDM::UsersModel::RealNameRole);
179+ sort(0);
180+}
181+
182+bool UsersModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
183+{
184+ auto leftName = source_left.data(QLightDM::UsersModel::NameRole);
185+ auto rightName = source_right.data(QLightDM::UsersModel::NameRole);
186+
187+ if (leftName == QStringLiteral("*guest"))
188+ return false;
189+ if (rightName == QStringLiteral("*guest"))
190+ return true;
164191
165− return QSortFilterProxyModel::data(index, role);
192+ return UnitySortFilterProxyModelQML::lessThan(source_left, source_right);
166193}
167194
168195#include "UsersModel.moc"
plugins/LightDM/UsersModel.h+2−11
@@ -30,15 +30,6 @@ class UsersModel : public UnitySortFilterProxyModelQML
3030public:
3131 explicit UsersModel(QObject* parent=0);
3232
33− int rowCount(const QModelIndex &parent = QModelIndex()) const override;
34− QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
35− QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
36−
37−private:
38− int manualRow() const;
39− int guestRow() const;
40−
41− void updateShowManual();
42−
43− bool m_showManual;
33+protected:
34+ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
4435};
tests/mocks/AccountsService/AccountsService.cpp+2−2
@@ -121,8 +121,8 @@ QString AccountsService::backgroundFile() const
121121
122122 // Check if our mock user has a background set in liblightdm
123123 for (int i = 0; i < m_usersModel->count(); i++) {
124− if (m_usersModel->data(m_usersModel->index(i, 0), QLightDM::UsersModel::NameRole) == m_user) {
125− return m_usersModel->data(m_usersModel->index(i, 0), QLightDM::UsersModel::BackgroundPathRole).toString();
124+ if (m_usersModel->data(i, QLightDM::UsersModel::NameRole) == m_user) {
125+ return m_usersModel->data(i, QLightDM::UsersModel::BackgroundPathRole).toString();
126126 }
127127 }
128128
tests/mocks/liblightdm/MockUsersModel.cpp+2
@@ -65,6 +65,8 @@ UsersModel::UsersModel(QObject *parent)
6565 roles[UidRole] = "uid";
6666 setRoleNames(roles);
6767
68+ connect(MockController::instance(), &MockController::hasGuestAccountHintChanged,
69+ this, &UsersModel::resetEntries);
6870 connect(MockController::instance(), &MockController::userModeChanged,
6971 this, &UsersModel::resetEntries);
7072 resetEntries();
tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+1−3
@@ -20,7 +20,6 @@ target_link_libraries(GreeterDBusTestExec
2020 )
2121target_include_directories(GreeterDBusTestExec PUBLIC
2222 ${CMAKE_SOURCE_DIR}/plugins/LightDM
23− ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM/IntegratedLightDM
2423 )
2524add_unity8_uitest(GreeterDBus dbus-test-runner
2625 ARG_PREFIX "--parameter"
@@ -57,7 +56,6 @@ target_link_libraries(GreeterSessionsModelTestExec
5756target_include_directories(GreeterSessionsModelTestExec PUBLIC
5857 ${CMAKE_SOURCE_DIR}/plugins/LightDM
5958 ${CMAKE_SOURCE_DIR}/plugins/Utils
60− ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM/IntegratedLightDM
6159 ${CMAKE_SOURCE_DIR}/tests/mocks/liblightdm/
6260 )
6361add_unity8_uitest(GreeterSessions GreeterSessionsModelTestExec
@@ -81,7 +79,7 @@ target_link_libraries(GreeterUsersModelTestExec
8179target_include_directories(GreeterUsersModelTestExec PUBLIC
8280 ${CMAKE_SOURCE_DIR}/plugins/LightDM
8381 ${CMAKE_SOURCE_DIR}/plugins/Utils
84− ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM/IntegratedLightDM
82+ ${CMAKE_SOURCE_DIR}/tests/mocks/liblightdm
8583 )
8684add_unity8_uitest(GreeterUsers GreeterUsersModelTestExec
8785 DEPENDS MockLightDM
tests/plugins/LightDM/IntegratedLightDM/usersmodel.cpp+34−4
@@ -14,6 +14,8 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17+#include "Greeter.h"
18+#include "MockController.h"
1719#include "UsersModel.h"
1820
1921#include <QLightDM/UsersModel>
@@ -40,17 +42,23 @@ private:
4042 return model->data(model->index(i, 0), role).toString();
4143 }
4244
45+ void recreateModel()
46+ {
47+ delete model;
48+ model = new UsersModel();
49+ QVERIFY(model);
50+ }
51+
4352private Q_SLOTS:
4453
4554 void init()
4655 {
47− model = new UsersModel();
48− QVERIFY(model);
56+ recreateModel();
4957 }
5058
5159 void cleanup()
5260 {
53− delete model;
61+ QLightDM::MockController::instance()->reset();
5462 }
5563
5664 void testMangleColor()
@@ -65,8 +73,30 @@ private Q_SLOTS:
6573 QVERIFY(name == "empty-name");
6674 }
6775
76+ void testHasGuest()
77+ {
78+ // sanity check that it doesn't start already present
79+ QCOMPARE(findName(model, QStringLiteral("*guest")), -1);
80+
81+ QLightDM::MockController::instance()->setHasGuestAccountHint(true);
82+ recreateModel();
83+
84+ int i = findName(model, QStringLiteral("*guest"));
85+ QVERIFY(i >= 0);
86+ QCOMPARE(i, model->count() - 1);
87+
88+ auto realName = model->data(i, QLightDM::UsersModel::RealNameRole).toString();
89+ QCOMPARE(realName, QStringLiteral("Guest Session"));
90+
91+ auto loggedIn = model->data(i, QLightDM::UsersModel::LoggedInRole).toBool();
92+ QVERIFY(!loggedIn);
93+
94+ auto session = model->data(i, QLightDM::UsersModel::SessionRole).toString();
95+ QCOMPARE(session, Greeter::instance()->defaultSessionHint());
96+ }
97+
6898private:
69− UsersModel *model;
99+ UsersModel *model = nullptr;
70100};
71101
72102QTEST_MAIN(GreeterUsersModelTest)