*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option) any
- * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
- * license.
+ * Software Foundation; either version 2 or version 3 of the License.
+ * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
*/
#include "QLightDM/usersmodel.h"
-#include <pwd.h>
-#include <errno.h>
-
-#include <QtCore/QSharedData>
#include <QtCore/QString>
-#include <QtCore/QFileSystemWatcher>
-#include <QtCore/QFile>
-#include <QtCore/QDir>
-#include <QtCore/QSettings>
#include <QtCore/QDebug>
-#include <QtGui/QPixmap>
+#include <QtGui/QIcon>
+
+#include <lightdm.h>
using namespace QLightDM;
QString realName;
QString homeDirectory;
QString image;
+ QString background;
+ QString session;
bool isLoggedIn;
+ bool hasMessages;
+ quint64 uid;
QString displayName() const;
};
}
}
-
+namespace QLightDM {
class UsersModelPrivate {
public:
+ UsersModelPrivate(UsersModel *parent);
+ virtual ~UsersModelPrivate();
QList<UserItem> users;
-};
-UsersModel::UsersModel(QObject *parent) :
- QAbstractListModel(parent),
- d (new UsersModelPrivate())
-{
- //load users on startup and if the password file changes.
- QFileSystemWatcher *watcher = new QFileSystemWatcher(this);
- watcher->addPath("/etc/passwd"); //FIXME harcoded path
- connect(watcher, SIGNAL(fileChanged(QString)), SLOT(loadUsers()));
+ protected:
+ UsersModel * const q_ptr;
+
+ void loadUsers();
- loadUsers();
+ static void cb_userAdded(LightDMUserList *user_list, LightDMUser *user, gpointer data);
+ static void cb_userChanged(LightDMUserList *user_list, LightDMUser *user, gpointer data);
+ static void cb_userRemoved(LightDMUserList *user_list, LightDMUser *user, gpointer data);
+ private:
+ Q_DECLARE_PUBLIC(UsersModel)
+};
}
-UsersModel::~UsersModel()
+UsersModelPrivate::UsersModelPrivate(UsersModel* parent) :
+ q_ptr(parent)
{
- delete d;
+#if !defined(GLIB_VERSION_2_36)
+ g_type_init();
+#endif
}
-
-int UsersModel::rowCount(const QModelIndex &parent) const
+UsersModelPrivate::~UsersModelPrivate()
{
- return d->users.count();
+ g_signal_handlers_disconnect_by_data(lightdm_user_list_get_instance(), this);
}
-QVariant UsersModel::data(const QModelIndex &index, int role) const
+void UsersModelPrivate::loadUsers()
{
- if (!index.isValid()) {
- return QVariant();
- }
+ Q_Q(UsersModel);
+
+ int rowCount = lightdm_user_list_get_length(lightdm_user_list_get_instance());
+
+ if (rowCount == 0) {
+ return;
+ } else {
+ q->beginInsertRows(QModelIndex(), 0, rowCount-1);
+
+ const GList *items, *item;
+ items = lightdm_user_list_get_users(lightdm_user_list_get_instance());
+ for (item = items; item; item = item->next) {
+ LightDMUser *ldmUser = static_cast<LightDMUser*>(item->data);
+
+ UserItem user;
+ user.name = QString::fromUtf8(lightdm_user_get_name(ldmUser));
+ user.homeDirectory = QString::fromUtf8(lightdm_user_get_home_directory(ldmUser));
+ user.realName = QString::fromUtf8(lightdm_user_get_real_name(ldmUser));
+ user.image = QString::fromUtf8(lightdm_user_get_image(ldmUser));
+ user.background = QString::fromUtf8(lightdm_user_get_background(ldmUser));
+ user.session = QString::fromUtf8(lightdm_user_get_session(ldmUser));
+ user.isLoggedIn = lightdm_user_get_logged_in(ldmUser);
+ user.hasMessages = lightdm_user_get_has_messages(ldmUser);
+ user.uid = (quint64)lightdm_user_get_uid(ldmUser);
+ users.append(user);
+ }
- int row = index.row();
- switch (role) {
- case Qt::DisplayRole:
- return d->users[row].displayName();
- case Qt::DecorationRole:
- return QPixmap(d->users[row].image);
- case UsersModel::NameRole:
- return d->users[row].name;
- case UsersModel::RealNameRole:
- return d->users[row].realName;
- case UsersModel::LoggedInRole:
- return d->users[row].isLoggedIn;
+ q->endInsertRows();
}
-
- return QVariant();
+ g_signal_connect(lightdm_user_list_get_instance(), LIGHTDM_USER_LIST_SIGNAL_USER_ADDED, G_CALLBACK (cb_userAdded), this);
+ g_signal_connect(lightdm_user_list_get_instance(), LIGHTDM_USER_LIST_SIGNAL_USER_CHANGED, G_CALLBACK (cb_userChanged), this);
+ g_signal_connect(lightdm_user_list_get_instance(), LIGHTDM_USER_LIST_SIGNAL_USER_REMOVED, G_CALLBACK (cb_userRemoved), this);
}
-
-QList<UserItem> UsersModel::getUsers() const
+void UsersModelPrivate::cb_userAdded(LightDMUserList *user_list, LightDMUser *ldmUser, gpointer data)
{
- QString file = "/etc/lightdm/users.conf"; //FIXME hardcoded path!!
+ Q_UNUSED(user_list)
+ UsersModelPrivate *that = static_cast<UsersModelPrivate*>(data);
- qDebug() << "Loading user configuration from " << file;
- QSettings settings(file, QSettings::IniFormat);
+ that->q_func()->beginInsertRows(QModelIndex(), that->users.size(), that->users.size());
- int minimumUid = settings.value("UserAccounts/minimum-uid", QVariant(500)).toInt();
- QStringList hiddenShells;
- if (settings.contains("UserAccounts/hidden-shells")) {
- hiddenShells = settings.value("UserAccounts/hidden-shells").toString().split(" ");
- }
- else {
- hiddenShells = QStringList() << "/bin/false" << "/usr/sbin/nologin";
- }
- QStringList hiddenUsers;
- if (settings.contains("UserAccounts/hidden-users")) {
- hiddenUsers = settings.value("UserAccounts/hidden-users").toString().split(" ");
- }
- else {
- hiddenUsers = QStringList() << "nobody" << "nobody4" << "noaccess";
- }
- QList<UserItem> users;
+ UserItem user;
+ user.name = QString::fromUtf8(lightdm_user_get_name(ldmUser));
+ user.homeDirectory = QString::fromUtf8(lightdm_user_get_home_directory(ldmUser));
+ user.realName = QString::fromUtf8(lightdm_user_get_real_name(ldmUser));
+ user.image = QString::fromUtf8(lightdm_user_get_image(ldmUser));
+ user.background = QString::fromUtf8(lightdm_user_get_background(ldmUser));
+ user.isLoggedIn = lightdm_user_get_logged_in(ldmUser);
+ user.hasMessages = lightdm_user_get_has_messages(ldmUser);
+ user.uid = (quint64)lightdm_user_get_uid(ldmUser);
+ that->users.append(user);
- setpwent();
- Q_FOREVER {
- errno = 0;
- struct passwd *entry = getpwent();
- if(!entry) {
- break;
- }
+ that->q_func()->endInsertRows();
- /* Ignore system users */
- if(entry->pw_uid < minimumUid) {
- continue;
- }
+}
- /* Ignore users disabled by shell */
- if(entry->pw_shell) {
- if (hiddenShells.contains(entry->pw_shell)) {
- continue;
- }
- }
+void UsersModelPrivate::cb_userChanged(LightDMUserList *user_list, LightDMUser *ldmUser, gpointer data)
+{
+ Q_UNUSED(user_list)
+ UsersModelPrivate *that = static_cast<UsersModelPrivate*>(data);
- if (hiddenUsers.contains(entry->pw_name)) {
- continue;
- }
+ QString userToChange = QString::fromUtf8(lightdm_user_get_name(ldmUser));
- QStringList tokens = QString(entry->pw_gecos).split(",");
- QString realName;
- if(tokens.size() > 0 && tokens.at(0) != "") {
- realName = tokens.at(0);
- }
+ for (int i=0;i<that->users.size();i++) {
+ if (that->users[i].name == userToChange) {
- QDir homeDir(entry->pw_dir);
- QString image = homeDir.filePath(".face");
- if(!QFile::exists (image)) {
- image = homeDir.filePath(".face.icon");
- if(!QFile::exists (image)) {
- image = "";
- }
- }
+ that->users[i].homeDirectory = QString::fromUtf8(lightdm_user_get_home_directory(ldmUser));
+ that->users[i].realName = QString::fromUtf8(lightdm_user_get_real_name(ldmUser));
+ that->users[i].image = QString::fromUtf8(lightdm_user_get_image(ldmUser));
+ that->users[i].background = QString::fromUtf8(lightdm_user_get_background(ldmUser));
+ that->users[i].isLoggedIn = lightdm_user_get_logged_in(ldmUser);
+ that->users[i].hasMessages = lightdm_user_get_has_messages(ldmUser);
+ that->users[i].uid = (quint64)lightdm_user_get_uid(ldmUser);
- UserItem user;
- user.name = entry->pw_name;
- user.realName = realName;
- user.homeDirectory = entry->pw_dir;
- user.image = image;
- user.isLoggedIn = false;
- users.append(user);
+ QModelIndex index = that->q_ptr->createIndex(i, 0);
+ that->q_ptr->dataChanged(index, index);
+ break;
+ }
}
+}
- if(errno != 0) {
- qDebug() << "Failed to read password database: " << strerror(errno);
+
+void UsersModelPrivate::cb_userRemoved(LightDMUserList *user_list, LightDMUser *ldmUser, gpointer data)
+{
+ Q_UNUSED(user_list)
+
+ UsersModelPrivate *that = static_cast<UsersModelPrivate*>(data);
+ QString userToRemove = QString::fromUtf8(lightdm_user_get_name(ldmUser));
+
+ for (int i=0;i<that->users.size();i++) {
+ if (that->users[i].name == userToRemove) {
+ that->q_ptr->beginRemoveRows(QModelIndex(), i, i);
+ that->users.removeAt(i);
+ that->q_ptr->endRemoveRows();
+ break;
+ }
}
- endpwent();
+}
+UsersModel::UsersModel(QObject *parent) :
+ QAbstractListModel(parent),
+ d_ptr(new UsersModelPrivate(this))
+{
+ Q_D(UsersModel);
+ // Extend roleNames (we want to keep the "display" role)
+ QHash<int, QByteArray> roles = roleNames();
+ roles[NameRole] = "name";
+ roles[RealNameRole] = "realName";
+ roles[LoggedInRole] = "loggedIn";
+ roles[BackgroundRole] = "background";
+ roles[BackgroundPathRole] = "backgroundPath";
+ roles[SessionRole] = "session";
+ roles[HasMessagesRole] = "hasMessages";
+ roles[ImagePathRole] = "imagePath";
+ roles[UidRole] = "uid";
+ setRoleNames(roles);
+ d->loadUsers();
- return users;
}
-void UsersModel::loadUsers()
+UsersModel::~UsersModel()
{
- QList<UserItem> usersToAdd;
-
- //might get rid of "User" object, keep as private object (like sessionsmodel) - or make it copyable.
-
- //loop through all the new list of users, if it's in the list already update it (or do nothing) otherwise append to list of new users
- QList<UserItem> newUserList = getUsers();
-
- Q_FOREACH(const UserItem &user, newUserList) {
- bool alreadyInList = false;
- for(int i=0; i < d->users.size(); i++) {
- if (user.name == d->users[i].name) {
- alreadyInList = true;
-// d->users[i].update(user.name(), user.homeDirectory(), user.image(), user.isLoggedIn());
- QModelIndex index = createIndex(i,0);
- dataChanged(index, index);
- }
- }
+ delete d_ptr;
+}
- if (!alreadyInList) {
- usersToAdd.append(user);
- }
+
+int UsersModel::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const UsersModel);
+ if (parent == QModelIndex()) {
+ return d->users.size();
}
- //loop through all the existing users, if they're not in the newly gathered list, remove them.
+ return 0;
+}
- //FIXME this isn't perfect, looping like this in a mutating list - use mutable iterator.
- for (int i=0; i < d->users.size() ; i++) {
- bool found = false;
- foreach(const UserItem &user, newUserList) {
- if (d->users[i].name == user.name) {
- found = true;
- }
- }
+QVariant UsersModel::data(const QModelIndex &index, int role) const
+{
+ Q_D(const UsersModel);
- if (!found) {
- beginRemoveRows(QModelIndex(), i, i);
- d->users.removeAt(i);
- endRemoveRows();
- }
+ if (!index.isValid()) {
+ return QVariant();
}
- //append new users
- if (usersToAdd.size() > 0) {
- beginInsertRows(QModelIndex(), d->users.size(), d->users.size() + usersToAdd.size() -1);
- d->users.append(usersToAdd);
- endInsertRows();
+ int row = index.row();
+ switch (role) {
+ case Qt::DisplayRole:
+ return d->users[row].displayName();
+ case Qt::DecorationRole:
+ return QIcon(d->users[row].image);
+ case UsersModel::NameRole:
+ return d->users[row].name;
+ case UsersModel::RealNameRole:
+ return d->users[row].realName;
+ case UsersModel::SessionRole:
+ return d->users[row].session;
+ case UsersModel::LoggedInRole:
+ return d->users[row].isLoggedIn;
+ case UsersModel::BackgroundRole:
+ return QPixmap(d->users[row].background);
+ case UsersModel::BackgroundPathRole:
+ return d->users[row].background;
+ case UsersModel::HasMessagesRole:
+ return d->users[row].hasMessages;
+ case UsersModel::ImagePathRole:
+ return d->users[row].image;
+ case UsersModel::UidRole:
+ return d->users[row].uid;
}
+
+ return QVariant();
}
-#include "usersmodel_moc.cpp"
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include "usersmodel_moc5.cpp"
+#else
+#include "usersmodel_moc4.cpp"
+#endif