summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/usermanager/groupdialog.cpp106
-rw-r--r--noncore/settings/usermanager/groupdialog.h36
-rw-r--r--noncore/settings/usermanager/main.cpp19
-rw-r--r--noncore/settings/usermanager/opie-usermanager.control10
-rw-r--r--noncore/settings/usermanager/passwd.cpp271
-rw-r--r--noncore/settings/usermanager/passwd.h85
-rw-r--r--noncore/settings/usermanager/userdialog.cpp319
-rw-r--r--noncore/settings/usermanager/userdialog.h55
-rw-r--r--noncore/settings/usermanager/usermanager.cpp242
-rw-r--r--noncore/settings/usermanager/usermanager.h65
-rw-r--r--noncore/settings/usermanager/usermanager.pro10
11 files changed, 1218 insertions, 0 deletions
diff --git a/noncore/settings/usermanager/groupdialog.cpp b/noncore/settings/usermanager/groupdialog.cpp
new file mode 100644
index 0000000..b595d31
--- a/dev/null
+++ b/noncore/settings/usermanager/groupdialog.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "groupdialog.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+
+#include <stdlib.h>
+
+#include "passwd.h"
+
+GroupDialog::GroupDialog(QWidget* parent, const char* name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl) {
+ // GID
+ QLabel *gidLabel=new QLabel(this,"gid: ");
+ gidLabel->setText("GroupID: ");
+ gidLineEdit=new QLineEdit(this,"gid: ");
+ gidLineEdit->setEnabled(false);
+
+ // Groupname
+ QLabel *groupnameLabel=new QLabel(this,"groupname");
+ groupnameLabel->setText("Groupname: ");
+ groupnameLineEdit=new QLineEdit(this,"groupname");
+
+ // Widget layout
+ QVBoxLayout *layout=new QVBoxLayout(this);
+ layout->setMargin(5);
+ QHBoxLayout *hlayout=new QHBoxLayout(-1,"hlayout");
+ layout->addLayout(hlayout);
+ QVBoxLayout *vlayout1=new QVBoxLayout(-1,"vlayout1");
+ QVBoxLayout *vlayout2=new QVBoxLayout(-1,"vlayout2");
+ // First column, labels
+ vlayout1->addWidget(gidLabel);
+ vlayout1->addWidget(groupnameLabel);
+ // Second column, data
+ vlayout2->addWidget(gidLineEdit);
+ vlayout2->addWidget(groupnameLineEdit);
+ hlayout->addLayout(vlayout1);
+ hlayout->addLayout(vlayout2);
+ layout->addSpacing(5);
+
+// showMaximized();
+}
+
+GroupDialog::~GroupDialog() {
+}
+
+bool GroupDialog::addGroup(int gid) {
+ GroupDialog *addgroupDialog=new GroupDialog(); // Make a groupinfo dialog.
+ addgroupDialog->setCaption(tr("Add Group")); // Set the caption.
+ addgroupDialog->gidLineEdit->setText(QString::number(gid)); // Set the next available gid.
+ if(!(addgroupDialog->exec())) return false; // View the dialog, and only continue if 'ok' was pressed.
+ if(!(accounts->addGroup(addgroupDialog->groupnameLineEdit->text(),addgroupDialog->gidLineEdit->text().toInt()))) { // Try to add the group.
+ QMessageBox::information(0,"Ooops!","Something went wrong.\nUnable to add group.");
+ return false;
+ }
+ return true;
+}
+
+bool GroupDialog::editGroup(int gid) {
+ GroupDialog *addgroupDialog=new GroupDialog(); // Create the groupinfo dialog.
+ accounts->findGroup(gid); // Locate the group in the database, and fill out the variables in 'accounts'.
+ // Fill out the widgets with previous data for this group.
+ addgroupDialog->setCaption(tr("Edit Group"));
+ addgroupDialog->gidLineEdit->setText(QString::number(accounts->gr_gid));
+ addgroupDialog->groupnameLineEdit->setText(accounts->gr_name);
+ if(!(addgroupDialog->exec())) return false; // View the dialog, and only continue if 'ok' was pressed.
+ accounts->findGroup(gid); // Locate the group, and fill out the variables in 'accounts' with all info about the group.
+ accounts->gr_name=addgroupDialog->groupnameLineEdit->text(); // Change the name
+ accounts->gr_gid=addgroupDialog->gidLineEdit->text().toInt(); // Change the GID. (Unneeded as its disabled right now.)
+ accounts->updateGroup(gid); // Update the database with the variables (gr_name,gr_gid,gr_mem) in 'accounts'.
+ return true;
+}
+
+bool GroupDialog::delGroup(const char *groupname) {
+ if((accounts->findGroup(groupname))) { // Does this group exist?
+ if(!(accounts->delGroup(groupname))) { // Try to delete it.
+ QMessageBox::information(0,"Ooops!","Something went wrong\nUnable to delete group: "+QString(groupname)+".");
+ }
+ } else {
+ QMessageBox::information(0,"Invalid Groupname","That groupname ("+QString(groupname)+")does not exist.");
+ return false;
+ }
+ return true;
+}
+
+void GroupDialog::accept() {
+ // Check if gid is already taken.
+// if((accounts->findGroup(gidLineEdit->text().toInt()))) {
+// QMessageBox::information(this,"GroupID taken","That GroupID is already taken.");
+// return;
+// }
+ // Check if groupname is already taken.
+ if((accounts->findGroup(groupnameLineEdit->text()))) {
+ QMessageBox::information(0,"Groupname taken","That groupname is already taken.");
+ return; // Don't close the dialog.
+ }
+ QDialog::accept();
+}
diff --git a/noncore/settings/usermanager/groupdialog.h b/noncore/settings/usermanager/groupdialog.h
new file mode 100644
index 0000000..8b37039
--- a/dev/null
+++ b/noncore/settings/usermanager/groupdialog.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef GROUPDIALOG_H
+#define GROUPDIALOG_H
+
+#include <qdialog.h>
+#include <qlineedit.h>
+
+class GroupDialog : public QDialog
+{
+ Q_OBJECT
+private:
+ QString gid;
+ QString groupname;
+ QLineEdit *gidLineEdit;
+ QLineEdit *groupnameLineEdit;
+ int execStatus;
+
+ void accept(void);
+
+public:
+ GroupDialog( QWidget* parent = 0, const char* name = 0, bool modal=true, WFlags fl = 0 );
+ ~GroupDialog();
+ static bool addGroup(int gid);
+ static bool delGroup(const char *groupname);
+ static bool editGroup(int gid);
+};
+
+#endif
diff --git a/noncore/settings/usermanager/main.cpp b/noncore/settings/usermanager/main.cpp
new file mode 100644
index 0000000..aa78286
--- a/dev/null
+++ b/noncore/settings/usermanager/main.cpp
@@ -0,0 +1,19 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "usermanager.h"
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char ** argv )
+{
+ QPEApplication a( argc, argv );
+ UserConfig mw(0,0,0);
+ a.showMainWidget( &mw );
+ return a.exec();
+}
diff --git a/noncore/settings/usermanager/opie-usermanager.control b/noncore/settings/usermanager/opie-usermanager.control
new file mode 100644
index 0000000..956d98e
--- a/dev/null
+++ b/noncore/settings/usermanager/opie-usermanager.control
@@ -0,0 +1,10 @@
+Package: userconfig
+Files: bin/usermanager apps/Settings/usermanager.desktop pics/userconfig/*
+Priority: optional
+Section: opie/settings
+Version: $QPE_VERSION-$SUB_VERSION-0.9
+Depends: opie-base ($QPE_VERSION)
+Architecture: arm
+Maintainer: Ted Parnefors <zaurus@bredband.net>
+License: GPL
+Description: User/Group manager for OPIE.
diff --git a/noncore/settings/usermanager/passwd.cpp b/noncore/settings/usermanager/passwd.cpp
new file mode 100644
index 0000000..310cef8
--- a/dev/null
+++ b/noncore/settings/usermanager/passwd.cpp
@@ -0,0 +1,271 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "passwd.h"
+
+// Needed for crypt_make_salt();
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+
+Passwd::Passwd() {
+}
+
+Passwd::~Passwd() {
+}
+
+// This function is taken from 'busybox'.
+int Passwd::i64c(int i)
+{
+ if (i <= 0)
+ return ('.');
+ if (i == 1)
+ return ('/');
+ if (i >= 2 && i < 12)
+ return ('0' - 2 + i);
+ if (i >= 12 && i < 38)
+ return ('A' - 12 + i);
+ if (i >= 38 && i < 63)
+ return ('a' - 38 + i);
+ return ('z');
+}
+
+// This function is taken from 'busybox'.
+char *Passwd::crypt_make_salt() {
+ time_t now;
+ static unsigned long x;
+ static char result[3];
+
+ time(&now);
+ x += now + getpid() + clock();
+ result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
+ result[1] = i64c(((x >> 12) ^ x) & 077);
+ result[2] = '\0';
+ return result;
+}
+
+bool Passwd::open() {
+ int returnvalue=false;
+
+ QFile passwd_file("/etc/passwd");
+ QFile group_file("/etc/group");
+ passwdStringList.clear();
+ groupStringList.clear();
+ if((passwd_file.open(IO_ReadOnly))) {
+ if((group_file.open(IO_ReadOnly))) {
+ QTextStream ts_passwd(&passwd_file);
+ while(!(ts_passwd.eof())) {
+ passwdStringList << ts_passwd.readLine();
+ }
+ QTextStream ts_group(&group_file);
+ while(!(ts_group.eof())) {
+ groupStringList << ts_group.readLine();
+ }
+ returnvalue=true;
+ group_file.close();
+ }
+ passwd_file.close();
+ }
+ return returnvalue;
+}
+
+bool Passwd::close() {
+ int returnvalue=false;
+ QFile passwd_file("/etc/passwd");
+ QFile group_file("/etc/group");
+ if((passwd_file.open(IO_WriteOnly))) {
+ if((group_file.open(IO_WriteOnly))) {
+ QTextStream ts_passwd(&passwd_file);
+ for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) {
+ ts_passwd << (*it) + "\n";
+ }
+ QTextStream ts_group(&group_file);
+ for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) {
+ ts_group << (*it) + "\n";
+ }
+ returnvalue=true;
+ group_file.close();
+ }
+ passwd_file.close();
+ }
+ return returnvalue;
+}
+
+void Passwd::splitPasswdEntry(QString &userString) {
+ userdataStringList=QStringList::split(":",userString,true);
+ QStringList::Iterator it=userdataStringList.begin();
+ pw_name=(*it++);
+ pw_passwd=(*it++);
+ pw_uid=(*it++).toInt();
+ pw_gid=(*it++).toInt();
+ pw_gecos=(*it++);
+ pw_dir=(*it++);
+ pw_shell=(*it++);
+}
+
+void Passwd::splitGroupEntry(QString &groupString) {
+ groupdataStringList=QStringList::split(":",groupString,true);
+ QStringList::Iterator it=groupdataStringList.begin();
+ gr_name=(*it++);
+ it++;
+ gr_gid=(*it++).toInt();
+ gr_mem=QStringList::split(" ",(*it++));
+}
+
+bool Passwd::searchUser(QRegExp &userRegExp) {
+ QStringList tempStringList(passwdStringList.grep(userRegExp));
+ if((tempStringList.isEmpty())) {
+ return false;
+ } else {
+ userString=(*(tempStringList.begin()));
+ splitPasswdEntry(userString);
+ }
+ return true;
+}
+
+bool Passwd::findUser(const char *username) {
+ QRegExp userRegExp(QString("^%1\\:").arg(username));
+ return searchUser(userRegExp);
+}
+
+bool Passwd::findUser(int uid) {
+ QRegExp userRegExp(QString(":%1\\:").arg(uid));
+ return searchUser(userRegExp);
+}
+
+bool Passwd::addUser(QString pw_name, QString pw_passwd, int pw_uid, int pw_gid, QString pw_gecos,QString pw_dir, QString pw_shell, bool createGroup=true) {
+ QString tempString;
+ if((createGroup) && (!(findGroup(pw_gid)))) addGroup(pw_name,pw_gid);
+ pw_passwd = crypt(pw_passwd, crypt_make_salt());
+ tempString=pw_name+":"+pw_passwd+":"+QString::number(pw_uid)+":"+QString::number(pw_gid)+":"+pw_gecos+":"+pw_dir+":"+pw_shell;
+ passwdStringList.append(tempString);
+ // Make home dir.
+ QDir d;
+ if(!(d.exists(pw_dir))) {
+ d.mkdir(pw_dir);
+ }
+ return 1;
+}
+
+bool Passwd::updateUser(QString login) {
+ QRegExp userRegExp(QString("^%1\\:").arg(login));
+ for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) {
+ if(userRegExp.find((*it),0)!=-1) {
+ *it=QString(pw_name+":"+pw_passwd+":"+QString::number(pw_uid)+":"+QString::number(pw_gid)+":"+pw_gecos+":"+pw_dir+":"+pw_shell);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Passwd::deleteUser(QRegExp &userRegExp, bool delGroup) {
+ for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) {
+ if(userRegExp.find((*it),0)!=-1) {
+ splitPasswdEntry(*it);
+ if(delGroup) this->delGroup(pw_gid);
+ passwdStringList.remove(it);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Passwd::delUser(const char *username, bool delGroup) {
+ QRegExp userRegExp(QString("^%1\\:").arg(username));
+ return deleteUser(userRegExp,delGroup);
+}
+
+bool Passwd::delUser(int uid, bool delGroup) {
+ QRegExp userRegExp(QString(":%1\\:").arg(uid));
+ return deleteUser(userRegExp,delGroup);
+}
+
+bool Passwd::searchGroup(QRegExp &groupRegExp) {
+ QStringList tempStringList(groupStringList.grep(groupRegExp));
+ if((tempStringList.isEmpty())) {
+ return false;
+ } else {
+ groupString=(*(tempStringList.begin()));
+ splitGroupEntry(groupString);
+ }
+ return true;
+}
+
+bool Passwd::findGroup(const char *groupname) {
+ QRegExp groupRegExp(QString("^%1\\:").arg(groupname));
+ return searchGroup(groupRegExp);
+}
+
+bool Passwd::findGroup(int gid) {
+ QRegExp groupRegExp(QString(":%1\\:").arg(gid));
+ return searchGroup(groupRegExp);
+}
+
+bool Passwd::addGroup(QString gr_name, int gr_gid) {
+ QString tempString;
+ tempString=gr_name+":*:"+QString::number(gr_gid)+":";
+ groupStringList.append(tempString);
+ return 1;
+}
+
+bool Passwd::updateGroup(int gid) {
+ QRegExp groupRegExp(QString(":%1\\:").arg(QString::number(gid)));
+ for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) {
+ if(groupRegExp.find((*it),0)!=-1) {
+ *it=QString(gr_name+":*:"+QString::number(gr_gid)+":");
+ for(QStringList::Iterator member=gr_mem.begin(); member!=gr_mem.end(); ++member) {
+ *it+=*member;
+ *it+=" ";
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Passwd::deleteGroup(QRegExp &groupRegExp) {
+ for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) {
+ if(groupRegExp.find((*it),0)!=-1) {
+ groupStringList.remove(it);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Passwd::delGroup(const char *groupname) {
+ QRegExp groupRegExp(QString("^%1\\:").arg(groupname));
+ return deleteGroup(groupRegExp);
+}
+
+bool Passwd::delGroup(int gid) {
+ QRegExp groupRegExp(QString(":%1\\:").arg(gid));
+ return deleteGroup(groupRegExp);
+}
+
+bool Passwd::addGroupMember(QString groupname, QString member) {
+ if(!(findGroup(groupname))) return false;
+ gr_mem << member;
+ if(!(updateGroup(gr_gid))) return false;
+ return true;
+}
+
+bool Passwd::delGroupMember(QString groupname, QString member) {
+ if(!(findGroup(groupname))) return false;
+ for(QStringList::Iterator it=gr_mem.begin(); it!=gr_mem.end(); ++it) {
+ if(*it==member) {
+ gr_mem.remove(it);
+ it=gr_mem.end();
+ }
+ }
+ if(!(updateGroup(gr_gid))) return false;
+ return true;
+}
+
+Passwd *accounts;
diff --git a/noncore/settings/usermanager/passwd.h b/noncore/settings/usermanager/passwd.h
new file mode 100644
index 0000000..37c41dc
--- a/dev/null
+++ b/noncore/settings/usermanager/passwd.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PASSWD_H
+#define PASSWD_H
+
+#include <qobject.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qdir.h>
+
+#include <crypt.h>
+#include <pwd.h>
+#include <grp.h>
+
+class Passwd
+{
+public:
+ QStringList passwdStringList; // List of all users (name,passwd,uid,gid,gecos,dir,shell)
+ QStringList groupStringList; // List of all groups (name,gid,mem)
+
+ // pwentry
+ QString pw_name;
+ QString pw_passwd;
+ int pw_uid;
+ int pw_gid;
+ QString pw_gecos;
+ QString pw_dir;
+ QString pw_shell;
+
+ // grentry
+ QString gr_name;
+ int gr_gid;
+ QStringList gr_mem;
+
+ Passwd(void);
+ ~Passwd(void);
+ bool open(void);
+ bool close(void);
+ char *crypt_make_salt(void);
+ void splitPasswdEntry(QString &userString);
+ void splitGroupEntry(QString &groupString);
+ bool findUser(const char *username);
+ bool findUser(int uid);
+ bool addUser(QString pw_name, QString pw_passwd, int pw_uid, int pw_gid, QString pw_gecos, QString pw_dir, QString pw_shell, bool createGroup=true);
+ bool updateUser(QString login);
+ bool delUser(const char *username, bool delGroup=true);
+ bool delUser(int uid, bool delGroup=true);
+ bool findGroup(const char *groupname);
+ bool findGroup(int gid);
+ bool addGroup(QString gr_name, int gr_gid);
+ bool updateGroup(int gid);
+ bool delGroup(const char *groupname);
+ bool delGroup(int gid);
+ bool addGroupMember(QString groupname,QString member);
+ bool delGroupMember(QString groupname,QString member);
+
+private:
+ QString userString;
+ QString groupString;
+
+ int i64c(int i);
+ bool searchUser(QRegExp &userRegExp);
+ bool deleteUser(QRegExp &userRegExp, bool delGroup);
+ bool searchGroup(QRegExp &groupRegExp);
+ bool deleteGroup(QRegExp &groupRegExp);
+ QStringList userdataStringList;
+ QStringList groupdataStringList;
+
+ QFile *passwd_file;
+ QFile *group_file;
+};
+
+extern Passwd *accounts; // Create a global object.
+
+#endif
diff --git a/noncore/settings/usermanager/userdialog.cpp b/noncore/settings/usermanager/userdialog.cpp
new file mode 100644
index 0000000..892fc8a
--- a/dev/null
+++ b/noncore/settings/usermanager/userdialog.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "userdialog.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qmessagebox.h>
+
+#include <stdlib.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "passwd.h"
+
+/**
+ * UserDialog constructor. Setup the dialog, fill the groupComboBox & groupsListView with all groups.
+ *
+ */
+UserDialog::UserDialog(QWidget* parent, const char* name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl) {
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ myTabWidget=new QTabWidget(this,"User Tab Widget");
+ layout->addWidget(myTabWidget);
+ setupTab1();
+ setupTab2();
+
+ // And also fill the listview & the combobox with all available groups.
+ for( QStringList::Iterator it = accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) {
+ accounts->splitGroupEntry(*it);
+ new QListViewItem(groupsListView,accounts->gr_name);
+ groupComboBox->insertItem(accounts->gr_name);
+ }
+
+ showMaximized();
+}
+
+/**
+ * Empty destructor.
+ *
+ */
+UserDialog::~UserDialog() {
+}
+
+/**
+ * Creates the first tab, all userinfo is here.
+ *
+ */
+void UserDialog::setupTab1() {
+ QPixmap mypixmap;
+ QWidget *tabpage = new QWidget(myTabWidget,"page1");
+ QVBoxLayout *layout = new QVBoxLayout(tabpage);
+ layout->setMargin(5);
+
+ // Picture
+ picturePushButton = new QPushButton(tabpage,"Label");
+ picturePushButton->setMinimumSize(48,48);
+ picturePushButton->setMaximumSize(48,48);
+ picturePushButton->setPixmap(Resource::loadPixmap("userconfig/usericon")); // Load default usericon.
+ connect(picturePushButton,SIGNAL(clicked()),this,SLOT(clickedPicture())); // Clicking the picture should invoke pictureselector.
+
+ // Login
+ QLabel *loginLabel=new QLabel(tabpage,"Login: ");
+ loginLabel->setText("Login: ");
+ loginLineEdit=new QLineEdit(tabpage,"Login: ");
+
+ // UID
+ QLabel *uidLabel=new QLabel(tabpage,"uid: ");
+ uidLabel->setText("UserID: ");
+ uidLineEdit=new QLineEdit(tabpage,"uid: ");
+ uidLineEdit->setEnabled(false);
+
+ // Username (gecos)
+ QLabel *gecosLabel=new QLabel(tabpage,"gecos");
+ gecosLabel->setText("Username: ");
+ gecosLineEdit=new QLineEdit(tabpage,"gecos");
+
+ // Password
+ QLabel *passwordLabel=new QLabel(tabpage,"password");
+ passwordLabel->setText("Password: ");
+ passwordLineEdit=new QLineEdit(tabpage,"password");
+ passwordLineEdit->setEchoMode(QLineEdit::Password);
+
+ // Shell
+ QLabel *shellLabel=new QLabel(tabpage,"shell");
+ shellLabel->setText("Shell: ");
+ shellComboBox=new QComboBox(tabpage,"shell");
+ shellComboBox->setEditable(true);
+ shellComboBox->insertItem("/bin/sh");
+ shellComboBox->insertItem("/bin/ash");
+ shellComboBox->insertItem("/bin/false");
+
+ // Primary Group
+ QLabel *groupLabel=new QLabel(tabpage,"group");
+ groupLabel->setText("Primary group: ");
+ groupComboBox=new QComboBox(tabpage,"PrimaryGroup");
+
+ // Widget layout
+ QHBoxLayout *hlayout=new QHBoxLayout(-1,"hlayout");
+ layout->addWidget(picturePushButton);
+ layout->addSpacing(5);
+ layout->addLayout(hlayout);
+ QVBoxLayout *vlayout1=new QVBoxLayout(-1,"vlayout1");
+ QVBoxLayout *vlayout2=new QVBoxLayout(-1,"vlayout2");
+ // First column, labels
+ vlayout1->addWidget(loginLabel);
+ vlayout1->addSpacing(5);
+ vlayout1->addWidget(uidLabel);
+ vlayout1->addSpacing(5);
+ vlayout1->addWidget(gecosLabel);
+ vlayout1->addSpacing(5);
+ vlayout1->addWidget(passwordLabel);
+ vlayout1->addSpacing(5);
+ vlayout1->addWidget(shellLabel);
+ vlayout1->addSpacing(5);
+ vlayout1->addWidget(groupLabel);
+ // Second column, data
+ vlayout2->addWidget(loginLineEdit);
+ vlayout2->addSpacing(5);
+ vlayout2->addWidget(uidLineEdit);
+ vlayout2->addSpacing(5);
+ vlayout2->addWidget(gecosLineEdit);
+ vlayout2->addSpacing(5);
+ vlayout2->addWidget(passwordLineEdit);
+ vlayout2->addSpacing(5);
+ vlayout2->addWidget(shellComboBox);
+ vlayout2->addSpacing(5);
+ vlayout2->addWidget(groupComboBox);
+ hlayout->addLayout(vlayout1);
+ hlayout->addLayout(vlayout2);
+
+ myTabWidget->addTab(tabpage,"User Info");
+}
+
+/**
+ * Creates the second tab containing additional groups for the user.
+ *
+ */
+void UserDialog::setupTab2() {
+ QWidget *tabpage = new QWidget(myTabWidget,"page2");
+ QVBoxLayout *layout = new QVBoxLayout(tabpage);
+ layout->setMargin(5);
+
+ // Additional groups
+ groupsListView=new QListView(tabpage,"groups");
+ groupsListView->addColumn("Additional groups");
+ groupsListView->setColumnWidthMode(0,QListView::Maximum);
+ groupsListView->setMultiSelection(true);
+
+ layout->addSpacing(5);
+ // Grouplist
+ layout->addWidget(groupsListView);
+
+ myTabWidget->addTab(tabpage,"User Groups");
+}
+
+/**
+ * Static function that creates the userinfo dialog.
+ * The user will be prompted to add a user.
+ *
+ * @param uid This is a suggested available UID.
+ * @param gid This is a suggested available GID.
+ *
+ * @return <code>true</code> if the user was successfully added, otherwise <code>false</code>.
+ *
+ */
+bool UserDialog::addUser(int uid, int gid) {
+ UserDialog *adduserDialog=new UserDialog();
+ adduserDialog->setCaption(tr("Add User"));
+ adduserDialog->userID=uid; // Set next available UID as default uid.
+ adduserDialog->groupID=gid; // Set next available GID as default gid.
+ // Insert default group into groupComboBox
+ adduserDialog->groupComboBox->insertItem("<create new group>",0);
+ adduserDialog->uidLineEdit->setText(QString::number(uid));
+ // Show the dialog!
+ if(!(adduserDialog->exec())) return false;
+ if((adduserDialog->groupComboBox->currentItem()!=0)) {
+ accounts->findGroup(adduserDialog->groupComboBox->currentText());
+ adduserDialog->groupID=accounts->gr_gid;
+ qWarning(QString::number(accounts->gr_gid));
+ }
+ if(!(accounts->addUser(adduserDialog->loginLineEdit->text(), adduserDialog->passwordLineEdit->text(),
+ adduserDialog->uidLineEdit->text().toInt(), adduserDialog->groupID, adduserDialog->gecosLineEdit->text(),
+ QString("/home/")+adduserDialog->loginLineEdit->text() , adduserDialog->shellComboBox->currentText()))) {
+ QMessageBox::information(0,"Ooops!","Something went wrong!\nUnable to add user.");
+ return false;
+ }
+
+ // Add User to additional groups.
+ QListViewItemIterator it( adduserDialog->groupsListView );
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isSelected() )
+ accounts->addGroupMember(it.current()->text(0),adduserDialog->loginLineEdit->text());
+ }
+ return true;
+}
+
+/**
+ * Deletes the user account.
+ *
+ * @param username User to be deleted.
+ *
+ * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>.
+ *
+ */
+bool UserDialog::delUser(const char *username) {
+ if((accounts->findUser(username))) { // Does that user exist?
+ if(!(accounts->delUser(username))) { // Delete the user.
+ QMessageBox::information(0,"Ooops!","Something went wrong\nUnable to delete user: "+QString(username)+".");
+ }
+ } else {
+ QMessageBox::information(0,"Invalid Username","That username ("+QString(username)+")does not exist.");
+ return false;
+ }
+ return true;
+}
+
+/**
+ * This displays a confirmation dialog wether a user should be deleted or not.
+ * (And also deletes the account)
+ *
+ * @param username User to be deleted.
+ *
+ * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>.
+ *
+ */
+bool UserDialog::editUser(const char *username) {
+ UserDialog *edituserDialog=new UserDialog(); // Create Dialog
+ edituserDialog->setCaption(tr("Edit User"));
+ accounts->findUser(username); // Locate user in database and fill variables in 'accounts' object.
+ accounts->findGroup(accounts->pw_gid); // Locate the user's primary group, and fill group variables in 'accounts' object.
+ // Fill widgets with userinfo.
+ edituserDialog->loginLineEdit->setText(accounts->pw_name);
+ edituserDialog->uidLineEdit->setText(QString::number(accounts->pw_uid));
+ edituserDialog->gecosLineEdit->setText(accounts->pw_gecos);
+ // Set password to '........', we will later check if this still is the contents, if not, the password has been changed.
+ edituserDialog->passwordLineEdit->setText("........");
+ // If this user is not using /bin/sh,/bin/ash or /bin/false as shell, add that entry to the shell-combobox.
+ if(accounts->pw_shell!="/bin/sh" && accounts->pw_shell!="/bin/ash" && accounts->pw_shell!="/bin/false") {
+ edituserDialog->shellComboBox->insertItem(accounts->pw_shell,0);
+ edituserDialog->shellComboBox->setCurrentItem(0);
+ }
+ // Select the primary group for this user.
+ for(int i=0;i<edituserDialog->groupComboBox->count();++i) {
+ if(accounts->gr_name==edituserDialog->groupComboBox->text(i)) {
+ edituserDialog->groupComboBox->setCurrentItem(i);
+ }
+ }
+ // Select the groups in the listview, to which the user belongs.
+ QRegExp userRegExp(QString("[:\\s]%1\\s").arg(username));
+ QStringList tempList=accounts->groupStringList.grep(userRegExp); // Find all entries in the group database, that the user is a member of.
+ for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) { // Iterate over all of them.
+ QListViewItemIterator lvit( edituserDialog->groupsListView ); // Compare to all groups.
+ for ( ; lvit.current(); ++lvit ) {
+ if(lvit.current()->text(0)==(*it).left((*it).find(":"))) {
+ lvit.current()->setSelected(true); // If we find a line with that groupname, select it.;
+ }
+ }
+ }
+
+ if(!(edituserDialog->exec())) return false; // SHOW THE DIALOG!
+
+ accounts->findUser(username); // Fill user variables in 'acccounts' object.
+ accounts->pw_name=edituserDialog->loginLineEdit->text();
+ // Has the password been changed ? Make a new "crypt":ed password.
+ if(edituserDialog->passwordLineEdit->text()!="........") accounts->pw_passwd=crypt(edituserDialog->passwordLineEdit->text(), accounts->crypt_make_salt());
+
+ // Set all variables in accounts object, that will be used when calling 'updateUser()'
+ accounts->pw_uid=edituserDialog->uidLineEdit->text().toInt();
+ accounts->findGroup(edituserDialog->groupComboBox->currentText()); // Fill all group variables in 'accounts' object.
+ accounts->pw_gid=accounts->gr_gid;
+ accounts->pw_gecos=edituserDialog->gecosLineEdit->text();
+ accounts->pw_shell=edituserDialog->shellComboBox->currentText();
+ // Update userinfo, using the information stored in the user variables stored in the accounts object.
+ accounts->updateUser(username);
+
+ // Remove user from all groups he/she is a member of. (could be done in a better way I guess, this was simple though.)
+ for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) {
+ accounts->delGroupMember((*it).left((*it).find(":")),username);
+ }
+
+ // Add User to additional groups that he/she is a member of.
+ QListViewItemIterator it( edituserDialog->groupsListView );
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isSelected() )
+ accounts->addGroupMember(it.current()->text(0),edituserDialog->loginLineEdit->text());
+ }
+ return true;
+}
+
+/**
+ * "OK" has been clicked. Verify some information before closing the dialog.
+ *
+ */
+void UserDialog::accept() {
+ // Add checking... valid username? username taken?
+ if(loginLineEdit->text().isEmpty()) {
+ QMessageBox::information(0,"Empty Login","Please enter a login.");
+ return;
+ }
+ QDialog::accept();
+}
+
+/**
+ * This slot is called when the usericon is clicked, this loads (should) the iconselector.
+ *
+ */
+void UserDialog::clickedPicture() {
+ QMessageBox::information(0,"Sorry!","Icon selection not yet implemented.\nComming real soon now! (tm)");
+}
diff --git a/noncore/settings/usermanager/userdialog.h b/noncore/settings/usermanager/userdialog.h
new file mode 100644
index 0000000..b44de9e
--- a/dev/null
+++ b/noncore/settings/usermanager/userdialog.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef USERDIALOG_H
+#define USERDIALOG_H
+
+#include <qdialog.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qlistview.h>
+#include <qtabwidget.h>
+#include <qpushbutton.h>
+
+#include <qpe/resource.h>
+
+class UserDialog : public QDialog
+{
+ Q_OBJECT
+private:
+ QTabWidget *myTabWidget;
+ QPushButton *picturePushButton;
+ QLineEdit *loginLineEdit;
+ QLineEdit *uidLineEdit;
+ QLineEdit *gecosLineEdit;
+ QLineEdit *passwordLineEdit;
+ QComboBox *shellComboBox;
+ QComboBox *groupComboBox;
+ QListView *groupsListView;
+
+ QStringList groupMembers;
+ QString pictureLocation;
+ int groupID;
+ int userID;
+
+ void setupTab1(void);
+ void setupTab2(void);
+ void accept(void);
+
+private slots:
+ void clickedPicture(void);
+
+public:
+ UserDialog( QWidget* parent = 0, const char* name = 0, bool modal=true, WFlags fl = 0 );
+ ~UserDialog();
+ static bool addUser(int uid, int gid);
+ static bool editUser(const char *username);
+ static bool delUser(const char *username);
+};
+
+#endif
diff --git a/noncore/settings/usermanager/usermanager.cpp b/noncore/settings/usermanager/usermanager.cpp
new file mode 100644
index 0000000..883e5d7
--- a/dev/null
+++ b/noncore/settings/usermanager/usermanager.cpp
@@ -0,0 +1,242 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "usermanager.h"
+
+#include <qlayout.h>
+#include <stdio.h>
+
+#include <qmessagebox.h>
+#include <qfile.h>
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+/**
+ * The mainwindow constructor.
+ *
+ * @param QWidget *parent
+ * @param const char *name
+ * @ param WFlags fl
+ *
+ */
+UserConfig::UserConfig(QWidget* parent, const char* name, WFlags fl) : QMainWindow(parent, name, fl) {
+ setCaption(tr("OPIE User Manager"));
+
+ // Create an instance of the global object 'accounts'. This holds all user/group info, and functions to modify them.
+ accounts=new Passwd();
+ accounts->open(); // This actually loads the files /etc/passwd & /etc/group into memory.
+
+ // Create the toolbar.
+ QPEToolBar *toolbar = new QPEToolBar(this,"Toolbar");
+ toolbar->setHorizontalStretchable(1); // Is there any other way to get the toolbar to stretch of the full screen!?
+ adduserToolButton = new QToolButton(Resource::loadPixmap("userconfig/adduser"),"Add User",0,this,SLOT(addUser()),toolbar,"Add User");
+ edituserToolButton = new QToolButton(Resource::loadPixmap("userconfig/edituser"),"Edit User",0,this,SLOT(editUser()),toolbar,"Edit User");
+ deleteuserToolButton = new QToolButton(Resource::loadPixmap("userconfig/deleteuser"),"Delete User",0,this,SLOT(delUser()),toolbar,"Delete User");
+ QToolButton *userstext = new QToolButton(0,"User",0,0,0,toolbar,"User");
+ userstext->setUsesTextLabel(true);
+ toolbar->addSeparator();
+ addgroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/addgroup"),"Add Group",0,this,SLOT(addGroup()),toolbar,"Add Group");
+ editgroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/editgroup"),"Edit Group",0,this,SLOT(editGroup()),toolbar,"Edit Group");
+ deletegroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/deletegroup"),"Delete Group",0,this,SLOT(delGroup()),toolbar,"Delete Group");
+ QToolButton *groupstext = new QToolButton(0,"Group",0,0,0,toolbar,"Group");
+ groupstext->setUsesTextLabel(true);
+ addToolBar(toolbar,"myToolBar");
+
+ // Add a tabwidget and all the tabs.
+ myTabWidget = new QTabWidget(this,"My Tab Widget");
+ setupTabAccounts();
+ setupTabAllUsers();
+ setupTabAllGroups();
+
+ getUsers(); // Fill out the iconview & listview with all users.
+ getGroups(); // Fill out the group listview with all groups.
+
+ setCentralWidget(myTabWidget);
+}
+
+UserConfig::~UserConfig() {
+ accounts->close();
+ delete accounts;
+}
+
+void UserConfig::setupTabAccounts() {
+ QWidget *tabpage = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(tabpage);
+ layout->setMargin(5);
+
+ usersIconView=new QIconView(tabpage,"users");
+ usersIconView->setItemTextPos(QIconView::Right);
+ layout->addWidget(usersIconView);
+
+ myTabWidget->addTab(tabpage,"Users");
+}
+
+void UserConfig::setupTabAllUsers() {
+ QWidget *tabpage = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(tabpage);
+ layout->setMargin(5);
+
+ usersListView=new QListView(tabpage,"allusers");
+ usersListView->addColumn("UID");
+ usersListView->addColumn("Login");
+ usersListView->addColumn("Username");
+ layout->addWidget(usersListView);
+ usersListView->setSorting(1,1);
+ usersListView->setAllColumnsShowFocus(true);
+
+ myTabWidget->addTab(tabpage,"All Users");
+}
+
+void UserConfig::setupTabAllGroups() {
+ QWidget *tabpage = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(tabpage);
+ layout->setMargin(5);
+
+ groupsListView=new QListView(tabpage,"groups");
+ groupsListView->addColumn("GID");
+ groupsListView->addColumn("Groupname");
+ layout->addWidget(groupsListView);
+ groupsListView->setSorting(1,1);
+ groupsListView->setAllColumnsShowFocus(true);
+
+ myTabWidget->addTab(tabpage,"All Groups");
+}
+void UserConfig::getUsers() {
+ QString mytext;
+ QPixmap mypixmap;
+
+ // Empty the iconview & the listview.
+ usersIconView->clear();
+ usersListView->clear();
+
+ // availableUID is used as a deposite for the next available UID on the system, this should start at an ID over 500.
+ availableUID=500;
+ for(QStringList::Iterator it=accounts->passwdStringList.begin(); it!=accounts->passwdStringList.end(); ++it) {
+ accounts->splitPasswdEntry(*it); // Split the string into it's components and store in variables in the accounts object. ("pr_name" and so on.)
+ new QListViewItem(usersListView,QString::number(accounts->pw_uid),accounts->pw_name,accounts->pw_gecos);
+ if((accounts->pw_uid>=500) && (accounts->pw_uid<65000)) { // Is this user a "normal" user ?
+ mytext=QString(accounts->pw_name)+" - ("+QString(accounts->pw_gecos)+")"; // The string displayed next to the icon.
+ mypixmap=Resource::loadPixmap(QString("users/"+accounts->pw_name)); // Is there an icon for this user?
+ if(mypixmap.isNull()) {
+ mypixmap=Resource::loadPixmap(QString("userconfig/usericon")); // If this user has no icon, load the default icon.
+ }
+ new QIconViewItem(usersIconView,mytext,mypixmap); // Add the icon+text to the qiconview.
+ }
+ if((accounts->pw_uid>=availableUID) && (accounts->pw_uid<65000)) availableUID=accounts->pw_uid+1; // Increase 1 to the latest know UID to get a free uid.
+ }
+}
+
+void UserConfig::addUser() {
+ if(UserDialog::addUser(availableUID,availableGID)) { // Add the user to the system, also send next available UID and GID.
+ getUsers(); // Update users views.
+ getGroups(); // Update groups view.
+ }
+}
+
+void UserConfig::editUser() {
+ QString username;
+ if(myTabWidget->currentPageIndex()==0) { // Users
+ if(usersIconView->currentItem()) { // Any icon selected?
+ username=usersIconView->currentItem()->text(); // Get the text associated with the icon.
+ username=username.left(username.find(" - (",0,true)); // Strip out the username.
+ if(UserDialog::editUser(username)) { // Bring up the userinfo dialog.
+ // If there were any changed also update the views.
+ getUsers();
+ getGroups();
+ }
+ } else {
+ QMessageBox::information(this,"No selection.","No user has been selected.");
+ }
+ }
+ if(myTabWidget->currentPageIndex()==1) { // All users
+ if(usersListView->currentItem()) { // Anything changed!?
+ username=usersListView->currentItem()->text(1); // Get the username.
+ if(UserDialog::editUser(username)) { // Bring up the userinfo dialog.
+ // And again update the views if there were any changes.
+ getUsers();
+ getGroups();
+ }
+ } else {
+ QMessageBox::information(this,"No selection.","No user has been selected.");
+ }
+ }
+}
+
+void UserConfig::delUser() {
+ QString username;
+
+ if(myTabWidget->currentPageIndex()==0) { // Users, Iconview.
+ if(usersIconView->currentItem()) { // Anything selected?
+ username=usersIconView->currentItem()->text(); // Get string associated with icon.
+ username=username.left(username.find(" - (",0,true)); // Strip out the username.
+ if(QMessageBox::warning(this,"Delete user","Are you sure you want to\ndelete this user? \""+QString(username)+"\" ?","&No","&Yes",0,0,1)) {
+ if(UserDialog::delUser(username)) { // Delete the user if possible.
+ // Update views.
+ getUsers();
+ getGroups();
+ }
+ }
+ } else {
+ QMessageBox::information(this,"No selection","No user has been selected.");
+ }
+ }
+ if(myTabWidget->currentPageIndex()==1) { // All users
+ if(usersListView->currentItem()) { // Anything changed!?
+ username=usersListView->currentItem()->text(1); // Get the username.
+ if(QMessageBox::warning(this,"Delete user","Are you sure you want to\ndelete this user? \""+QString(username)+"\" ?","&No","&Yes",0,0,1)) {
+ if(UserDialog::delUser(username)) { // Try to delete the user.
+ // Update views.
+ getUsers();
+ getGroups();
+ }
+ }
+ } else {
+ QMessageBox::information(this,"No selection","No user has been selected.");
+ }
+ }
+
+}
+
+void UserConfig::getGroups() {
+ groupsListView->clear(); // Empty the listview.
+ availableGID=500; // We need to find the next free GID, and are only interested in values between 500 & 65000.
+ for(QStringList::Iterator it=accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) { // Split the list into lines.
+ accounts->splitGroupEntry(*it); // Split the line into its components and fill the variables of 'accounts'. (gr_name, gr_uid & gr_mem).
+ new QListViewItem(groupsListView,QString::number(accounts->gr_gid),accounts->gr_name);
+ if((accounts->gr_gid>=availableGID) && (accounts->gr_gid<65000)) availableGID=accounts->gr_gid+1; // Maybe a new free GID.
+ }
+}
+
+void UserConfig::addGroup() {
+ if(GroupDialog::addGroup(availableGID)) getGroups(); // Bring up the add group dialog.
+}
+
+void UserConfig::editGroup() {
+ int gid;
+ if(groupsListView->currentItem()) { // Any group selected?
+ gid=groupsListView->currentItem()->text(0).toInt(); // Get the GID from the listview.
+ if(GroupDialog::editGroup(gid)) getGroups(); // Bring up the edit group dialog.
+ } else {
+ QMessageBox::information(this,"No selection","No group has been selected.");
+ }
+}
+
+void UserConfig::delGroup() {
+ const char *groupname;
+ if(groupsListView->currentItem()) { // Any group selected?
+ groupname=groupsListView->currentItem()->text(1); // Get the groupname from the listview.
+ if(QMessageBox::warning(this,"Delete group","Are you sure you want to\ndelete the group \""+QString(groupname)+"\" ?","&No","&Yes",0,0,1)) {
+ // If confirmed, try to delete the group.
+ if(GroupDialog::delGroup(groupname)) getGroups(); // And also update the view afterwards if the user was deleted.
+ }
+ } else {
+ QMessageBox::information(this,"No selection","No group has been selected.");
+ }
+}
diff --git a/noncore/settings/usermanager/usermanager.h b/noncore/settings/usermanager/usermanager.h
new file mode 100644
index 0000000..bb5d04f
--- a/dev/null
+++ b/noncore/settings/usermanager/usermanager.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef USERCONFIG_H
+#define USERCONFIG_H
+
+#include <qmainwindow.h>
+#include <qtabwidget.h>
+#include <qlistview.h>
+#include <qiconview.h>
+
+#include <qpe/qpemenubar.h>
+#include <qpopupmenu.h>
+#include <qpe/qpetoolbar.h>
+#include <qtoolbutton.h>
+
+#include "userdialog.h"
+#include "groupdialog.h"
+#include "passwd.h"
+
+class UserConfig : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ UserConfig( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~UserConfig();
+
+private:
+ QToolButton *adduserToolButton;
+ QToolButton *edituserToolButton;
+ QToolButton *deleteuserToolButton;
+ QToolButton *addgroupToolButton;
+ QToolButton *editgroupToolButton;
+ QToolButton *deletegroupToolButton;
+ QTabWidget *myTabWidget;
+ QIconView *usersIconView;
+ QListView *usersListView;
+ QListView *groupsListView;
+ int availableUID;
+ int availableGID;
+ void setupTabAccounts();
+ void setupTabAllUsers();
+ void setupTabAllGroups();
+ void setupTabPrefs();
+ void setupTabAbout();
+ void getUsers();
+ void getGroups();
+
+private slots:
+ void addUser();
+ void editUser();
+ void delUser();
+ void addGroup();
+ void editGroup();
+ void delGroup();
+};
+
+#endif // USERCONFIG_H
diff --git a/noncore/settings/usermanager/usermanager.pro b/noncore/settings/usermanager/usermanager.pro
new file mode 100644
index 0000000..956d98e
--- a/dev/null
+++ b/noncore/settings/usermanager/usermanager.pro
@@ -0,0 +1,10 @@
+Package: userconfig
+Files: bin/usermanager apps/Settings/usermanager.desktop pics/userconfig/*
+Priority: optional
+Section: opie/settings
+Version: $QPE_VERSION-$SUB_VERSION-0.9
+Depends: opie-base ($QPE_VERSION)
+Architecture: arm
+Maintainer: Ted Parnefors <zaurus@bredband.net>
+License: GPL
+Description: User/Group manager for OPIE.