add more spacing
[personal-kdebase.git] / workspace / kdm / kfrontend / kgreeter.cpp
blobbfcc216cbdf0406db84c383db29623566db5ac09
1 /*
3 Greeter widget for kdm
5 Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
6 Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "kgreeter.h"
26 #include "kconsole.h"
27 #include "kdmconfig.h"
28 #include "kdmclock.h"
29 #include "kdm_greet.h"
30 #include "themer/kdmthemer.h"
31 #include "themer/kdmitem.h"
32 #include "themer/kdmlabel.h"
34 #include <KColorScheme>
35 #include <KConfigGroup>
36 #include <klocale.h>
37 #include <kseparator.h>
38 #include <kstandarddirs.h>
39 #include <kstringhandler.h>
41 #include <QAction>
42 #include <QBuffer>
43 #include <QDir>
44 #include <QFile>
45 #include <QImageReader>
46 #include <QKeyEvent>
47 #include <QLabel>
48 #include <QListWidget>
49 #include <QListWidgetItem>
50 #include <QMenu>
51 #include <QMovie>
52 #include <QPainter>
53 #include <QPushButton>
54 #include <QStyle>
56 #include <sys/types.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59 #include <fcntl.h>
60 #include <pwd.h>
61 #include <grp.h>
63 #include <X11/Xlib.h>
65 class UserListView : public QListWidget {
66 public:
67 UserListView( QWidget *parent = 0 )
68 : QListWidget( parent )
69 , cachedSizeHint( -1, 0 )
71 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Ignored );
72 setUniformItemSizes( true );
73 setVerticalScrollMode( ScrollPerPixel );
74 setIconSize( QSize( 48, 48 ) );
75 setAlternatingRowColors( true );
78 mutable QSize cachedSizeHint;
80 protected:
81 virtual QSize sizeHint() const
83 if (!cachedSizeHint.isValid()) {
84 ensurePolished();
85 QStyleOptionViewItem vo( viewOptions() );
86 QAbstractListModel *md( static_cast<QAbstractListModel *>(model()) );
87 uint maxw = 0, h = 0;
88 for (int i = 0, rc = md->rowCount(); i < rc; i++) {
89 QSize sh = itemDelegate()->sizeHint( vo, md->index( i ) );
90 uint thisw = sh.width();
91 if (thisw > maxw)
92 maxw = thisw;
93 h += sh.height();
95 cachedSizeHint.setWidth(
96 style()->pixelMetric( QStyle::PM_ScrollBarExtent ) +
97 (frameWidth() +
98 (style()->styleHint( QStyle::SH_ScrollView_FrameOnlyAroundContents ) ?
99 style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0)) * 2 +
100 maxw );
101 cachedSizeHint.setHeight( frameWidth() * 2 + h );
103 return cachedSizeHint;
106 virtual void keyPressEvent( QKeyEvent *event )
108 switch (event->key()) {
109 case Qt::Key_Enter:
110 case Qt::Key_Return:
111 if (currentItem())
112 emit itemDoubleClicked( currentItem() );
113 event->accept();
114 break;
115 case Qt::Key_Space:
116 if (currentItem())
117 emit itemClicked( currentItem() );
118 event->accept();
119 break;
120 default:
121 QListWidget::keyPressEvent( event );
122 break;
126 virtual void mousePressEvent( QMouseEvent *event )
128 m_suppressClick = false;
129 QListWidget::mousePressEvent(event);
132 virtual void mouseReleaseEvent( QMouseEvent *event )
134 if (m_suppressClick)
135 m_suppressClick = false;
136 else
137 QListWidget::mouseReleaseEvent(event);
140 virtual void mouseDoubleClickEvent( QMouseEvent *event )
142 m_suppressClick = true;
143 QListWidget::mouseDoubleClickEvent(event);
146 private:
147 bool m_suppressClick;
150 class UserListViewItem : public QListWidgetItem {
151 public:
152 UserListViewItem( UserListView *parent, const QString &text,
153 const QPixmap &pixmap, const QString &username )
154 : QListWidgetItem( parent )
155 , login( username )
157 setIcon( pixmap );
158 setText( text );
159 parent->cachedSizeHint.setWidth( -1 );
162 QString login;
166 int KGreeter::curPlugin = -1;
167 PluginList KGreeter::pluginList;
169 KGreeter::KGreeter( bool framed )
170 : inherited( framed )
171 , dName( dname )
172 , userView( 0 )
173 , userList( 0 )
174 , nNormals( 0 )
175 , nSpecials( 0 )
176 , curPrev( 0 )
177 , prevValid( true )
178 , needLoad( false )
180 stsGroup = new KConfigGroup( KSharedConfig::openConfig( _stsFile ),
181 "PrevUser" );
183 if (_userList) {
184 userView = new UserListView( this );
185 connect( userView, SIGNAL(itemClicked( QListWidgetItem * )),
186 SLOT(slotUserClicked( QListWidgetItem * )) );
187 connect( userView, SIGNAL(itemDoubleClicked( QListWidgetItem * )),
188 SLOT(accept()) );
190 if (_userCompletion)
191 userList = new QStringList;
192 if (userView || userList)
193 insertUsers();
195 sessMenu = new QMenu( this );
196 connect( sessMenu, SIGNAL(triggered( QAction * )),
197 SLOT(slotSessionSelected()) );
199 sessGroup = new QActionGroup( this );
200 insertSessions();
202 if (curPlugin < 0) {
203 curPlugin = 0;
204 pluginList = KGVerify::init( _pluginsLogin );
208 KGreeter::~KGreeter()
210 hide();
211 delete userList;
212 delete verify;
213 delete stsGroup;
216 #define FILE_LIMIT_ICON 20
217 #define FILE_LIMIT_IMAGE 200
218 #define PIXEL_LIMIT_ICON 100
219 #define PIXEL_LIMIT_IMAGE 300
221 static bool
222 loadFace( QByteArray &fn, QImage &p )
224 int fd, ico;
225 if ((fd = open( fn.data(), O_RDONLY | O_NONBLOCK )) < 0) {
226 fn.chop( 5 );
227 if ((fd = open( fn.data(), O_RDONLY | O_NONBLOCK )) < 0)
228 return false;
229 ico = 0;
230 } else
231 ico = 1;
232 QFile f;
233 f.open( fd, QFile::ReadOnly );
234 int fs = f.size();
235 if (fs > (ico ? FILE_LIMIT_ICON : FILE_LIMIT_IMAGE) * 1000) {
236 logWarn( "%s exceeds file size limit (%dkB)\n",
237 fn.data(), ico ? FILE_LIMIT_ICON : FILE_LIMIT_IMAGE );
238 return false;
240 QByteArray fc = f.read( fs );
241 ::close( fd );
242 QBuffer buf( &fc );
243 buf.open( QBuffer::ReadOnly );
244 QImageReader ir( &buf );
245 QSize sz = ir.size();
246 int lim = ico ? PIXEL_LIMIT_ICON : PIXEL_LIMIT_IMAGE;
247 if (sz.width() > lim || sz.height() > lim) {
248 logWarn( "%s exceeds image dimension limit (%dx%d)\n",
249 fn.data(), lim, lim );
250 return false;
252 sz.scale( 48, 48, Qt::KeepAspectRatio );
253 ir.setScaledSize( sz );
254 p = ir.read();
255 if (p.isNull()) {
256 logInfo( "%s is no valid image\n", fn.data() );
257 return false;
259 if (p.width() < 48) {
260 QImage np( 48, p.height(), QImage::Format_ARGB32 );
261 np.fill( 0 );
262 QPainter pnt( &np );
263 pnt.drawImage( (48 - p.width()) / 2, 0, p );
264 p = np;
266 return true;
269 void
270 KGreeter::insertUser( const QImage &default_pix,
271 const QString &username, struct passwd *ps )
273 if (userList)
274 userList->append( username );
275 if (!userView)
276 return;
278 int dp = 0, nd = 0;
279 if (_faceSource == FACE_USER_ONLY ||
280 _faceSource == FACE_PREFER_USER)
281 dp = 1;
282 if (_faceSource != FACE_USER_ONLY &&
283 _faceSource != FACE_ADMIN_ONLY)
284 nd = 1;
285 QImage p;
286 do {
287 dp ^= 1;
288 QByteArray fn = !dp ?
289 QByteArray( ps->pw_dir ) + '/' :
290 QFile::encodeName( _faceDir + '/' + username );
291 fn += ".face.icon";
292 if (loadFace( fn, p ))
293 goto gotit;
294 } while (--nd >= 0);
295 p = default_pix;
296 gotit:
297 QString realname = KStringHandler::from8Bit( ps->pw_gecos );
298 realname.truncate( realname.indexOf( ',' ) & (~0U >> 1) );
299 if (realname.isEmpty() || realname == username)
300 new UserListViewItem( userView, username, QPixmap::fromImage( p ), username );
301 else {
302 realname.append( "\n" ).append( username );
303 new UserListViewItem( userView, realname, QPixmap::fromImage( p ), username );
307 class UserList {
308 public:
309 UserList( char **in );
310 bool hasUser( const char *str ) const { return users.contains( str ); }
311 bool hasGroup( gid_t gid ) const { return groups.contains( gid ); }
312 bool hasGroups() const { return !groups.isEmpty(); }
314 private:
315 QSet<gid_t> groups;
316 QSet<QByteArray> users;
319 UserList::UserList( char **in )
321 struct group *grp;
323 for (; *in; in++)
324 if (**in == '@') {
325 if ((grp = getgrnam( *in + 1 ))) {
326 for (; *grp->gr_mem; grp->gr_mem++)
327 users.insert( *grp->gr_mem );
328 groups.insert( grp->gr_gid );
330 } else
331 users.insert( *in );
334 void
335 KGreeter::insertUsers()
337 struct passwd *ps;
339 // XXX remove seteuid-voodoo when we run as nobody
340 if (!(ps = getpwnam( "nobody" )))
341 return;
342 if (setegid( ps->pw_gid ))
343 return;
344 if (seteuid( ps->pw_uid )) {
345 setegid( 0 );
346 return;
349 QImage default_pix;
350 if (userView) {
351 QByteArray fn = QFile::encodeName( _faceDir + "/.default.face.icon" );
352 if (!loadFace( fn, default_pix )) {
353 logError( "Cannot open default user face\n" );
354 default_pix = QImage( 48, 48, QImage::Format_ARGB32 );
355 default_pix.fill( 0 );
358 if (_showUsers == SHOW_ALL) {
359 UserList noUsers( _noUsers );
360 QSet<QString> dupes;
361 for (setpwent(); (ps = getpwent()) != 0;) {
362 if (*ps->pw_dir && *ps->pw_shell &&
363 (ps->pw_uid >= (unsigned)_lowUserId ||
364 (!ps->pw_uid && _showRoot)) &&
365 ps->pw_uid <= (unsigned)_highUserId &&
366 !noUsers.hasUser( ps->pw_name ) &&
367 !noUsers.hasGroup( ps->pw_gid ))
369 QString username( QFile::decodeName( ps->pw_name ) );
370 if (!dupes.contains( username )) {
371 dupes.insert( username );
372 insertUser( default_pix, username, ps );
376 } else {
377 UserList users( _users );
378 if (users.hasGroups()) {
379 QSet<QString> dupes;
380 for (setpwent(); (ps = getpwent()) != 0;) {
381 if (*ps->pw_dir && *ps->pw_shell &&
382 (ps->pw_uid >= (unsigned)_lowUserId ||
383 (!ps->pw_uid && _showRoot)) &&
384 ps->pw_uid <= (unsigned)_highUserId &&
385 (users.hasUser( ps->pw_name ) ||
386 users.hasGroup( ps->pw_gid )))
388 QString username( QFile::decodeName( ps->pw_name ) );
389 if (!dupes.contains( username )) {
390 dupes.insert( username );
391 insertUser( default_pix, username, ps );
395 } else {
396 for (int i = 0; _users[i]; i++)
397 if ((ps = getpwnam( _users[i] )) && (ps->pw_uid || _showRoot))
398 insertUser( default_pix, QFile::decodeName( _users[i] ), ps );
401 endpwent();
402 endgrent();
403 if (_sortUsers) {
404 if (userView)
405 userView->sortItems();
406 if (userList)
407 userList->sort();
410 // XXX remove seteuid-voodoo when we run as nobody
411 seteuid( 0 );
412 setegid( 0 );
415 void
416 KGreeter::putSession( const QString &type, const QString &name, bool hid, const char *exe )
418 int prio = exe ? (!strcmp( exe, "default" ) ? 0 :
419 !strcmp( exe, "custom" ) ? 1 :
420 !strcmp( exe, "failsafe" ) ? 3 : 2) : 2;
421 for (int i = 0; i < sessionTypes.size(); i++)
422 if (sessionTypes[i].type == type) {
423 sessionTypes[i].prio = prio;
424 return;
426 sessionTypes.append( SessType( name, type, hid, prio ) );
429 void
430 KGreeter::insertSessions()
432 for (char **dit = _sessionsDirs; *dit; ++dit)
433 foreach (QString ent, QDir( *dit ).entryList())
434 if (ent.endsWith( ".desktop" )) {
435 KConfigGroup dsk(
436 KSharedConfig::openConfig(
437 QString( *dit ).append( '/' ).append( ent ) ),
438 "Desktop Entry" );
439 putSession( ent.left( ent.length() - 8 ),
440 dsk.readEntry( "Name" ),
441 (dsk.readEntry( "Hidden", false ) ||
442 (dsk.hasKey( "TryExec" ) &&
443 KStandardDirs::findExe(
444 dsk.readEntry( "TryExec" ) ).isEmpty())),
445 dsk.readEntry( "Exec" ).toLatin1() );
447 putSession( "default", i18nc("@item:inlistbox session type", "Default"), false, "default" );
448 putSession( "custom", i18nc("@item:inlistbox session type", "Custom"), false, "custom" );
449 putSession( "failsafe", i18nc("@item:inlistbox session type", "Failsafe"), false, "failsafe" );
450 qSort( sessionTypes );
451 for (int i = 0; i < sessionTypes.size() && !sessionTypes[i].hid; i++) {
452 sessionTypes[i].action = sessGroup->addAction( sessionTypes[i].name );
453 sessionTypes[i].action->setData( i );
454 sessionTypes[i].action->setCheckable( true );
455 switch (sessionTypes[i].prio) {
456 case 0: case 1: nSpecials++; break;
457 case 2: nNormals++; break;
460 sessMenu->addActions( sessGroup->actions() );
463 void
464 KGreeter::slotUserEntered()
466 struct passwd *pw;
468 if (userView) {
469 if ((pw = getpwnam( curUser.toLocal8Bit().data() ))) {
470 QString theUser = QString::fromLocal8Bit( pw->pw_name );
471 for (int i = 0, rc = userView->model()->rowCount(); i < rc; i++) {
472 UserListViewItem *item =
473 static_cast<UserListViewItem *>(userView->item( i ));
474 if (item->login == theUser) {
475 userView->setCurrentItem( item );
476 goto oke;
480 userView->clearSelection();
482 oke:
483 if (isVisible())
484 slotLoadPrevWM();
485 else
486 QTimer::singleShot( 0, this, SLOT(slotLoadPrevWM()) );
489 void
490 KGreeter::slotUserClicked( QListWidgetItem *item )
492 if (item) {
493 curUser = ((UserListViewItem *)item)->login;
494 verify->setUser( curUser );
495 slotLoadPrevWM();
499 void
500 KGreeter::slotSessionSelected()
502 verify->gplugChanged();
505 void
506 KGreeter::reject()
508 verify->reject();
511 void
512 KGreeter::accept()
514 verify->accept();
517 void // private
518 KGreeter::setPrevWM( QAction *wm )
520 if (curPrev != wm) {
521 if (curPrev)
522 curPrev->setText( sessionTypes[curPrev->data().toInt()].name );
523 if (wm)
524 wm->setText( i18nc( "@item:inmenu session type",
525 "%1 (previous)",
526 sessionTypes[wm->data().toInt()].name ) );
527 curPrev = wm;
531 void
532 KGreeter::slotLoadPrevWM()
534 int len, i, b;
535 unsigned long crc, by;
536 QByteArray name;
537 char *sess;
539 if (verify->coreLock) {
540 needLoad = true;
541 return;
543 needLoad = false;
545 prevValid = true;
546 name = curUser.toLocal8Bit();
547 gSendInt( G_ReadDmrc );
548 gSendStr( name.data() );
549 gRecvInt(); // ignore status code ...
550 if ((len = name.length())) {
551 gSendInt( G_GetDmrc );
552 gSendStr( "Session" );
553 sess = gRecvStr();
554 if (!sess) { /* no such user */
555 if (!userView && !userList) { // don't fake if user list shown
556 prevValid = false;
557 /* simple crc32 */
558 for (crc = _forgingSeed, i = 0; i < len; i++) {
559 by = (crc & 255) ^ name[i];
560 for (b = 0; b < 8; b++)
561 by = (by >> 1) ^ (-(by & 1) & 0xedb88320);
562 crc = (crc >> 8) ^ by;
564 /* forge a session with this hash - default & custom more probable */
565 /* XXX - this should do a statistical analysis of the real users */
566 #if 1
567 setPrevWM( sessionTypes[crc % (nSpecials * 2 + nNormals) % (nSpecials + nNormals)].action );
568 #else
569 i = crc % (nSpecials * 2 + nNormals);
570 if (i < nNormals)
571 setPrevWM( sessionTypes[i + nSpecials].action );
572 else
573 setPrevWM( sessionTypes[(i - nNormals) / 2].action );
574 #endif
575 return;
577 } else {
578 for (int i = 0; i < sessionTypes.count() && !sessionTypes[i].hid; i++)
579 if (sessionTypes[i].type == sess) {
580 free( sess );
581 setPrevWM( sessionTypes[i].action );
582 return;
584 if (!sessGroup->checkedAction())
585 KFMsgBox::box( this, sorrybox,
586 i18n("Your saved session type '%1' is not valid any more.\n"
587 "Please select a new one, otherwise 'default' will be used.", sess ) );
588 free( sess );
589 prevValid = false;
592 setPrevWM( 0 );
595 void // protected
596 KGreeter::pluginSetup()
598 int field = 0;
599 QString ent, pn( verify->pluginName() ), dn( dName + '_' + pn );
601 if (_preselUser != PRESEL_PREV)
602 stsGroup->deleteEntry( verify->entitiesLocal() ? dName : dn, false );
603 if (_preselUser != PRESEL_NONE && verify->entityPresettable()) {
604 if (verify->entitiesLocal())
605 ent = _preselUser == PRESEL_PREV ?
606 stsGroup->readEntry( dName, QString() ) : _defaultUser;
607 else
608 ent = _preselUser == PRESEL_PREV ?
609 stsGroup->readEntry( dn, QString() ) :
610 verify->getConf( 0, (pn + ".DefaultEntity").toLatin1(), QVariant() ).toString();
611 field = verify->entitiesFielded() ?
612 verify->getConf( 0, (pn + ".FocusField").toLatin1(), QVariant( 0 ) ).toInt() :
613 _focusPasswd;
615 verify->presetEntity( ent, field );
616 if (userList)
617 verify->loadUsers( *userList );
620 void
621 KGreeter::verifyPluginChanged( int id )
623 curPlugin = id;
624 pluginSetup();
627 void
628 KGreeter::verifyClear()
630 curUser.clear();
631 slotUserEntered();
632 if (QAction *curSel = sessGroup->checkedAction())
633 curSel->setChecked( false );
636 void
637 KGreeter::verifyOk()
639 if (_preselUser == PRESEL_PREV && verify->entityPresettable())
640 stsGroup->writeEntry( verify->entitiesLocal() ?
641 dName :
642 dName + '_' + verify->pluginName(),
643 verify->getEntity() );
644 if (QAction *curSel = sessGroup->checkedAction()) {
645 gSendInt( G_PutDmrc );
646 gSendStr( "Session" );
647 gSendStr( sessionTypes[curSel->data().toInt()].type.toUtf8() );
648 } else if (!prevValid) {
649 gSendInt( G_PutDmrc );
650 gSendStr( "Session" );
651 gSendStr( "default" );
653 done( ex_login );
656 void
657 KGreeter::verifyFailed()
659 if (userView)
660 userView->setEnabled( false );
661 if (needLoad)
662 slotLoadPrevWM();
665 void
666 KGreeter::verifyRetry()
668 if (userView)
669 userView->setEnabled( true );
672 void
673 KGreeter::verifySetUser( const QString &user )
675 curUser = user;
676 slotUserEntered();
680 KStdGreeter::KStdGreeter()
681 : KGreeter()
682 , clock( 0 )
683 , pixLabel( 0 )
685 QBoxLayout *main_box;
686 #ifdef WITH_KDM_XCONSOLE
687 if (consoleView) {
688 QBoxLayout *ex_box = new QVBoxLayout( this );
689 main_box = new QHBoxLayout();
690 ex_box->addLayout( main_box );
691 ex_box->addWidget( consoleView );
692 } else
693 #endif
695 main_box = new QHBoxLayout( this );
697 int rs = layout()->spacing();
698 main_box->setSpacing( layout()->margin() );
700 if (userView)
701 main_box->addWidget( userView );
703 QBoxLayout *inner_box = new QVBoxLayout();
704 main_box->addLayout( inner_box );
705 inner_box->setSpacing( rs );
707 if (!_authorized && _authComplain) {
708 QLabel *complainLabel = new QLabel(
709 i18n("Warning: this is an unsecured session"), this );
710 complainLabel->setToolTip(
711 i18n("This display requires no X authorization.\n"
712 "This means that anybody can connect to it,\n"
713 "open windows on it or intercept your input.") );
714 complainLabel->setAlignment( Qt::AlignCenter );
715 complainLabel->setFont( *_failFont );
716 QPalette p;
717 p.setBrush( QPalette::WindowText,
718 KColorScheme( QPalette::Active, KColorScheme::Window )
719 .foreground( KColorScheme::NegativeText ) );
720 complainLabel->setPalette( p );
721 inner_box->addWidget( complainLabel );
723 if (!_greetString.isEmpty()) {
724 QLabel *welcomeLabel = new QLabel( _greetString, this );
725 welcomeLabel->setAlignment( Qt::AlignCenter );
726 welcomeLabel->setFont( *_greetFont );
727 inner_box->addWidget( welcomeLabel );
730 switch (_logoArea) {
731 case LOGO_CLOCK:
732 clock = new KdmClock( this );
733 break;
734 case LOGO_LOGO:
736 QMovie *movie = new QMovie( this );
737 movie->setFileName( _logo );
738 if (movie->isValid()) {
739 movie->start();
740 pixLabel = new QLabel( this );
741 pixLabel->setMovie( movie );
742 if (!movie->currentImage().hasAlphaChannel())
743 pixLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
744 pixLabel->setIndent( 0 );
745 } else
746 delete movie;
748 break;
751 if (userView) {
752 if (clock)
753 inner_box->addWidget( clock, 0, Qt::AlignCenter );
754 else if (pixLabel)
755 inner_box->addWidget( pixLabel, 0, Qt::AlignCenter );
756 inner_box->addSpacing( inner_box->spacing() );
757 } else {
758 if (clock)
759 main_box->addWidget( clock, 0, Qt::AlignCenter );
760 else if (pixLabel)
761 main_box->addWidget( pixLabel, 0, Qt::AlignCenter );
764 goButton = new QPushButton( i18nc("@action:button", "L&ogin"), this );
765 goButton->setDefault( true );
766 connect( goButton, SIGNAL(clicked()), SLOT(accept()) );
767 QPushButton *menuButton = new QPushButton( i18nc("@action:button", "&Menu"), this );
768 //helpButton
770 QWidget *prec;
771 if (userView)
772 prec = userView;
773 #ifdef WITH_KDM_XCONSOLE
774 else if (consoleView)
775 prec = consoleView;
776 #endif
777 else
778 prec = menuButton;
779 KGStdVerify *sverify =
780 new KGStdVerify( this, this, prec, QString(),
781 pluginList, KGreeterPlugin::Authenticate,
782 KGreeterPlugin::Login );
783 inner_box->addLayout( sverify->getLayout() );
784 QMenu *plugMenu = sverify->getPlugMenu();
785 sverify->selectPlugin( curPlugin );
786 verify = sverify;
788 inner_box->addWidget( new KSeparator( Qt::Horizontal, this ) );
790 QBoxLayout *hbox2 = new QHBoxLayout();
791 inner_box->addLayout( hbox2 );
792 hbox2->addWidget( goButton );
793 hbox2->addStretch( 1 );
794 hbox2->addWidget( menuButton );
795 hbox2->addStretch( 1 );
797 if (sessMenu->actions().count() > 1) {
798 inserten( i18nc("@title:menu", "Session &Type"), Qt::ALT+Qt::Key_T, sessMenu );
799 needSep = true;
802 if (plugMenu) {
803 inserten( i18nc("@title:menu", "&Authentication Method"), Qt::ALT+Qt::Key_A, plugMenu );
804 needSep = true;
807 #ifdef XDMCP
808 completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18nc("@action:inmenu", "&Remote Login"), Qt::ALT+Qt::Key_R );
809 #else
810 completeMenu();
811 #endif
813 if (optMenu)
814 menuButton->setMenu( optMenu );
815 else
816 menuButton->hide();
818 pluginSetup();
820 verify->start();
823 void
824 KStdGreeter::pluginSetup()
826 inherited::pluginSetup();
827 if (userView) {
828 if (verify->entitiesLocal() && verify->entityPresettable())
829 userView->show();
830 else
831 userView->hide();
833 adjustGeometry();
834 update();
837 void
838 KStdGreeter::verifyFailed()
840 goButton->setEnabled( false );
841 inherited::verifyFailed();
844 void
845 KStdGreeter::verifyRetry()
847 goButton->setEnabled( true );
848 inherited::verifyRetry();
852 KThemedGreeter::KThemedGreeter( KdmThemer *_themer )
853 : KGreeter( true )
854 , themer( _themer )
855 // , clock( 0 )
857 // We do all painting ourselves
858 setAttribute( Qt::WA_NoSystemBackground, true );
859 // Allow tracking the mouse position
860 setMouseTracking( true );
862 adjustGeometry();
864 themer->setWidget( this );
866 connect( themer, SIGNAL(activated( const QString & )),
867 SLOT(slotThemeActivated( const QString & )) );
869 KdmItem *console_node = themer->findNode( "xconsole" ); // kdm ext
870 KdmItem *console_rect = themer->findNode( "xconsole-rect" ); // kdm ext
871 if (!console_rect)
872 console_rect = console_node;
873 userlist_node = themer->findNode( "userlist" );
874 userlist_rect = themer->findNode( "userlist-rect" );
875 if (!userlist_rect)
876 userlist_rect = userlist_node;
877 caps_warning = themer->findNode( "caps-lock-warning" );
878 xauth_warning = themer->findNode( "xauth-warning" ); // kdm ext
879 pam_error = themer->findNode( "pam-error" );
880 KdmLabel *pam_error_label = qobject_cast<KdmLabel *>(pam_error);
881 if (pam_error_label)
882 pam_error_label->setText( i18n("Login failed") );
883 timed_label = themer->findNode( "timed-label" );
885 KdmItem *itm;
886 if ((itm = themer->findNode( "pam-message" ))) // done via msgboxes
887 itm->setVisible( false );
888 if ((itm = themer->findNode( "language_button" ))) // not implemented yet
889 itm->setVisible( false );
891 if (console_node) {
892 #ifdef WITH_KDM_XCONSOLE
893 if (consoleView)
894 console_node->setWidget( consoleView );
895 else
896 #endif
897 console_rect->setVisible( false );
900 if (xauth_warning && (_authorized || !_authComplain))
901 xauth_warning->setVisible( false );
903 // if (!_greetString.isEmpty()) {
904 // }
905 // clock = new KdmClock( this, "clock" );
907 QWidget *prec;
908 if (userView)
909 prec = userView;
910 #ifdef WITH_KDM_XCONSOLE
911 else if (consoleView)
912 prec = consoleView;
913 #endif
914 else
915 prec = 0;
916 KGThemedVerify *tverify =
917 new KGThemedVerify( this, themer, this, prec, QString(),
918 pluginList, KGreeterPlugin::Authenticate,
919 KGreeterPlugin::Login );
920 QMenu *plugMenu = tverify->getPlugMenu();
921 tverify->selectPlugin( curPlugin );
922 verify = tverify;
924 if ((session_button = themer->findNode( "session_button" ))) {
925 if (sessMenu->actions().count() <= 1) {
926 session_button->setVisible( false );
927 session_button = 0;
929 } else {
930 if (sessMenu->actions().count() > 1) {
931 inserten( i18nc("@title:menu", "Session &Type"), Qt::ALT+Qt::Key_T, sessMenu );
932 needSep = true;
936 if (plugMenu) {
937 inserten( i18nc("@title:menu", "&Authentication Method"), Qt::ALT+Qt::Key_A, plugMenu );
938 needSep = true;
941 #ifdef XDMCP
942 completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18nc("@action:inmenu", "&Remote Login"), Qt::ALT+Qt::Key_R );
943 #else
944 completeMenu();
945 #endif
947 if ((system_button = themer->findNode( "system_button" ))) {
948 if (optMenu)
949 addAction( optMenu->menuAction() );
950 else
951 system_button->setVisible( false );
954 pluginSetup();
956 verify->start();
959 KThemedGreeter::~KThemedGreeter()
961 themer->setWidget( 0 );
964 bool
965 KThemedGreeter::event( QEvent *e )
967 if (themer)
968 themer->widgetEvent( e );
969 return inherited::event( e );
972 void
973 KThemedGreeter::pluginSetup()
975 inherited::pluginSetup();
977 if (userView && verify->entitiesLocal() && verify->entityPresettable() && userlist_node) {
978 userlist_node->setWidget( userView );
979 userlist_rect->setVisible( true );
980 } else {
981 if (userView)
982 userView->hide();
983 if (userlist_rect)
984 userlist_rect->setVisible( false );
988 #if 0
989 void
990 KThemedGreeter::verifyFailed()
992 // goButton->setEnabled( false );
993 inherited::verifyFailed();
996 void
997 KThemedGreeter::verifyRetry()
999 // goButton->setEnabled( true );
1000 inherited::verifyRetry();
1002 #endif
1004 void
1005 KThemedGreeter::updateStatus( bool fail, bool caps, int timedleft )
1007 if (pam_error)
1008 pam_error->setVisible( fail );
1009 if (caps_warning)
1010 caps_warning->setVisible( caps );
1011 if (timed_label) {
1012 if (timedleft) {
1013 if (timedleft != KdmLabel::timedDelay) {
1014 KdmLabel::timedDelay = timedleft;
1015 KdmLabel::timedUser = curUser;
1016 timed_label->setVisible( true );
1017 timed_label->update();
1019 } else {
1020 KdmLabel::timedDelay = -1;
1021 timed_label->setVisible( false );
1026 void
1027 KThemedGreeter::slotThemeActivated( const QString &id )
1029 if (id == "login_button")
1030 accept();
1031 else if (id == "session_button")
1032 slotSessMenu();
1033 else if (id == "system_button")
1034 slotActionMenu();
1037 void
1038 KThemedGreeter::slotSessMenu()
1040 sessMenu->popup( mapToGlobal( session_button->rect().center() ) );
1043 void
1044 KThemedGreeter::slotActionMenu()
1046 if (system_button)
1047 optMenu->popup( mapToGlobal( system_button->rect().center() ) );
1048 else
1049 optMenu->popup( mapToGlobal( rect().center() ) );
1052 void
1053 KThemedGreeter::keyPressEvent( QKeyEvent *e )
1055 inherited::keyPressEvent( e );
1056 if (!(e->modifiers() & ~Qt::KeypadModifier) &&
1057 (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter))
1058 accept();
1061 #include "kgreeter.moc"