4 * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
6 * Requires the Qt widget libraries, available at no cost at
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.
26 #include <config-workspace.h>
28 #include "background.h"
31 #include "kdm-users.h"
34 #include "kdm-theme.h"
36 #include <k3urldrag.h>
37 #include <kaboutdata.h>
40 #include <kmessagebox.h>
42 #include <kmimetype.h>
44 #include <kpluginfactory.h>
45 #include <kpluginloader.h>
50 #include <QStackedWidget>
52 #include <QVBoxLayout>
54 #include <sys/types.h>
61 K_PLUGIN_FACTORY(KDMFactory
, registerPlugin
<KDModule
>();)
62 K_EXPORT_PLUGIN(KDMFactory( "kdmconfig" ))
64 KUrl
*decodeImgDrop( QDropEvent
*e
, QWidget
*wdg
)
68 if (K3URLDrag::decode( e
, uris
) && (uris
.count() > 0)) {
69 KUrl
*url
= new KUrl( uris
.first() );
71 KMimeType::Ptr mime
= KMimeType::findByUrl( *url
);
72 if (mime
&& KImageIO::isSupported( mime
->name(), KImageIO::Reading
))
75 QStringList qs
= KImageIO::pattern().split( '\n' );
76 qs
.erase( qs
.begin() );
78 QString msg
= i18n( "%1 "
79 "does not appear to be an image file.\n"
80 "Please use files with these extensions:\n"
84 KMessageBox::sorry( wdg
, msg
);
92 KDModule::KDModule( QWidget
*parent
, const QVariantList
& )
93 : KCModule( KDMFactory::componentData(), parent
)
99 new KAboutData( I18N_NOOP( "kcmkdm" ), 0, ki18n( "KDE Login Manager Config Module" ),
100 0, KLocalizedString(), KAboutData::License_GPL
,
101 ki18n( "(c) 1996 - 2006 The KDM Authors" ) );
103 about
->addAuthor( ki18n("Thomas Tanghus"), ki18n( "Original author" ), "tanghus@earthling.net" );
104 about
->addAuthor( ki18n("Steffen Hansen"), KLocalizedString(), "hansen@kde.org" );
105 about
->addAuthor( ki18n("Oswald Buddenhagen"), ki18n( "Current maintainer" ), "ossi@kde.org" );
106 about
->addAuthor( ki18n("Stephen Leaf"), KLocalizedString(), "smileaf@smileaf.org" );
108 setQuickHelp( i18n( "<h1>Login Manager</h1> In this module you can configure the "
109 "various aspects of the KDE Login Manager. This includes "
110 "the look and feel as well as the users that can be "
111 "selected for login. Note that you can only make changes "
112 "if you run the module with superuser rights. If you have not started the KDE "
113 "Control Center with superuser rights (which is absolutely the right thing to "
114 "do, by the way), click on the <em>Modify</em> button to acquire "
115 "superuser rights. You will be asked for the superuser password."
116 "<h2>General</h2> On this tab page, you can configure parts of "
117 "the Login Manager's look, and which language it should use. "
118 "The language settings made here have no influence on "
119 "the user's language settings."
120 "<h2>Dialog</h2>Here you can configure the look of the \"classical\" "
121 "dialog based mode if you have chosen to use it. "
122 "<h2>Background</h2>If you want to set a special background for the dialog based "
123 "login screen, this is where to do it."
124 "<h2>Themes</h2> Here you can specify a theme to be used by the Login Manager."
125 "<h2>Shutdown</h2> Here you can specify who is allowed to shutdown/reboot the machine "
126 "and whether a boot manager should be used."
127 "<h2>Users</h2>On this tab page, you can select which users the Login Manager "
128 "will offer you for logging in."
129 "<h2>Convenience</h2> Here you can specify a user to be logged in automatically, "
130 "users not needing to provide a password to log in, and other convenience features.<br/>"
131 "Note, that these settings are security holes by their nature, so use them very carefully.") );
133 setAboutData( about
);
135 setlocale( LC_COLLATE
, "C" );
137 KGlobal::locale()->insertCatalog( "kcmbackground" );
140 QMap
<gid_t
,QStringList
> tgmap
;
141 QMap
<gid_t
,QStringList
>::Iterator tgmapi
;
142 QMap
<gid_t
,QStringList
>::ConstIterator tgmapci
;
143 QMap
<QString
, QPair
<int,QStringList
> >::Iterator umapi
;
146 for (setpwent(); (ps
= getpwent()); ) {
147 QString
un( QFile::decodeName( ps
->pw_name
) );
148 if (usermap
.find( un
) == usermap
.end()) {
149 usermap
.insert( un
, QPair
<int,QStringList
>( ps
->pw_uid
, sl
) );
150 if ((tgmapi
= tgmap
.find( ps
->pw_gid
)) != tgmap
.end())
151 (*tgmapi
).append( un
);
153 tgmap
[ps
->pw_gid
] = QStringList(un
);
159 for (setgrent(); (grp
= getgrent()); ) {
160 QString
gn( QFile::decodeName( grp
->gr_name
) );
162 if ((tgmapi
= tgmap
.find( grp
->gr_gid
)) != tgmap
.end()) {
163 if ((*tgmapi
).count() == 1 && (*tgmapi
).first() == gn
)
166 for (QStringList::ConstIterator it
= (*tgmapi
).begin();
167 it
!= (*tgmapi
).end(); ++it
)
168 usermap
[*it
].second
.append( gn
);
169 tgmap
.erase( tgmapi
);
172 (delme
&& !grp
->gr_mem
[1] && gn
== QFile::decodeName( *grp
->gr_mem
)))
175 QString
un( QFile::decodeName( *grp
->gr_mem
) );
176 if ((umapi
= usermap
.find( un
)) != usermap
.end()) {
177 if (!(*umapi
).second
.contains( gn
))
178 (*umapi
).second
.append( gn
);
180 kWarning() << "group '" << gn
<< "' contains unknown user '" << un
<< "'" ;
181 } while (*++grp
->gr_mem
);
185 for (tgmapci
= tgmap
.begin(); tgmapci
!= tgmap
.end(); ++tgmapci
)
186 kWarning() << "user(s) '" << tgmapci
.value().join( "," )
187 << "' have unknown GID " << tgmapci
.key() << endl
;
189 config
= new KConfig( QString::fromLatin1(KDE_CONFDIR
"/kdm/kdmrc"), KConfig::SimpleConfig
);
191 QVBoxLayout
*top
= new QVBoxLayout( this );
193 tab
= new QTabWidget( this );
195 general
= new KDMGeneralWidget( this );
196 tab
->addTab( general
, i18n("General (&1)") );
197 connect( general
, SIGNAL(changed()), SLOT(changed()) );
198 connect( general
, SIGNAL(useThemeChanged( bool )),
199 SLOT(slotUseThemeChanged( bool )) );
201 dialog_stack
= new QStackedWidget( this );
202 tab
->addTab( dialog_stack
, i18n("Dialog (&2)") );
203 dialog
= new KDMDialogWidget( dialog_stack
);
204 dialog_stack
->addWidget( dialog
);
205 connect( dialog
, SIGNAL(changed()), SLOT(changed()) );
206 QLabel
*lbl
= new QLabel(
207 i18n("There is no login dialog window in themed mode."),
209 lbl
->setAlignment( Qt::AlignCenter
);
210 dialog_stack
->addWidget( lbl
);
212 background_stack
= new QStackedWidget( this );
213 tab
->addTab( background_stack
, i18n("Background (&3)") );
214 background
= new KBackground( background_stack
);
215 background_stack
->addWidget( background
);
216 connect( background
, SIGNAL(changed()), SLOT(changed()) );
218 i18n("The background cannot be configured separately in themed mode."),
220 lbl
->setAlignment( Qt::AlignCenter
);
221 background_stack
->addWidget( lbl
);
223 theme_stack
= new QStackedWidget( this );
224 tab
->addTab( theme_stack
, i18n("Theme (&4)") );
226 i18n("Themed mode is disabled. See \"General\" tab."),
228 lbl
->setAlignment( Qt::AlignCenter
);
229 theme_stack
->addWidget( lbl
);
230 theme
= new KDMThemeWidget( theme_stack
);
231 theme_stack
->addWidget( theme
);
232 connect( theme
, SIGNAL(changed()), SLOT(changed()) );
234 sessions
= new KDMSessionsWidget( this );
235 tab
->addTab( sessions
, i18n("Shutdown (&5)") );
236 connect( sessions
, SIGNAL(changed()), SLOT(changed()) );
238 users
= new KDMUsersWidget( this );
239 tab
->addTab( users
, i18n("Users (&6)") );
240 connect( users
, SIGNAL(changed()), SLOT(changed()) );
241 connect( users
, SIGNAL(setMinMaxUID( int,int )), SLOT(slotMinMaxUID( int,int )) );
242 connect( this, SIGNAL(addUsers( const QMap
<QString
,int> & )), users
, SLOT(slotAddUsers( const QMap
<QString
,int> & )) );
243 connect( this, SIGNAL(delUsers( const QMap
<QString
,int> & )), users
, SLOT(slotDelUsers( const QMap
<QString
,int> & )) );
244 connect( this, SIGNAL(clearUsers()), users
, SLOT(slotClearUsers()) );
246 convenience
= new KDMConvenienceWidget( this );
247 tab
->addTab( convenience
, i18n("Convenience (&7)") );
248 connect( convenience
, SIGNAL(changed()), SLOT(changed()) );
249 connect( this, SIGNAL(addUsers( const QMap
<QString
,int> & )), convenience
, SLOT(slotAddUsers( const QMap
<QString
,int> & )) );
250 connect( this, SIGNAL(delUsers( const QMap
<QString
,int> & )), convenience
, SLOT(slotDelUsers( const QMap
<QString
,int> & )) );
251 connect( this, SIGNAL(clearUsers()), convenience
, SLOT(slotClearUsers()) );
254 if (getuid() != 0 || !config
->isConfigWritable( true )) {
255 general
->makeReadOnly();
256 dialog
->makeReadOnly();
257 background
->makeReadOnly();
258 theme
->makeReadOnly();
259 users
->makeReadOnly();
260 sessions
->makeReadOnly();
261 convenience
->makeReadOnly();
263 top
->addWidget( tab
);
266 KDModule::~KDModule()
271 void KDModule::load()
284 void KDModule::save()
297 void KDModule::defaults()
302 background
->defaults();
305 sessions
->defaults();
306 convenience
->defaults();
311 void KDModule::propagateUsers()
315 QMap
<QString
,int> lusers
;
316 QMap
<QString
, QPair
<int,QStringList
> >::const_iterator it
;
317 QStringList::ConstIterator jt
;
318 QMap
<QString
,int>::Iterator gmapi
;
319 for (it
= usermap
.begin(); it
!= usermap
.end(); ++it
) {
320 int uid
= it
.value().first
;
321 if (!uid
|| (uid
>= minshowuid
&& uid
<= maxshowuid
)) {
322 lusers
[it
.key()] = uid
;
323 for (jt
= it
.value().second
.begin(); jt
!= it
.value().second
.end(); ++jt
)
324 if ((gmapi
= groupmap
.find( *jt
)) == groupmap
.end()) {
326 lusers
['@' + *jt
] = -uid
;
331 emit
addUsers( lusers
);
335 void KDModule::slotMinMaxUID( int min
, int max
)
338 QMap
<QString
,int> alusers
, dlusers
;
339 QMap
<QString
, QPair
<int,QStringList
> >::const_iterator it
;
340 QStringList::ConstIterator jt
;
341 QMap
<QString
,int>::Iterator gmapi
;
342 for (it
= usermap
.begin(); it
!= usermap
.end(); ++it
) {
343 int uid
= it
.value().first
;
346 if ((uid
>= minshowuid
&& uid
<= maxshowuid
) &&
347 !(uid
>= min
&& uid
<= max
))
349 dlusers
[it
.key()] = uid
;
350 for (jt
= it
.value().second
.begin();
351 jt
!= it
.value().second
.end(); ++jt
) {
352 gmapi
= groupmap
.find( *jt
);
354 groupmap
.erase( gmapi
);
355 dlusers
['@' + *jt
] = -uid
;
358 } else if ((uid
>= min
&& uid
<= max
) &&
359 !(uid
>= minshowuid
&& uid
<= maxshowuid
))
361 alusers
[it
.key()] = uid
;
362 for (jt
= it
.value().second
.begin();
363 jt
!= it
.value().second
.end(); ++jt
)
364 if ((gmapi
= groupmap
.find( *jt
)) == groupmap
.end()) {
366 alusers
['@' + *jt
] = -uid
;
371 emit
delUsers( dlusers
);
372 emit
addUsers( alusers
);
378 void KDModule::slotUseThemeChanged( bool use
)
380 dialog_stack
->setCurrentIndex( use
);
381 background_stack
->setCurrentIndex( use
);
382 theme_stack
->setCurrentIndex( use
);