--- kgreeter.cpp	2008-02-13 02:40:49.000000000 -0700
+++ kgreeter.cpp.new	2008-02-23 08:10:41.000000000 -0700
@@ -38,6 +38,7 @@
 #include <klistview.h>
 #include <ksimpleconfig.h>
 #include <kstringhandler.h>
+#include <kdebug.h>
 
 #undef Unsorted // x headers suck - make qdir.h work with --enable-final
 #include <qdir.h>
@@ -46,6 +47,7 @@
 #include <qmemarray.h>
 #include <qimage.h>
 #include <qmovie.h>
+#include <qpainter.h>
 #include <qpopupmenu.h>
 #include <qtimer.h>
 #include <qheader.h>
@@ -63,27 +65,46 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
-
+#include <utmp.h>
+#include <utmpx.h>
 #include <X11/Xlib.h>
 
 class UserListView : public KListView {
   public:
-	UserListView( QWidget *parent = 0, const char *name = 0 )
+	UserListView( bool _them, QWidget *parent = 0, const char *name = 0 )
 		: KListView( parent, name )
-		, cachedSizeHint( -1, 0 )
+		, themed(_them), cachedSizeHint( -1, 0 )
 	{
 		setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored );
 		header()->hide();
 		addColumn( QString::null );
 		setColumnAlignment( 0, AlignVCenter );
 		setResizeMode( QListView::LastColumn );
+		if (themed) {
+		  setBackgroundMode( Qt::NoBackground );
+		  viewport()->setBackgroundMode( Qt::NoBackground );
+		  setFrameStyle( QFrame::NoFrame );
+		}
 	}
 
+	bool themed;
 	mutable QSize cachedSizeHint;
 
-  protected:
-	virtual QSize sizeHint() const
+        int sumHeight() const 
+  {
+        int sum = 0;
+        for (QListViewItem *itm = firstChild(); itm; itm = itm->nextSibling()) {
+            sum += itm->height();
+        }
+        return sum;
+    }
+public:
+	
+virtual QSize sizeHint() const
 	{
+	  if (themed)
+            return KListView::sizeHint();
+
 		if (!cachedSizeHint.isValid()) {
 			constPolish();
 			uint maxw = 0;
@@ -98,8 +119,23 @@
 		}
 		return cachedSizeHint;
 	}
-};
+    virtual void paintEmptyArea ( QPainter * p, const QRect & rect )
+    {
+      if (!themed)
+        return KListView::paintEmptyArea(p, rect );
+
+        const QPixmap *pm = paletteBackgroundPixmap();
+        if (!pm || pm->isNull())
+            return;
+
+        kdDebug() << "paintEmpty " << rect << endl;
+        QRect devRect = p->xForm( rect );
+        kdDebug() << "paintEmpty2 " << devRect << endl;
+        p->drawPixmap(0, 0, *pm, devRect.left(), devRect.top() );
+    }
 
+    QPixmap background;
+};
 
 int KGreeter::curPlugin = -1;
 PluginList KGreeter::pluginList;
@@ -115,12 +151,14 @@
   , curSel( -1 )
   , prevValid( true )
   , needLoad( false )
+  , themed( framed )
 {
 	stsFile = new KSimpleConfig( _stsFile );
 	stsFile->setGroup( "PrevUser" );
 
 	if (_userList) {
-		userView = new UserListView( this );
+		readFacesList();
+		userView = new UserListView( framed, this );
 		connect( userView, SIGNAL(clicked( QListViewItem * )),
 		         SLOT(slotUserClicked( QListViewItem * )) );
 		connect( userView, SIGNAL(doubleClicked( QListViewItem * )),
@@ -128,8 +166,6 @@
 	}
 	if (_userCompletion)
 		userList = new QStringList;
-	if (userView || userList)
-		insertUsers();
 
 	sessMenu = new QPopupMenu( this );
 	connect( sessMenu, SIGNAL(activated( int )),
@@ -150,6 +186,33 @@
 	delete stsFile;
 }
 
+void KGreeter::readFacesList()
+{
+    FILE *f = fopen( QFile::encodeName( _faceDir + "/.randomlist" ), "rt" );
+    if ( !f )
+        return;
+    QTextIStream is( f );
+    while ( !is.eof() )
+    {
+        QString line = is.readLine().simplifyWhiteSpace();
+        if ( line.isEmpty() )
+            continue;
+        QString icon;
+        int index = line.find( ' ' );
+        if ( index > 0 ) {
+            icon = line.left( index );
+            line = line.mid( index );
+        } else {
+            icon = line;
+            line = QString::null;
+        }
+        randomFaces.push_back( icon );
+        QStringList list = QStringList::split( ' ', line );
+        for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
+            randomFacesMap[*it] = icon;
+    }
+}
+
 class UserListViewItem : public KListViewItem {
   public:
 	UserListViewItem( UserListView *parent, const QString &text,
@@ -163,6 +226,14 @@
 		parent->cachedSizeHint.setWidth( -1 );
 	}
 
+        virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+    {
+      if (((UserListView*)listView())->themed)
+        QListViewItem::paintCell(p, cg, column, width, alignment);
+      else
+	KListViewItem::paintCell(p, cg, column, width, alignment);
+    }
+
 	QString login;
 };
 
@@ -226,9 +297,23 @@
 			p = p.convertDepth( 32 ).smoothScale( ns, QImage::ScaleMin );
 		goto gotit;
 	} while (--nd >= 0);
-	p = default_pix;
-  gotit:
-	QString realname = KStringHandler::from8Bit( ps->pw_gecos );
+
+        if ( p.isNull() && randomFaces.count() ) {
+            QString randomFace = randomFacesMap[username];
+            if ( randomFace.isNull() ) {
+                QStringList::size_type index = 0;
+                for ( size_t i = 0; i < username.length(); ++i )
+                    index += ( 0x7f - username.at( i ).latin1() ) % 37;
+                randomFace = randomFaces[ index % randomFaces.count() ];
+            }
+            p.load( _faceDir + "/../pics/users/" + randomFace + ".png" );
+        }
+
+        if ( p.isNull() )
++            p = default_pix;
++
+	
+QString realname = KStringHandler::from8Bit( ps->pw_gecos );
 	realname.truncate( realname.find( ',' ) );
 	if (realname.isEmpty() || realname == username)
 		new UserListViewItem( userView, username, QPixmap( p ), username );
@@ -278,7 +363,7 @@
 }
 
 void
-KGreeter::insertUsers()
+KGreeter::insertUsers(int limit_users)
 {
 	struct passwd *ps;
 
@@ -305,6 +390,8 @@
 	if (_showUsers == SHOW_ALL) {
 		UserList noUsers( _noUsers );
 		QDict<int> dupes( 1000 );
+                QStringList toinsert;
+                int count = 0;
 		for (setpwent(); (ps = getpwent()) != 0;) {
 			if (*ps->pw_dir && *ps->pw_shell &&
 			    (ps->pw_uid >= (unsigned)_lowUserId ||
@@ -316,11 +403,55 @@
 				QString username( QFile::decodeName( ps->pw_name ) );
 				if (!dupes.find( username )) {
 					dupes.insert( username, (int *)-1 );
-					insertUser( default_pix, username, ps );
+                                        toinsert.append( username );
+
+                                        if ( limit_users >= 0 && ++count > limit_users )
+                                            break;
+				
 				}
 			}
 		}
-	} else {
+                if ( limit_users >= 0 && ++count > limit_users ) {
+                    utmpname( _PATH_WTMP );
+                    setutxent();
+                    toinsert = QStringList();
+                    dupes.clear();
+
+                    for ( count = 0; count < limit_users; ) {
+                        struct utmpx * ent = getutxent();
+                        if ( !ent )
+                            break;
+                        struct passwd *ps = getpwnam( ent->ut_user );
+                        if (ps && *ps->pw_dir && *ps->pw_shell &&
+			    (ps->pw_uid >= (unsigned)_lowUserId ||
+			     !ps->pw_uid && _showRoot) &&
+			    ps->pw_uid <= (unsigned)_highUserId &&
+			    !noUsers.hasUser( ps->pw_name ) &&
+			    !noUsers.hasGroup( ps->pw_gid ))
+                        {
+                            QString username( QFile::decodeName( ent->ut_user ) );
+                            if (!dupes.find( username )) {
+                                dupes.insert( username, (int *)-1 );
+                                toinsert.append( username );
+                                count++;
+                            }
+                        }
+
+
+                    }
+                    endutxent();
+                }
+
+                for ( QStringList::ConstIterator it = toinsert.begin();
+                      it != toinsert.end(); ++it )
+                {
+                    // pretty stupid to do another lookup round, but the number is limited
+                    // and caching struct passwd is pretty ugly
+                    struct passwd *ps = getpwnam( QFile::encodeName( *it ) );
+                    if ( ps )
+                        insertUser( default_pix, *it, ps );
+	} 
+else {
 		UserList users( _users );
 		if (users.hasGroups()) {
 			QDict<int> dupes( 1000 );
@@ -721,21 +852,24 @@
 	hbox2->addStretch( 1 );
 
 	if (sessMenu->count() > 1) {
-		inserten( i18n("Session &Type"), ALT+Key_T, sessMenu );
+		inserten( i18n("Session &Type"), 0, sessMenu );
 		needSep = true;
 	}
 
 	if (plugMenu) {
-		inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu );
+		inserten( i18n("&Authentication Method"), 0, plugMenu );
 		needSep = true;
 	}
 
 #ifdef XDMCP
-	completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R );
+	completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 );
 #else
 	completeMenu();
 #endif
 
+        if (userView || userList)
+		insertUsers();
+
 	if (optMenu)
 		menuButton->setPopup( optMenu );
 	else
@@ -829,7 +963,11 @@
 	if (xauth_warning && (_authorized || !_authComplain))
 		xauth_warning->hide( true );
 
-//	if (!_greetString.isEmpty()) {
+        if (userView || userList)
+            insertUsers( 7 ); // TODO: find out how many are a good value
+
+//	
+if (!_greetString.isEmpty()) {
 //	}
 //	clock = new KdmClock( this, "clock" );
 
@@ -854,34 +992,27 @@
 	if ((itm = themer->findNode( "session_button" ))) {
 		if (sessMenu->count() <= 1)
 			itm->hide( true );
-		else {
+		else 
 			session_button = itm;
-			QAccel *accel = new QAccel( this );
-			accel->insertItem( ALT+Key_T, 0 );
-			connect( accel, SIGNAL(activated( int )), SLOT(slotSessMenu()) );
-		}
 	} else {
 		if (sessMenu->count() > 1) {
-			inserten( i18n("Session &Type"), ALT+Key_T, sessMenu );
+			inserten( i18n("Session &Type"), 0, sessMenu );
 			needSep = true;
 		}
 	}
 
 	if (plugMenu) {
-		inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu );
+		inserten( i18n("&Authentication Method"), 0, plugMenu );
 		needSep = true;
 	}
 
 #ifdef XDMCP
-	completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R );
+	completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 );
 #else
 	completeMenu();
 #endif
 
 	system_button = themer->findNode( "system_button" );
-	QAccel *accel = new QAccel( this );
-	accel->insertItem( ALT+Key_M, 0 );
-	connect( accel, SIGNAL(activated( int )), SLOT(slotActionMenu()) );
 
 	pluginSetup();
 
@@ -902,8 +1033,8 @@
 	inherited::pluginSetup();
 
 	if (userView && verify->entitiesLocal() && verify->entityPresettable() && userlist_rect) {
+		userView->setMaximumHeight( userView->sumHeight() );
 		userlist_rect->setWidget( userView );
-		userView->show();
 	} else {
 		if (userView)
 			userView->hide();
@@ -919,12 +1050,17 @@
 {
 //	goButton->setEnabled( false );
 	inherited::verifyFailed();
+	if (userView)
+		userView->setEnabled(false);
 }
 
 void
 KThemedGreeter::verifyRetry()
 {
 //	goButton->setEnabled( true );
+	if (userView)
+		userView->setEnabled(true);
+
 }
 
 QString KThemedGreeter::timedUser = QString::null;
