summaryrefslogtreecommitdiffstats
path: root/kcontrol/tdm/tdm-users.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/tdm/tdm-users.cpp')
-rw-r--r--kcontrol/tdm/tdm-users.cpp500
1 files changed, 500 insertions, 0 deletions
diff --git a/kcontrol/tdm/tdm-users.cpp b/kcontrol/tdm/tdm-users.cpp
new file mode 100644
index 000000000..f4b48b9a6
--- /dev/null
+++ b/kcontrol/tdm/tdm-users.cpp
@@ -0,0 +1,500 @@
+/* This file is part of the KDE Display Manager Configuration package
+ Copyright (C) 1997 Thomas Tanghus (tanghus@earthling.net)
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <tqstyle.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqtooltip.h>
+#include <tqvalidator.h>
+#include <tqwhatsthis.h>
+#include <tqvgroupbox.h>
+#include <tqpushbutton.h>
+
+#include <kfiledialog.h>
+#include <kimageio.h>
+#include <kimagefilepreview.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kurldrag.h>
+
+#include "tdm-users.h"
+
+#include <sys/stat.h>
+
+
+extern KSimpleConfig *config;
+
+TDMUsersWidget::TDMUsersWidget(TQWidget *parent, const char *name)
+ : TQWidget(parent, name)
+{
+#ifdef __linux__
+ struct stat st;
+ if (!stat( "/etc/debian_version", &st )) { /* debian */
+ defminuid = "1000";
+ defmaxuid = "29999";
+ } else if (!stat( "/usr/portage", &st )) { /* gentoo */
+ defminuid = "1000";
+ defmaxuid = "65000";
+ } else if (!stat( "/etc/mandrake-release", &st )) { /* mandrake - check before redhat! */
+ defminuid = "500";
+ defmaxuid = "65000";
+ } else if (!stat( "/etc/redhat-release", &st )) { /* redhat */
+ defminuid = "100";
+ defmaxuid = "65000";
+ } else /* if (!stat( "/etc/SuSE-release", &st )) */ { /* suse */
+ defminuid = "500";
+ defmaxuid = "65000";
+ }
+#else
+ defminuid = "1000";
+ defmaxuid = "65000";
+#endif
+
+ // We assume that $kde_datadir/tdm exists, but better check for pics/ and pics/users,
+ // and create them if necessary.
+ config->setGroup( "X-*-Greeter" );
+ m_userPixDir = config->readEntry( "FaceDir", KGlobal::dirs()->resourceDirs("data").last() + "tdm/faces" ) + '/';
+ m_notFirst = false;
+ TQDir testDir( m_userPixDir );
+ if ( !testDir.exists() && !testDir.mkdir( testDir.absPath() ) && !geteuid() )
+ KMessageBox::sorry( this, i18n("Unable to create folder %1").arg( testDir.absPath() ) );
+ chmod( TQFile::encodeName( m_userPixDir ), 0755 );
+
+ m_defaultText = i18n("<default>");
+
+ TQString wtstr;
+
+ minGroup = new TQGroupBox( 2, Qt::Horizontal, i18n("System U&IDs"), this );
+ TQWhatsThis::add( minGroup, i18n("Users with a UID (numerical user identification) outside this range will not be listed by TDM and this setup dialog."
+ " Note that users with the UID 0 (typically root) are not affected by this and must be"
+ " explicitly hidden in \"Not hidden\" mode."));
+ TQSizePolicy sp_ign_fix( TQSizePolicy::Ignored, TQSizePolicy::Fixed );
+ TQValidator *valid = new TQIntValidator( 0, 999999, TQT_TQOBJECT(minGroup) );
+ TQLabel *minlab = new TQLabel( i18n("Below:"), minGroup );
+ leminuid = new KLineEdit( minGroup );
+ minlab->setBuddy( leminuid );
+ leminuid->setSizePolicy( sp_ign_fix );
+ leminuid->setValidator( valid );
+ connect( leminuid, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotChanged()) );
+ connect( leminuid, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotMinMaxChanged()) );
+ TQLabel *maxlab = new TQLabel( i18n("Above:"), minGroup );
+ lemaxuid = new KLineEdit( minGroup );
+ maxlab->setBuddy( lemaxuid );
+ lemaxuid->setSizePolicy( sp_ign_fix );
+ lemaxuid->setValidator( valid );
+ connect(lemaxuid, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotChanged()) );
+ connect(lemaxuid, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotMinMaxChanged()) );
+
+ usrGroup = new TQButtonGroup( 5, Qt::Vertical, i18n("Users"), this );
+ connect( usrGroup, TQT_SIGNAL(clicked( int )), TQT_SLOT(slotShowOpts()) );
+ connect( usrGroup, TQT_SIGNAL(clicked( int )), TQT_SLOT(slotChanged()) );
+ cbshowlist = new TQCheckBox( i18n("Show list"), usrGroup );
+ TQWhatsThis::add( cbshowlist, i18n("If this option is checked, TDM will show a list of users,"
+ " so users can click on their name or image rather than typing in their login.") );
+ cbcomplete = new TQCheckBox( i18n("Autocompletion"), usrGroup );
+ TQWhatsThis::add( cbcomplete, i18n("If this option is checked, TDM will automatically complete"
+ " user names while they are typed in the line edit.") );
+ cbinverted = new TQCheckBox( i18n("Inverse selection"), usrGroup );
+ TQWhatsThis::add( cbinverted, i18n("This option specifies how the users for \"Show list\" and \"Autocompletion\""
+ " are selected in the \"Select users and groups\" list: "
+ "If not checked, select only the checked users. "
+ "If checked, select all non-system users, except the checked ones."));
+ cbusrsrt = new TQCheckBox( i18n("Sor&t users"), usrGroup );
+ connect( cbusrsrt, TQT_SIGNAL(toggled( bool )), TQT_SLOT(slotChanged()) );
+ TQWhatsThis::add( cbusrsrt, i18n("If this is checked, TDM will alphabetically sort the user list."
+ " Otherwise users are listed in the order they appear in the password file.") );
+
+ wstack = new TQWidgetStack( this );
+ s_label = new TQLabel( wstack, i18n("S&elect users and groups:"), this );
+ optinlv = new KListView( this );
+ optinlv->addColumn( i18n("Selected Users") );
+ optinlv->setResizeMode( TQListView::LastColumn );
+ TQWhatsThis::add( optinlv, i18n("TDM will show all checked users. Entries denoted with '@' are user groups. Checking a group is like checking all users in that group.") );
+ wstack->addWidget( optinlv );
+ connect( optinlv, TQT_SIGNAL(clicked( TQListViewItem * )),
+ TQT_SLOT(slotUpdateOptIn( TQListViewItem * )) );
+ connect( optinlv, TQT_SIGNAL(clicked( TQListViewItem * )),
+ TQT_SLOT(slotChanged()) );
+ optoutlv = new KListView( this );
+ optoutlv->addColumn( i18n("Hidden Users") );
+ optoutlv->setResizeMode( TQListView::LastColumn );
+ TQWhatsThis::add( optoutlv, i18n("TDM will show all non-checked non-system users. Entries denoted with '@' are user groups. Checking a group is like checking all users in that group.") );
+ wstack->addWidget( optoutlv );
+ connect( optoutlv, TQT_SIGNAL(clicked( TQListViewItem * )),
+ TQT_SLOT(slotUpdateOptOut( TQListViewItem * )) );
+ connect( optoutlv, TQT_SIGNAL(clicked( TQListViewItem * )),
+ TQT_SLOT(slotChanged()) );
+
+ faceGroup = new TQButtonGroup( 5, Qt::Vertical, i18n("User Image Source"), this );
+ TQWhatsThis::add( faceGroup, i18n("Here you can specify where TDM will obtain the images that represent users."
+ " \"Admin\" represents the global folder; these are the pictures you can set below."
+ " \"User\" means that TDM should read the user's $HOME/.face.icon file."
+ " The two selections in the middle define the order of preference if both sources are available.") );
+ connect( faceGroup, TQT_SIGNAL(clicked( int )), TQT_SLOT(slotFaceOpts()) );
+ connect( faceGroup, TQT_SIGNAL(clicked( int )), TQT_SLOT(slotChanged()) );
+ rbadmonly = new TQRadioButton( i18n("Admin"), faceGroup );
+ rbprefadm = new TQRadioButton( i18n("Admin, user"), faceGroup );
+ rbprefusr = new TQRadioButton( i18n("User, admin"), faceGroup );
+ rbusronly = new TQRadioButton( i18n("User"), faceGroup );
+
+ TQGroupBox *picGroup = new TQVGroupBox( i18n("User Images"), this );
+ TQWidget *hlpw = new TQWidget( picGroup );
+ usercombo = new KComboBox( hlpw );
+ TQWhatsThis::add( usercombo, i18n("The user the image below belongs to.") );
+ connect( usercombo, TQT_SIGNAL(activated( int )),
+ TQT_SLOT(slotUserSelected()) );
+ TQLabel *userlabel = new TQLabel( usercombo, i18n("User:"), hlpw );
+ userbutton = new TQPushButton( hlpw );
+ userbutton->setAcceptDrops( true );
+ userbutton->installEventFilter( this ); // for drag and drop
+ uint sz = style().pixelMetric( TQStyle::PM_ButtonMargin ) * 2 + 48;
+ userbutton->setFixedSize( sz, sz );
+ connect( userbutton, TQT_SIGNAL(clicked()),
+ TQT_SLOT(slotUserButtonClicked()) );
+ TQToolTip::add( userbutton, i18n("Click or drop an image here") );
+ TQWhatsThis::add( userbutton, i18n("Here you can see the image assigned to the user selected in the combo box above. Click on the image button to select from a list"
+ " of images or drag and drop your own image on to the button (e.g. from Konqueror).") );
+ rstuserbutton = new TQPushButton( i18n("Unset"), hlpw );
+ TQWhatsThis::add( rstuserbutton, i18n("Click this button to make TDM use the default image for the selected user.") );
+ connect( rstuserbutton, TQT_SIGNAL(clicked()),
+ TQT_SLOT(slotUnsetUserPix()) );
+ TQGridLayout *hlpl = new TQGridLayout( hlpw, 3, 2, 0, KDialog::spacingHint() );
+ hlpl->addWidget( userlabel, 0, 0 );
+// hlpl->addSpacing( KDialog::spacingHint() );
+ hlpl->addWidget( usercombo, 0, 1 );
+ hlpl->addMultiCellWidget( userbutton, 1,1, 0,1, Qt::AlignHCenter );
+ hlpl->addMultiCellWidget( rstuserbutton, 2,2, 0,1, Qt::AlignHCenter );
+
+ TQHBoxLayout *main = new TQHBoxLayout( this, 10 );
+
+ TQVBoxLayout *lLayout = new TQVBoxLayout( main, 10 );
+ lLayout->addWidget( minGroup );
+ lLayout->addWidget( usrGroup );
+ lLayout->addStretch( 1 );
+
+ TQVBoxLayout *mLayout = new TQVBoxLayout( main, 10 );
+ mLayout->addWidget( s_label );
+ mLayout->addWidget( wstack );
+ mLayout->setStretchFactor( wstack, 1 );
+ main->setStretchFactor( mLayout, 1 );
+
+ TQVBoxLayout *rLayout = new TQVBoxLayout( main, 10 );
+ rLayout->addWidget( faceGroup );
+ rLayout->addWidget( picGroup );
+ rLayout->addStretch( 1 );
+
+}
+
+void TDMUsersWidget::makeReadOnly()
+{
+ leminuid->setReadOnly(true);
+ lemaxuid->setReadOnly(true);
+ cbshowlist->setEnabled(false);
+ cbcomplete->setEnabled(false);
+ cbinverted->setEnabled(false);
+ cbusrsrt->setEnabled(false);
+ rbadmonly->setEnabled(false);
+ rbprefadm->setEnabled(false);
+ rbprefusr->setEnabled(false);
+ rbusronly->setEnabled(false);
+ wstack->setEnabled(false);
+ disconnect( userbutton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotUserButtonClicked()) );
+ userbutton->setAcceptDrops(false);
+ rstuserbutton->setEnabled(false);
+}
+
+void TDMUsersWidget::slotShowOpts()
+{
+ bool en = cbshowlist->isChecked() || cbcomplete->isChecked();
+ cbinverted->setEnabled( en );
+ cbusrsrt->setEnabled( en );
+ wstack->setEnabled( en );
+ wstack->raiseWidget( cbinverted->isChecked() ? optoutlv : optinlv );
+ en = cbshowlist->isChecked();
+ faceGroup->setEnabled( en );
+ if (!en) {
+ usercombo->setEnabled( false );
+ userbutton->setEnabled( false );
+ rstuserbutton->setEnabled( false );
+ } else
+ slotFaceOpts();
+}
+
+void TDMUsersWidget::slotFaceOpts()
+{
+ bool en = !rbusronly->isChecked();
+ usercombo->setEnabled( en );
+ userbutton->setEnabled( en );
+ if (en)
+ slotUserSelected();
+ else
+ rstuserbutton->setEnabled( false );
+}
+
+void TDMUsersWidget::slotUserSelected()
+{
+ TQString user = usercombo->currentText();
+ TQImage p;
+ if (user != m_defaultText &&
+ p.load( m_userPixDir + user + ".face.icon" )) {
+ rstuserbutton->setEnabled( !getuid() );
+ } else {
+ p.load( m_userPixDir + ".default.face.icon" );
+ rstuserbutton->setEnabled( false );
+ }
+ userbutton->setPixmap( p.smoothScale( 48, 48, TQ_ScaleMin ) );
+}
+
+
+void TDMUsersWidget::changeUserPix(const TQString &pix)
+{
+ TQString user( usercombo->currentText() );
+ if (user == m_defaultText)
+ {
+ user = ".default";
+ if (KMessageBox::questionYesNo(this, i18n("Save image as default image?"),TQString::null,KStdGuiItem::save(),KStdGuiItem::cancel())
+ != KMessageBox::Yes)
+ return;
+ }
+
+ TQImage p( pix );
+ if (p.isNull()) {
+ KMessageBox::sorry( this,
+ i18n("There was an error loading the image\n"
+ "%1").arg( pix ) );
+ return;
+ }
+
+ p = p.smoothScale( 48, 48, TQ_ScaleMin );
+ TQString userpix = m_userPixDir + user + ".face.icon";
+ if (!p.save( userpix, "PNG" ))
+ KMessageBox::sorry(this,
+ i18n("There was an error saving the image:\n%1")
+ .arg( userpix ) );
+ else
+ chmod( TQFile::encodeName( userpix ), 0644 );
+
+ slotUserSelected();
+}
+
+void TDMUsersWidget::slotUserButtonClicked()
+{
+ KFileDialog dlg(m_notFirst ? TQString::null :
+ KGlobal::dirs()->resourceDirs("data").last() + "tdm/pics/users",
+ KImageIO::pattern( KImageIO::Reading ),
+ this, 0, true);
+ dlg.setOperationMode( KFileDialog::Opening );
+ dlg.setCaption( i18n("Choose Image") );
+ dlg.setMode( KFile::File | KFile::LocalOnly );
+
+ KImageFilePreview *ip = new KImageFilePreview( &dlg );
+ dlg.setPreviewWidget( ip );
+ if (dlg.exec() != TQDialog::Accepted)
+ return;
+ m_notFirst = true;
+
+ changeUserPix( dlg.selectedFile() );
+}
+
+void TDMUsersWidget::slotUnsetUserPix()
+{
+ TQFile::remove( m_userPixDir + usercombo->currentText() + ".face.icon" );
+ slotUserSelected();
+}
+
+bool TDMUsersWidget::eventFilter(TQObject *, TQEvent *e)
+{
+ if (e->type() == TQEvent::DragEnter) {
+ TQDragEnterEvent *ee = (TQDragEnterEvent *) e;
+ ee->accept( KURLDrag::canDecode(ee) );
+ return true;
+ }
+
+ if (e->type() == TQEvent::Drop) {
+ userButtonDropEvent((TQDropEvent *) e);
+ return true;
+ }
+
+ return false;
+}
+
+KURL *decodeImgDrop(TQDropEvent *e, TQWidget *wdg);
+
+void TDMUsersWidget::userButtonDropEvent(TQDropEvent *e)
+{
+ KURL *url = decodeImgDrop(e, this);
+ if (url) {
+ TQString pixpath;
+ KIO::NetAccess::download(*url, pixpath, parentWidget());
+ changeUserPix( pixpath );
+ KIO::NetAccess::removeTempFile(pixpath);
+ delete url;
+ }
+}
+
+void TDMUsersWidget::save()
+{
+ config->setGroup( "X-*-Greeter" );
+
+ config->writeEntry( "MinShowUID", leminuid->text() );
+ config->writeEntry( "MaxShowUID", lemaxuid->text() );
+
+ config->writeEntry( "UserList", cbshowlist->isChecked() );
+ config->writeEntry( "UserCompletion", cbcomplete->isChecked() );
+ config->writeEntry( "ShowUsers",
+ cbinverted->isChecked() ? "NotHidden" : "Selected" );
+ config->writeEntry( "SortUsers", cbusrsrt->isChecked() );
+
+ config->writeEntry( "HiddenUsers", hiddenUsers );
+ config->writeEntry( "SelectedUsers", selectedUsers );
+
+ config->writeEntry( "FaceSource",
+ rbadmonly->isChecked() ? "AdminOnly" :
+ rbprefadm->isChecked() ? "PreferAdmin" :
+ rbprefusr->isChecked() ? "PreferUser" : "UserOnly" );
+}
+
+
+void TDMUsersWidget::updateOptList( TQListViewItem *item, TQStringList &list )
+{
+ if ( !item )
+ return;
+ TQCheckListItem *itm = (TQCheckListItem *)item;
+ TQStringList::iterator it = list.find( itm->text() );
+ if (itm->isOn()) {
+ if (it == list.end())
+ list.append( itm->text() );
+ } else {
+ if (it != list.end())
+ list.remove( it );
+ }
+}
+
+void TDMUsersWidget::slotUpdateOptIn( TQListViewItem *item )
+{
+ updateOptList( item, selectedUsers );
+}
+
+void TDMUsersWidget::slotUpdateOptOut( TQListViewItem *item )
+{
+ updateOptList( item, hiddenUsers );
+}
+
+void TDMUsersWidget::slotClearUsers()
+{
+ optinlv->clear();
+ optoutlv->clear();
+ usercombo->clear();
+ usercombo->insertItem( m_defaultText );
+}
+
+void TDMUsersWidget::slotAddUsers(const TQMap<TQString,int> &users)
+{
+ TQMapConstIterator<TQString,int> it;
+ for (it = users.begin(); it != users.end(); ++it) {
+ const TQString *name = &it.key();
+ (new TQCheckListItem(optinlv, *name, TQCheckListItem::CheckBox))->
+ setOn(selectedUsers.find(*name) != selectedUsers.end());
+ (new TQCheckListItem(optoutlv, *name, TQCheckListItem::CheckBox))->
+ setOn(hiddenUsers.find(*name) != hiddenUsers.end());
+ if ((*name)[0] != '@')
+ usercombo->insertItem(*name);
+ }
+ optinlv->sort();
+ optoutlv->sort();
+ if (usercombo->listBox())
+ usercombo->listBox()->sort();
+}
+
+void TDMUsersWidget::slotDelUsers(const TQMap<TQString,int> &users)
+{
+ TQMapConstIterator<TQString,int> it;
+ for (it = users.begin(); it != users.end(); ++it) {
+ const TQString *name = &it.key();
+ if (usercombo->listBox())
+ delete usercombo->listBox()->findItem( *name, ExactMatch | CaseSensitive );
+ delete optinlv->findItem( *name, 0 );
+ delete optoutlv->findItem( *name, 0 );
+ }
+}
+
+void TDMUsersWidget::load()
+{
+ TQString str;
+
+ config->setGroup("X-*-Greeter");
+
+ selectedUsers = config->readListEntry( "SelectedUsers");
+ hiddenUsers = config->readListEntry( "HiddenUsers");
+
+ leminuid->setText(config->readEntry("MinShowUID", defminuid));
+ lemaxuid->setText(config->readEntry("MaxShowUID", defmaxuid));
+
+ cbshowlist->setChecked( config->readBoolEntry( "UserList", true ) );
+ cbcomplete->setChecked( config->readBoolEntry( "UserCompletion", false ) );
+ cbinverted->setChecked( config->readEntry( "ShowUsers" ) != "Selected" );
+ cbusrsrt->setChecked(config->readBoolEntry("SortUsers", true));
+
+ TQString ps = config->readEntry( "FaceSource" );
+ if (ps == TQString::fromLatin1("UserOnly"))
+ rbusronly->setChecked(true);
+ else if (ps == TQString::fromLatin1("PreferUser"))
+ rbprefusr->setChecked(true);
+ else if (ps == TQString::fromLatin1("PreferAdmin"))
+ rbprefadm->setChecked(true);
+ else
+ rbadmonly->setChecked(true);
+
+ slotUserSelected();
+
+ slotShowOpts();
+ slotFaceOpts();
+}
+
+void TDMUsersWidget::defaults()
+{
+ leminuid->setText( defminuid );
+ lemaxuid->setText( defmaxuid );
+ cbshowlist->setChecked( true );
+ cbcomplete->setChecked( false );
+ cbinverted->setChecked( true );
+ cbusrsrt->setChecked( true );
+ rbadmonly->setChecked( true );
+ hiddenUsers.clear();
+ selectedUsers.clear();
+ slotShowOpts();
+ slotFaceOpts();
+}
+
+void TDMUsersWidget::slotMinMaxChanged()
+{
+ emit setMinMaxUID( leminuid->text().toInt(), lemaxuid->text().toInt() );
+}
+
+void TDMUsersWidget::slotChanged()
+{
+ emit changed(true);
+}
+
+#include "tdm-users.moc"