]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Added a users model
authorDavid Edmundson <david@davidedmundson.co.uk>
Sun, 22 May 2011 11:19:24 +0000 (12:19 +0100)
committerDavid Edmundson <david@davidedmundson.co.uk>
Sun, 22 May 2011 11:19:24 +0000 (12:19 +0100)
greeters/qt/loginprompt.cpp
greeters/qt/loginprompt.ui
greeters/qt/panel.cpp
liblightdm-qt/QLightDM/Makefile.am
liblightdm-qt/QLightDM/UsersModel [new file with mode: 0644]
liblightdm-qt/QLightDM/config.cpp
liblightdm-qt/QLightDM/config.h
liblightdm-qt/QLightDM/greeter.cpp
liblightdm-qt/QLightDM/greeter.h
liblightdm-qt/QLightDM/usersmodel.cpp [new file with mode: 0644]
liblightdm-qt/QLightDM/usersmodel.h [new file with mode: 0644]

index 4130d240855f48d3aa5564404399e874f267f033..e361ac80bb7c136f876a0dfa77ea7c7ab45f9ee4 100644 (file)
@@ -6,6 +6,7 @@
 #include <QLightDM/Language>
 
 #include <QListWidgetItem>
+#include <QLightDM/usersmodel.h>
 
 LoginPrompt::LoginPrompt(QLightDM::Greeter *greeter, QWidget *parent) :
     QWidget(parent),
@@ -14,22 +15,11 @@ LoginPrompt::LoginPrompt(QLightDM::Greeter *greeter, QWidget *parent) :
 {
     ui->setupUi(this);
     ui->feedbackLabel->setText(QString());
-
-    m_greeter->connectToServer();
-
+    
     ui->hostnameLabel->setText(m_greeter->hostname());
-
-    QList<QLightDM::User*> users = m_greeter->users();
-    foreach(QLightDM::User *user, users) {
-        QListWidgetItem* item = new QListWidgetItem(user->displayName(), ui->userList);
-        item->setData(Qt::UserRole, user->name());
-        if(user->image().isEmpty())         {
-            item->setIcon(QIcon::fromTheme("user-identity"));
-        } else {
-            item->setIcon(QIcon(user->image()));
-        }
-
-    }
+    
+    QLightDM::UsersModel *usersModel = new QLightDM::UsersModel(greeter->config(), this);
+    ui->userListView->setModel(usersModel);
 
     connect(ui->loginButton, SIGNAL(released()), SLOT(onLoginButtonClicked()));
     connect(m_greeter, SIGNAL(authenticationComplete(bool)), SLOT(onAuthenticationComplete(bool)));
@@ -41,11 +31,12 @@ LoginPrompt::~LoginPrompt()
     delete ui;
 }
 
+
 void LoginPrompt::onLoginButtonClicked()
 {
     ui->feedbackLabel->setText(QString());
-    if (ui->userList->currentItem()) {
-        m_greeter->startAuthentication(ui->userList->currentItem()->data(Qt::UserRole).toString());
+    if (ui->userListView->currentIndex().isValid()) {
+        m_greeter->startAuthentication(ui->userListView->currentIndex().data(Qt::UserRole).toString());
     }
 }
 
index 0d9fab71be7ea25086476a68c1057303550cb27e..91146a7229713e195c08bbb7c6ee71dccdd85808 100644 (file)
@@ -38,7 +38,7 @@
     </widget>
    </item>
    <item>
-    <widget class="QListWidget" name="userList"/>
+    <widget class="QListView" name="userListView"/>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
index 091140fa60c28fa68a0dab402cb5520478095616..a942735601f7075625e24cf158e7e5d8f241d719 100644 (file)
@@ -42,7 +42,9 @@ Panel::Panel(QLightDM::Greeter *greeter, QWidget *parent):
 
     ui->powerOptionsButton->setMenu(powerMenu);
 
-    ui->sessionCombo->setModel(m_greeter->sessionsModel());
+    
+    QLightDM::SessionsModel* sessionsModel = new QLightDM::SessionsModel(this);
+    ui->sessionCombo->setModel(sessionsModel);
 }
 
 Panel::~Panel()
index 33ec6506870cb5a656764240f916cd9eb503e294..0a14b9fc25cfe3867290a5689e5548b7186a253f 100644 (file)
@@ -5,7 +5,8 @@ MOC_FILES = \
        greeter_moc.cpp \
        sessionsmodel_moc.cpp \
        user_moc.cpp \
-       config_moc.cpp
+       config_moc.cpp \
+       usersmodel_moc.cpp 
 
 greeter_moc.cpp: greeter.h
        moc $< -o $@
@@ -15,6 +16,8 @@ user_moc.cpp: user.h
        moc $< -o $@
 config_moc.cpp: config.h
        moc $< -o $@
+usersmodel_moc.cpp: usersmodel.h
+       moc $< -o $@
 
 
 liblightdm_qt_0include_HEADERS = \
@@ -23,6 +26,7 @@ liblightdm_qt_0include_HEADERS = \
        sessionsmodel.h \
        user.h \
        config.h \
+       usersmodel.h \
        Greeter \
        Language \
        SessionsModel \
@@ -41,6 +45,7 @@ liblightdm_qt_0_la_SOURCES = \
        sessionsmodel.cpp \
        user.cpp \
        config.cpp \
+       usersmodel.cpp \
        $(MOC_FILES)
 
 pkgconfigdir = $(libdir)/pkgconfig
diff --git a/liblightdm-qt/QLightDM/UsersModel b/liblightdm-qt/QLightDM/UsersModel
new file mode 100644 (file)
index 0000000..95f2cf3
--- /dev/null
@@ -0,0 +1 @@
+#include "QLightDM/usersmodel.h"
\ No newline at end of file
index 5175b32138664686d96ed2fa5c5165a76fa3f946..33b396d88ad1f49c05f532d2dbe94b43a777ca58 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <QtCore/QSettings>
 
+#include <QDebug>
+
 using namespace QLightDM;
 
 class ConfigPrivate {
@@ -13,11 +15,17 @@ Config::Config(QString filePath, QObject *parent) :
     QObject(parent),
     d (new ConfigPrivate())
 {
+    qDebug() << "creating config";
+    qDebug() << this;
     d->settings = new QSettings(filePath, QSettings::IniFormat, this);
+    qDebug() << d->settings;
+    qDebug() << d->settings->value("UserManager/load-users", QVariant(true)).toBool();
 }
 
 Config::~Config()
 {
+    qDebug() << "deleting config";
+
     delete d;
 }
 
@@ -47,5 +55,7 @@ QStringList Config::hiddenUsers() const
 
 bool QLightDM::Config::loadUsers() const
 {
+    qDebug() << this;
+    qDebug() << d->settings;
     return d->settings->value("UserManager/load-users", QVariant(true)).toBool();
 }
index f65cc01153e75f4790f948b671f443e4edfe3d45..c17f36d84c18221e965a5c7548a0d002e9fbc15f 100644 (file)
@@ -10,8 +10,8 @@
 
 class ConfigPrivate;
 
-//Ideas:
-//    This uses an sync method to get the filename to load from dbus. For bonus points we should make it async and emit a sort of "finsihed() signal"
+//Logic for loading file name should be here.
+//For bonus points it should be async.
 
 namespace QLightDM
 {
index 3ddc5f6279f4aa20f1d3a73f50e8ef041d476319..9c0d2843012f8fadfd04c1493b175a7af0ce6204 100644 (file)
@@ -5,8 +5,6 @@
 #include "config.h"
 
 #include <security/pam_appl.h>
-#include <pwd.h>
-#include <errno.h>
 
 #include <QtNetwork/QHostInfo> //needed for localHostName
 #include <QtCore/QDebug>
@@ -48,9 +46,6 @@ public:
     SessionsModel *sessionsModel;
     Config *config;
 
-    QList<User*> users;
-    bool haveUsers;
-
     QDBusInterface* lightdmInterface;
     QDBusInterface* powerManagementInterface;
     QDBusInterface* consoleKitInterface;
@@ -72,8 +67,7 @@ Greeter::Greeter(QObject *parent) :
 {
     d->readBuffer = (char *)malloc (HEADER_SIZE);
     d->nRead = 0;
-    d->haveUsers = false;
-    
+    d->config = 0;
     d->sessionsModel = new SessionsModel(this);
 }
 
@@ -165,11 +159,15 @@ void Greeter::connectToServer()
         busType = QDBusConnection::sessionBus();
     }
 
-
     d->lightdmInterface = new QDBusInterface("org.lightdm.LightDisplayManager", "/org/lightdm/LightDisplayManager", "org.lightdm.LightDisplayManager", busType);
     d->powerManagementInterface = new QDBusInterface("org.freedesktop.PowerManagement","/org/freedesktop/PowerManagement", "org.freedesktop.PowerManagement");
     d->consoleKitInterface = new QDBusInterface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit");
 
+    QString file;
+    file = d->lightdmInterface->property("ConfigFile").toString();
+    qDebug() << "Loading configuration from " << file;
+    d->config = new Config(file, this);
+
     char* fd = getenv("LDM_TO_SERVER_FD");
     if(!fd) {
        qDebug() << "No LDM_TO_SERVER_FD environment variable";
@@ -197,10 +195,7 @@ void Greeter::connectToServer()
     flush();
 
 
-    QString file;
-    file = d->lightdmInterface->property("ConfigFile").toString();
-    qDebug() << "Loading configuration from " << file;
-    d->config = new Config(file, this);
+
 }
 
 void Greeter::startAuthentication(const QString &username)
@@ -406,163 +401,11 @@ int Greeter::timedLoginDelay() const
     return d->loginDelay;
 }
 
-void Greeter::loadUsers()
-{
-    QStringList hiddenUsers, hiddenShells;
-    int minimumUid;
-    QList<User*> users, oldUsers, newUsers, changedUsers;
-
-    minimumUid = d->config->minimumUid();
-    hiddenUsers = d->config->hiddenUsers();
-    hiddenShells = d->config->hiddenShells();
-
-    setpwent();
-
-    while(TRUE)
-    {
-        struct passwd *entry;
-        User *user;
-        QStringList tokens;
-        QString realName, image;
-        QFile *imageFile;
-        int i;
-
-        errno = 0;
-        entry = getpwent();
-        if(!entry)
-            break;
-
-        /* Ignore system users */
-        if(entry->pw_uid < minimumUid)
-            continue;
-
-        /* Ignore users disabled by shell */
-        if(entry->pw_shell)
-        {
-            for(i = 0; i < hiddenShells.size(); i++)
-                if(entry->pw_shell == hiddenShells.at(i))
-                    break;
-            if(i < hiddenShells.size())
-                continue;
-        }
-
-        /* Ignore certain users */
-        for(i = 0; i < hiddenUsers.size(); i++)
-            if(entry->pw_name == hiddenUsers.at(i))
-                break;
-        if(i < hiddenUsers.size())
-            continue;
-        tokens = QString(entry->pw_gecos).split(",");
-        if(tokens.size() > 0 && tokens.at(i) != "")
-            realName = tokens.at(i);
-      
-        QDir homeDir(entry->pw_dir);
-        imageFile = new QFile(homeDir.filePath(".face"));
-        if(!imageFile->exists())
-        {
-            delete imageFile;
-            imageFile = new QFile(homeDir.filePath(".face.icon"));
-        }
-        if(imageFile->exists())
-            image = "file://" + imageFile->fileName();
-        delete imageFile;
-
-        user = new User(entry->pw_name, realName, entry->pw_dir, image, FALSE);
-
-        /* Update existing users if have them */
-        bool matchedUser = false;
-        foreach(User *info, d->users)
-        {
-            if(info->name() == user->name())
-            {
-                matchedUser = true;
-                if(info->update(user->realName(), user->homeDirectory(), user->image(), user->isLoggedIn()))
-                    changedUsers.append(user);
-                delete user;
-                user = info;
-                break;
-            }
-        }
-        if(!matchedUser)
-        {
-            /* Only notify once we have loaded the user list */
-            if(d->haveUsers)
-                newUsers.append(user);
-        }
-        users.append(user);
-    }
-
-    if(errno != 0)
-        qDebug() << "Failed to read password database: " << strerror(errno);
-
-    endpwent();
-
-    /* Use new user list */
-    oldUsers = d->users;
-    d->users = users;
-
-    /* Notify of changes */
-    foreach(User *user, newUsers)
-    {
-        qDebug() << "User " << user->name() << " added";
-        emit userAdded(user);
-    }
-
-    foreach(User *user, changedUsers)
-    {
-        qDebug() << "User " << user->name() << " changed";
-        emit userChanged(user);
-    }
-
-    foreach(User *user, oldUsers)
-    {
-        /* See if this user is in the current list */
-        bool existing = false;
-        foreach(User *new_user, d->users)
-        {
-            if (new_user == user)
-            {
-                existing = true;
-                break;
-            }
-        }
-
-        if(!existing)
-        {
-            qDebug() << "User " << user->name() << " removed";
-            emit userRemoved(user);
-            delete user;
-        }
-    }
-}
-
-void Greeter::updateUsers()
+Config* Greeter::config() const
 {
-    if (d->haveUsers) {
-        return;
-    }
-
-    /** Load users if we need to. */
-    if (d->config->loadUsers()) {
-        loadUsers();
-    }
-
-    d->haveUsers = true;
-}
-
-QList<User*> Greeter::users()
-{
-    updateUsers();
-    return d->users;
+    return d->config;
 }
 
-SessionsModel* Greeter::sessionsModel() const
-{
-    return d->sessionsModel; 
-}
-
-
 bool Greeter::canSuspend() const
 {
     QDBusReply<bool> reply = d->powerManagementInterface->call("CanSuspend");
index 9d7fbffe34c9add45f852607fa309d4841e8ac0c..67b75be32d393c94d3e043e05fa31bfcdcbb1d66 100644 (file)
@@ -12,7 +12,7 @@ class GreeterPrivate;
 
 namespace QLightDM
 {
-  class SessionsModel;
+  class Config;
   
   class Q_DECL_EXPORT Greeter : public QObject
   {
@@ -37,8 +37,6 @@ namespace QLightDM
        QString timedLoginUser() const;
        int timedLoginDelay() const;
 
-       QList<QLightDM::User*> users();
-
        QList<QLightDM::Language> languages() const;
        QString defaultLanguage() const;
 
@@ -46,8 +44,8 @@ namespace QLightDM
        QString defaultLayout() const;
        QString layout() const;
 
-        //TODO why did I make this? the clients can just create a session model when they need to
-       QLightDM::SessionsModel *sessionsModel() const;
+        QLightDM::Config *config() const;
+
        QString defaultSession() const;
 
        bool inAuthentication() const;
@@ -80,9 +78,6 @@ namespace QLightDM
        void showError(QString message);
        void authenticationComplete(bool isAuthenticated);
        void timedLogin(QString username);
-        void userAdded(User *user);
-        void userChanged(User *user);
-        void userRemoved(User *user);
        void quit();
     
     private slots:  
@@ -97,8 +92,6 @@ namespace QLightDM
        int getPacketLength();
        int readInt(int *offset);
        QString readString(int *offset);
-       void loadUsers();
-       void updateUsers();
     };
 
 };//end namespace
diff --git a/liblightdm-qt/QLightDM/usersmodel.cpp b/liblightdm-qt/QLightDM/usersmodel.cpp
new file mode 100644 (file)
index 0000000..69edcaa
--- /dev/null
@@ -0,0 +1,170 @@
+#include "usersmodel.h"
+#include "user.h"
+#include "config.h"
+
+#include <pwd.h>
+#include <errno.h>
+
+#include <QtCore/QString>
+#include <QtCore/QFileSystemWatcher>
+#include <QtGui/QPixmap>
+
+using namespace QLightDM;
+
+class UsersModelPrivate {
+public:
+    QList<User*> users;
+    QLightDM::Config *config;
+};
+
+UsersModel::UsersModel(QLightDM::Config *config, QObject *parent) :
+    QAbstractListModel(parent),
+    d (new UsersModelPrivate())
+{
+    d->config = config;
+
+    if (d->config->loadUsers()) {
+        //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()));
+
+        loadUsers();
+    }
+}
+
+UsersModel::~UsersModel()
+{
+    delete d;
+}
+
+
+int UsersModel::rowCount(const QModelIndex &parent) const
+{
+    return d->users.count();
+}
+
+QVariant UsersModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid()) {
+        return QVariant();
+    }
+
+    int row = index.row();
+    switch (role) {
+    case Qt::DisplayRole:
+        return d->users[row]->displayName();
+    case Qt::DecorationRole:
+        return QPixmap(d->users[row]->image());
+    }
+
+    return QVariant();
+}
+
+
+void UsersModel::loadUsers()
+{
+    QStringList hiddenUsers, hiddenShells;
+    int minimumUid;
+    QList<User*> newUsers;
+
+    minimumUid = d->config->minimumUid();
+    hiddenUsers = d->config->hiddenUsers();
+    hiddenShells = d->config->hiddenShells();
+    //FIXME accidently not got the "if contact removed" code. Need to fix.
+
+    setpwent();
+
+    while(TRUE)
+    {
+        struct passwd *entry;
+        User *user;
+        QStringList tokens;
+        QString realName, image;
+        QFile *imageFile;
+        int i;
+
+        errno = 0;
+        entry = getpwent();
+        if(!entry)
+            break;
+
+        /* Ignore system users */
+        if(entry->pw_uid < minimumUid)
+            continue;
+
+        /* Ignore users disabled by shell */
+        if(entry->pw_shell)
+        {
+            for(i = 0; i < hiddenShells.size(); i++)
+                if(entry->pw_shell == hiddenShells.at(i))
+                    break;
+            if(i < hiddenShells.size())
+                continue;
+        }
+
+        /* Ignore certain users */
+        for(i = 0; i < hiddenUsers.size(); i++)
+            if(entry->pw_name == hiddenUsers.at(i))
+                break;
+        if(i < hiddenUsers.size())
+            continue;
+
+        tokens = QString(entry->pw_gecos).split(",");
+        if(tokens.size() > 0 && tokens.at(i) != "")
+            realName = tokens.at(i);
+
+
+        //replace this with QFile::exists();
+        QDir homeDir(entry->pw_dir);
+        imageFile = new QFile(homeDir.filePath(".face"));
+        if(!imageFile->exists())
+        {
+            delete imageFile;
+            imageFile = new QFile(homeDir.filePath(".face.icon"));
+        }
+        if(imageFile->exists()) {
+            image = "file://" + imageFile->fileName();
+        }
+        delete imageFile;
+
+        //FIXME don't create objects on the heap in the middle of a loop with breaks in it! Destined for fail.
+        //FIXME pointers all over the place in this code.
+        user = new User(entry->pw_name, realName, entry->pw_dir, image, false, this);
+
+        /* Update existing users if have them */
+        bool matchedUser = false;
+
+        for (int i=0; i < d->users.size(); i++)
+        {
+            User* info = d->users[i];
+            if(info->name() == user->name()) {
+                matchedUser = true;
+                info->update(user->realName(), user->homeDirectory(), user->image(), user->isLoggedIn());
+                dataChanged(createIndex(i, 0), createIndex(i,0));
+                delete user;
+            }
+        }
+        if(!matchedUser) {
+            newUsers.append(user);
+        }
+    }
+
+    if(errno != 0) {
+        qDebug() << "Failed to read password database: " << strerror(errno);
+    }
+
+    endpwent();
+
+    //FIXME accidently not got the "if contact removed" code. Need to restore that.
+    //should call beginRemoveRows, and then remove the row from the model.
+    //might get rid of "User" object, keep as private object (like sessionsmodel) - or make it copyable.
+
+
+    //append new users
+    if (newUsers.size() > 0) {
+        beginInsertRows(QModelIndex(), 0, newUsers.size());
+        d->users.append(newUsers);
+        endInsertRows();
+    }
+}
diff --git a/liblightdm-qt/QLightDM/usersmodel.h b/liblightdm-qt/QLightDM/usersmodel.h
new file mode 100644 (file)
index 0000000..e79c492
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef USERSMODEL_H
+#define USERSMODEL_H
+
+#include <QAbstractListModel>
+
+class UsersModelPrivate;
+
+namespace QLightDM
+{
+
+class Config;
+
+class Q_DECL_EXPORT UsersModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    explicit UsersModel(QLightDM::Config *config, QObject *parent = 0);
+    ~UsersModel();
+    int rowCount(const QModelIndex &parent) const;
+    QVariant data(const QModelIndex &index, int role) const;
+
+signals:
+
+public slots:
+
+private slots:
+    void loadUsers();
+
+private:
+    UsersModelPrivate *d;
+};
+};
+
+#endif // USERSMODEL_H