~lightdm-team/lightdm/1.4

« back to all changes in this revision

Viewing changes to liblightdm-qt/QLightDM/usersmodel.cpp

  • Committer: David Edmundson
  • Date: 2011-05-22 11:19:24 UTC
  • mto: This revision was merged to the branch mainline in revision 461.
  • Revision ID: david@davidedmundson.co.uk-20110522111924-aar5y8f75tm9q9xh
Added a users model

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "usersmodel.h"
 
2
#include "user.h"
 
3
#include "config.h"
 
4
 
 
5
#include <pwd.h>
 
6
#include <errno.h>
 
7
 
 
8
#include <QtCore/QString>
 
9
#include <QtCore/QFileSystemWatcher>
 
10
#include <QtGui/QPixmap>
 
11
 
 
12
using namespace QLightDM;
 
13
 
 
14
class UsersModelPrivate {
 
15
public:
 
16
    QList<User*> users;
 
17
    QLightDM::Config *config;
 
18
};
 
19
 
 
20
UsersModel::UsersModel(QLightDM::Config *config, QObject *parent) :
 
21
    QAbstractListModel(parent),
 
22
    d (new UsersModelPrivate())
 
23
{
 
24
    d->config = config;
 
25
 
 
26
    if (d->config->loadUsers()) {
 
27
        //load users on startup and if the password file changes.
 
28
        QFileSystemWatcher *watcher = new QFileSystemWatcher(this);
 
29
        watcher->addPath("/etc/passwd"); //FIXME harcoded path
 
30
        connect(watcher, SIGNAL(fileChanged(QString)), SLOT(loadUsers()));
 
31
 
 
32
        loadUsers();
 
33
    }
 
34
}
 
35
 
 
36
UsersModel::~UsersModel()
 
37
{
 
38
    delete d;
 
39
}
 
40
 
 
41
 
 
42
int UsersModel::rowCount(const QModelIndex &parent) const
 
43
{
 
44
    return d->users.count();
 
45
}
 
46
 
 
47
QVariant UsersModel::data(const QModelIndex &index, int role) const
 
48
{
 
49
    if (!index.isValid()) {
 
50
        return QVariant();
 
51
    }
 
52
 
 
53
    int row = index.row();
 
54
    switch (role) {
 
55
    case Qt::DisplayRole:
 
56
        return d->users[row]->displayName();
 
57
    case Qt::DecorationRole:
 
58
        return QPixmap(d->users[row]->image());
 
59
    }
 
60
 
 
61
    return QVariant();
 
62
}
 
63
 
 
64
 
 
65
void UsersModel::loadUsers()
 
66
{
 
67
    QStringList hiddenUsers, hiddenShells;
 
68
    int minimumUid;
 
69
    QList<User*> newUsers;
 
70
 
 
71
    minimumUid = d->config->minimumUid();
 
72
    hiddenUsers = d->config->hiddenUsers();
 
73
    hiddenShells = d->config->hiddenShells();
 
74
    //FIXME accidently not got the "if contact removed" code. Need to fix.
 
75
 
 
76
    setpwent();
 
77
 
 
78
    while(TRUE)
 
79
    {
 
80
        struct passwd *entry;
 
81
        User *user;
 
82
        QStringList tokens;
 
83
        QString realName, image;
 
84
        QFile *imageFile;
 
85
        int i;
 
86
 
 
87
        errno = 0;
 
88
        entry = getpwent();
 
89
        if(!entry)
 
90
            break;
 
91
 
 
92
        /* Ignore system users */
 
93
        if(entry->pw_uid < minimumUid)
 
94
            continue;
 
95
 
 
96
        /* Ignore users disabled by shell */
 
97
        if(entry->pw_shell)
 
98
        {
 
99
            for(i = 0; i < hiddenShells.size(); i++)
 
100
                if(entry->pw_shell == hiddenShells.at(i))
 
101
                    break;
 
102
            if(i < hiddenShells.size())
 
103
                continue;
 
104
        }
 
105
 
 
106
        /* Ignore certain users */
 
107
        for(i = 0; i < hiddenUsers.size(); i++)
 
108
            if(entry->pw_name == hiddenUsers.at(i))
 
109
                break;
 
110
        if(i < hiddenUsers.size())
 
111
            continue;
 
112
 
 
113
        tokens = QString(entry->pw_gecos).split(",");
 
114
        if(tokens.size() > 0 && tokens.at(i) != "")
 
115
            realName = tokens.at(i);
 
116
 
 
117
 
 
118
        //replace this with QFile::exists();
 
119
        QDir homeDir(entry->pw_dir);
 
120
        imageFile = new QFile(homeDir.filePath(".face"));
 
121
        if(!imageFile->exists())
 
122
        {
 
123
            delete imageFile;
 
124
            imageFile = new QFile(homeDir.filePath(".face.icon"));
 
125
        }
 
126
        if(imageFile->exists()) {
 
127
            image = "file://" + imageFile->fileName();
 
128
        }
 
129
        delete imageFile;
 
130
 
 
131
        //FIXME don't create objects on the heap in the middle of a loop with breaks in it! Destined for fail.
 
132
        //FIXME pointers all over the place in this code.
 
133
        user = new User(entry->pw_name, realName, entry->pw_dir, image, false, this);
 
134
 
 
135
        /* Update existing users if have them */
 
136
        bool matchedUser = false;
 
137
 
 
138
        for (int i=0; i < d->users.size(); i++)
 
139
        {
 
140
            User* info = d->users[i];
 
141
            if(info->name() == user->name()) {
 
142
                matchedUser = true;
 
143
                info->update(user->realName(), user->homeDirectory(), user->image(), user->isLoggedIn());
 
144
                dataChanged(createIndex(i, 0), createIndex(i,0));
 
145
                delete user;
 
146
            }
 
147
        }
 
148
        if(!matchedUser) {
 
149
            newUsers.append(user);
 
150
        }
 
151
    }
 
152
 
 
153
    if(errno != 0) {
 
154
        qDebug() << "Failed to read password database: " << strerror(errno);
 
155
    }
 
156
 
 
157
    endpwent();
 
158
 
 
159
    //FIXME accidently not got the "if contact removed" code. Need to restore that.
 
160
    //should call beginRemoveRows, and then remove the row from the model.
 
161
    //might get rid of "User" object, keep as private object (like sessionsmodel) - or make it copyable.
 
162
 
 
163
 
 
164
    //append new users
 
165
    if (newUsers.size() > 0) {
 
166
        beginInsertRows(QModelIndex(), 0, newUsers.size());
 
167
        d->users.append(newUsers);
 
168
        endInsertRows();
 
169
    }
 
170
}