13
13
* You should have received a copy of the GNU General Public License
14
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Author: Michael Terry <michael.terry@canonical.com>
19
18
#include "UsersModel.h"
19
#include <QIdentityProxyModel>
20
20
#include <QLightDM/UsersModel>
21
#include <QtCore/QSortFilterProxyModel>
23
24
// First, we define an internal class that wraps LightDM's UsersModel. This
24
25
// class will modify some of the data coming from LightDM. For example, we
25
// 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.
26
28
// (We can't modify the data directly in UsersModel below because it won't sort
27
29
// using the modified data.)
28
class MangleModel : public QSortFilterProxyModel
30
class MangleModel : public QIdentityProxyModel
33
35
explicit MangleModel(QObject* parent=0);
35
37
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;
47
int sourceRowCount() const;
49
void updateGuestRow();
50
void updateManualRow();
51
void updateCustomRows();
53
void addCustomRow(const CustomRow &newRow);
54
void removeCustomRow(const QString &rowName);
56
QList<CustomRow> m_customRows;
57
bool m_updatingCustomRows;
38
60
MangleModel::MangleModel(QObject* parent)
39
: QSortFilterProxyModel(parent)
61
: QIdentityProxyModel(parent)
62
, m_updatingCustomRows(false)
41
64
setSourceModel(new QLightDM::UsersModel(this));
68
// Would be nice if there were a rowCountChanged signal in the base class.
69
// We redo all custom rows on any row count change, because (A) some of
70
// custom rows (manual login) use row count information and (B) when
71
// testing, we use a modelReset signal as a way to indicate that a custom
72
// row has been toggled off or on.
73
connect(this, &QIdentityProxyModel::modelReset,
74
this, &MangleModel::updateCustomRows);
75
connect(this, &QIdentityProxyModel::rowsInserted,
76
this, &MangleModel::updateCustomRows);
77
connect(this, &QIdentityProxyModel::rowsRemoved,
78
this, &MangleModel::updateCustomRows);
44
81
QVariant MangleModel::data(const QModelIndex &index, int role) const
46
QVariant variantData = QSortFilterProxyModel::data(index, role);
85
if (index.row() >= rowCount())
88
bool isCustomRow = index.row() >= sourceRowCount();
89
if (isCustomRow && index.column() == 0) {
90
int customIndex = index.row() - sourceRowCount();
91
if (role == QLightDM::UsersModel::NameRole) {
92
variantData = m_customRows[customIndex].name;
93
} else if (role == QLightDM::UsersModel::RealNameRole) {
94
variantData = m_customRows[customIndex].realName;
95
} else if (role == QLightDM::UsersModel::LoggedInRole) {
97
} else if (role == QLightDM::UsersModel::SessionRole) {
98
variantData = Greeter::instance()->defaultSessionHint();
101
variantData = QIdentityProxyModel::data(index, role);
48
104
// If user's real name is empty, switch to unix name
49
105
if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
50
variantData = QSortFilterProxyModel::data(index, QLightDM::UsersModel::NameRole);
106
variantData = data(index, QLightDM::UsersModel::NameRole);
51
107
} else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
52
108
const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
53
109
variantData = stringData;
56
112
return variantData;
115
void MangleModel::addCustomRow(const CustomRow &newRow)
117
for (int i = 0; i < m_customRows.size(); i++) {
118
if (m_customRows[i].name == newRow.name) {
119
return; // we don't have custom rows that change content yet
123
beginInsertRows(QModelIndex(), rowCount(), rowCount());
124
m_customRows << newRow;
128
void MangleModel::removeCustomRow(const QString &rowName)
130
for (int i = 0; i < m_customRows.size(); i++) {
131
if (m_customRows[i].name == rowName) {
132
int rowNum = sourceRowCount() + i;
133
beginRemoveRows(QModelIndex(), rowNum, rowNum);
134
m_customRows.removeAt(i);
141
void MangleModel::updateManualRow()
143
bool hasAnotherEntry = sourceRowCount() > 0;
144
for (int i = 0; !hasAnotherEntry && i < m_customRows.size(); i++) {
145
if (m_customRows[i].name != QStringLiteral("*other")) {
146
hasAnotherEntry = true;
150
// Show manual login if we are asked to OR if no other entry exists
151
if (Greeter::instance()->showManualLoginHint() || !hasAnotherEntry)
152
addCustomRow({QStringLiteral("*other"), gettext("Login")});
154
removeCustomRow(QStringLiteral("*other"));
157
void MangleModel::updateGuestRow()
159
if (Greeter::instance()->hasGuestAccount())
160
addCustomRow({QStringLiteral("*guest"), gettext("Guest Session")});
162
removeCustomRow(QStringLiteral("*guest"));
165
void MangleModel::updateCustomRows()
167
// We update when rowCount changes, but we also insert/remove rows here.
168
// So guard this function to avoid recursion.
169
if (m_updatingCustomRows)
172
m_updatingCustomRows = true;
175
m_updatingCustomRows = false;
178
int MangleModel::rowCount(const QModelIndex &parent) const
180
if (parent.isValid())
183
return sourceRowCount() + m_customRows.size();
186
int MangleModel::sourceRowCount() const
188
return Greeter::instance()->hideUsersHint() ? 0 : sourceModel()->rowCount();
191
QModelIndex MangleModel::index(int row, int column, const QModelIndex &parent) const
193
if (row >= rowCount())
194
return QModelIndex();
196
bool isCustomRow = row >= sourceRowCount();
197
if (isCustomRow && !parent.isValid()) {
198
return createIndex(row, column);
200
return QIdentityProxyModel::index(row, column, parent);
59
204
// **** Now we continue with actual UsersModel class ****
61
206
UsersModel::UsersModel(QObject* parent)
216
bool UsersModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
218
auto leftName = source_left.data(QLightDM::UsersModel::NameRole);
219
auto rightName = source_right.data(QLightDM::UsersModel::NameRole);
221
if (leftName == QStringLiteral("*guest"))
223
if (rightName == QStringLiteral("*guest"))
225
if (leftName == QStringLiteral("*other"))
227
if (rightName == QStringLiteral("*other"))
230
return UnitySortFilterProxyModelQML::lessThan(source_left, source_right);
71
233
#include "UsersModel.moc"