~lukas-kde/unity8/dashboard

« back to all changes in this revision

Viewing changes to plugins/LightDM/UsersModel.cpp

  • Committer: Lukáš Tinkl
  • Date: 2017-01-26 12:13:17 UTC
  • mfrom: (2749.1.49 unity8)
  • Revision ID: lukas.tinkl@canonical.com-20170126121317-qms39s9pikclidbe
merge trunk, fix conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2013 Canonical, Ltd.
 
2
 * Copyright (C) 2013,2015-2016 Canonical, Ltd.
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
5
5
 * it under the terms of the GNU General Public License as published by
12
12
 *
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/>.
15
 
 *
16
 
 * Author: Michael Terry <michael.terry@canonical.com>
17
15
 */
18
16
 
 
17
#include "Greeter.h"
19
18
#include "UsersModel.h"
 
19
#include <QIdentityProxyModel>
20
20
#include <QLightDM/UsersModel>
21
 
#include <QtCore/QSortFilterProxyModel>
 
21
 
 
22
#include <libintl.h>
22
23
 
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
29
31
{
30
32
    Q_OBJECT
31
33
 
33
35
    explicit MangleModel(QObject* parent=0);
34
36
 
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;
 
40
 
 
41
private:
 
42
    struct CustomRow {
 
43
        QString name;
 
44
        QString realName;
 
45
    };
 
46
 
 
47
    int sourceRowCount() const;
 
48
 
 
49
    void updateGuestRow();
 
50
    void updateManualRow();
 
51
    void updateCustomRows();
 
52
 
 
53
    void addCustomRow(const CustomRow &newRow);
 
54
    void removeCustomRow(const QString &rowName);
 
55
 
 
56
    QList<CustomRow> m_customRows;
 
57
    bool m_updatingCustomRows;
36
58
};
37
59
 
38
60
MangleModel::MangleModel(QObject* parent)
39
 
  : QSortFilterProxyModel(parent)
 
61
  : QIdentityProxyModel(parent)
 
62
  , m_updatingCustomRows(false)
40
63
{
41
64
    setSourceModel(new QLightDM::UsersModel(this));
 
65
 
 
66
    updateCustomRows();
 
67
 
 
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);
42
79
}
43
80
 
44
81
QVariant MangleModel::data(const QModelIndex &index, int role) const
45
82
{
46
 
    QVariant variantData = QSortFilterProxyModel::data(index, role);
 
83
    QVariant variantData;
 
84
 
 
85
    if (index.row() >= rowCount())
 
86
        return QVariant();
 
87
 
 
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) {
 
96
            variantData = false;
 
97
        } else if (role == QLightDM::UsersModel::SessionRole) {
 
98
            variantData = Greeter::instance()->defaultSessionHint();
 
99
        }
 
100
    } else {
 
101
        variantData = QIdentityProxyModel::data(index, role);
 
102
    }
47
103
 
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;
57
113
}
58
114
 
 
115
void MangleModel::addCustomRow(const CustomRow &newRow)
 
116
{
 
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
 
120
        }
 
121
    }
 
122
 
 
123
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
 
124
    m_customRows << newRow;
 
125
    endInsertRows();
 
126
}
 
127
 
 
128
void MangleModel::removeCustomRow(const QString &rowName)
 
129
{
 
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);
 
135
            endRemoveRows();
 
136
            break;
 
137
        }
 
138
    }
 
139
}
 
140
 
 
141
void MangleModel::updateManualRow()
 
142
{
 
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;
 
147
        }
 
148
    }
 
149
 
 
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")});
 
153
    else
 
154
        removeCustomRow(QStringLiteral("*other"));
 
155
}
 
156
 
 
157
void MangleModel::updateGuestRow()
 
158
{
 
159
    if (Greeter::instance()->hasGuestAccount())
 
160
        addCustomRow({QStringLiteral("*guest"), gettext("Guest Session")});
 
161
    else
 
162
        removeCustomRow(QStringLiteral("*guest"));
 
163
}
 
164
 
 
165
void MangleModel::updateCustomRows()
 
166
{
 
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)
 
170
        return;
 
171
 
 
172
    m_updatingCustomRows = true;
 
173
    updateGuestRow();
 
174
    updateManualRow();
 
175
    m_updatingCustomRows = false;
 
176
}
 
177
 
 
178
int MangleModel::rowCount(const QModelIndex &parent) const
 
179
{
 
180
    if (parent.isValid())
 
181
        return 0;
 
182
    else
 
183
        return sourceRowCount() + m_customRows.size();
 
184
}
 
185
 
 
186
int MangleModel::sourceRowCount() const
 
187
{
 
188
    return Greeter::instance()->hideUsersHint() ? 0 : sourceModel()->rowCount();
 
189
}
 
190
 
 
191
QModelIndex MangleModel::index(int row, int column, const QModelIndex &parent) const
 
192
{
 
193
    if (row >= rowCount())
 
194
        return QModelIndex();
 
195
 
 
196
    bool isCustomRow = row >= sourceRowCount();
 
197
    if (isCustomRow && !parent.isValid()) {
 
198
        return createIndex(row, column);
 
199
    } else {
 
200
        return QIdentityProxyModel::index(row, column, parent);
 
201
    }
 
202
}
 
203
 
59
204
// **** Now we continue with actual UsersModel class ****
60
205
 
61
206
UsersModel::UsersModel(QObject* parent)
68
213
    sort(0);
69
214
}
70
215
 
 
216
bool UsersModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
 
217
{
 
218
    auto leftName = source_left.data(QLightDM::UsersModel::NameRole);
 
219
    auto rightName = source_right.data(QLightDM::UsersModel::NameRole);
 
220
 
 
221
    if (leftName == QStringLiteral("*guest"))
 
222
        return false;
 
223
    if (rightName == QStringLiteral("*guest"))
 
224
        return true;
 
225
    if (leftName == QStringLiteral("*other"))
 
226
        return false;
 
227
    if (rightName == QStringLiteral("*other"))
 
228
        return true;
 
229
 
 
230
    return UnitySortFilterProxyModelQML::lessThan(source_left, source_right);
 
231
}
 
232
 
71
233
#include "UsersModel.moc"