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
)
66 KUrl::List uriList
= KUrl::List::fromMimeData( e
->mimeData() );
67 if (!uriList
.isEmpty()) {
68 KUrl
*url
= new KUrl( uriList
.first() );
70 KMimeType::Ptr mime
= KMimeType::findByUrl( *url
);
71 if (mime
&& KImageIO::isSupported( mime
->name(), KImageIO::Reading
))
74 QStringList qs
= KImageIO::pattern().split( '\n' );
77 QString msg
= i18n( "%1 "
78 "does not appear to be an image file.\n"
79 "Please use files with these extensions:\n"
83 KMessageBox::sorry( wdg
, msg
);
91 KDModule::KDModule( QWidget
*parent
, const QVariantList
& )
92 : KCModule( KDMFactory::componentData(), parent
)
98 new KAboutData( "kcmkdm", "kdmconfig", ki18n("KDE Login Manager Config Module"),
99 QByteArray(), KLocalizedString(), KAboutData::License_GPL
,
100 ki18n("(c) 1996-2008 The KDM Authors"), KLocalizedString(),
101 "http://developer.kde.org/~ossi/sw/kdm.html" );
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" );
109 "<h1>Login Manager</h1> In this module you can configure the "
110 "various aspects of the KDE Login Manager. This includes "
111 "the look and feel as well as the users that can be "
112 "selected for login. Note that you can only make changes "
113 "if you run the module with superuser rights. If you have not started the KDE "
114 "Control Center with superuser rights (which is absolutely the right thing to "
115 "do, by the way), click on the <em>Modify</em> button to acquire "
116 "superuser rights. You will be asked for the superuser password."
117 "<h2>General</h2> On this tab page, you can configure parts of "
118 "the Login Manager's look, and which language it should use. "
119 "The language settings made here have no influence on "
120 "the user's language settings."
121 "<h2>Dialog</h2>Here you can configure the look of the \"classical\" "
122 "dialog based mode if you have chosen to use it. "
123 "<h2>Background</h2>If you want to set a special background for the dialog based "
124 "login screen, this is where to do it."
125 "<h2>Themes</h2> Here you can specify a theme to be used by the Login Manager."
126 "<h2>Shutdown</h2> Here you can specify who is allowed to shutdown/reboot the machine "
127 "and whether a boot manager should be used."
128 "<h2>Users</h2>On this tab page, you can select which users the Login Manager "
129 "will offer you for logging in."
130 "<h2>Convenience</h2> Here you can specify a user to be logged in automatically, "
131 "users not needing to provide a password to log in, and other convenience features.<br/>"
132 "Note, that these settings are security holes by their nature, so use them very carefully.") );
134 setAboutData( about
);
136 setlocale( LC_COLLATE
, "C" );
138 KGlobal::locale()->insertCatalog( "kcmbackground" );
141 QMap
<gid_t
,QStringList
> tgmap
;
142 QMap
<gid_t
,QStringList
>::Iterator tgmapi
;
143 QMap
<gid_t
,QStringList
>::ConstIterator tgmapci
;
144 QMap
<QString
, QPair
<int,QStringList
> >::Iterator umapi
;
147 for (setpwent(); (ps
= getpwent()); ) {
148 QString
un( QFile::decodeName( ps
->pw_name
) );
149 if (usermap
.find( un
) == usermap
.end()) {
150 usermap
.insert( un
, QPair
<int,QStringList
>( ps
->pw_uid
, sl
) );
151 if ((tgmapi
= tgmap
.find( ps
->pw_gid
)) != tgmap
.end())
152 (*tgmapi
).append( un
);
154 tgmap
[ps
->pw_gid
] = QStringList(un
);
160 for (setgrent(); (grp
= getgrent()); ) {
161 QString
gn( QFile::decodeName( grp
->gr_name
) );
163 if ((tgmapi
= tgmap
.find( grp
->gr_gid
)) != tgmap
.end()) {
164 if ((*tgmapi
).count() == 1 && (*tgmapi
).first() == gn
)
167 for (QStringList::ConstIterator it
= (*tgmapi
).constBegin();
168 it
!= (*tgmapi
).constEnd(); ++it
)
169 usermap
[*it
].second
.append( gn
);
170 tgmap
.erase( tgmapi
);
173 (delme
&& !grp
->gr_mem
[1] && gn
== QFile::decodeName( *grp
->gr_mem
)))
176 QString
un( QFile::decodeName( *grp
->gr_mem
) );
177 if ((umapi
= usermap
.find( un
)) != usermap
.end()) {
178 if (!(*umapi
).second
.contains( gn
))
179 (*umapi
).second
.append( gn
);
181 kWarning() << "group '" << gn
<< "' contains unknown user '" << un
<< "'" ;
182 } while (*++grp
->gr_mem
);
186 for (tgmapci
= tgmap
.constBegin(); tgmapci
!= tgmap
.constEnd(); ++tgmapci
)
187 kWarning() << "user(s) '" << tgmapci
.value().join( "," )
188 << "' have unknown GID " << tgmapci
.key() << endl
;
190 config
= new KConfig( QString::fromLatin1(KDE_CONFDIR
"/kdm/kdmrc"), KConfig::SimpleConfig
);
192 QVBoxLayout
*top
= new QVBoxLayout( this );
194 tab
= new QTabWidget( this );
196 general
= new KDMGeneralWidget( this );
197 tab
->addTab( general
, i18n("General (&1)") );
198 connect( general
, SIGNAL(changed()), SLOT(changed()) );
199 connect( general
, SIGNAL(useThemeChanged( bool )),
200 SLOT(slotUseThemeChanged( bool )) );
202 dialog_stack
= new QStackedWidget( this );
203 tab
->addTab( dialog_stack
, i18n("Dialog (&2)") );
204 dialog
= new KDMDialogWidget( dialog_stack
);
205 dialog_stack
->addWidget( dialog
);
206 connect( dialog
, SIGNAL(changed()), SLOT(changed()) );
207 QLabel
*lbl
= new QLabel(
208 i18n("There is no login dialog window in themed mode."),
210 lbl
->setAlignment( Qt::AlignCenter
);
211 dialog_stack
->addWidget( lbl
);
213 background_stack
= new QStackedWidget( this );
214 tab
->addTab( background_stack
, i18n("Background (&3)") );
215 background
= new KBackground( background_stack
);
216 background_stack
->addWidget( background
);
217 connect( background
, SIGNAL(changed()), SLOT(changed()) );
219 i18n("The background cannot be configured separately in themed mode."),
221 lbl
->setAlignment( Qt::AlignCenter
);
222 background_stack
->addWidget( lbl
);
224 theme_stack
= new QStackedWidget( this );
225 tab
->addTab( theme_stack
, i18n("Theme (&4)") );
227 i18n("Themed mode is disabled. See \"General\" tab."),
229 lbl
->setAlignment( Qt::AlignCenter
);
230 theme_stack
->addWidget( lbl
);
231 theme
= new KDMThemeWidget( theme_stack
);
232 theme_stack
->addWidget( theme
);
233 connect( theme
, SIGNAL(changed()), SLOT(changed()) );
235 sessions
= new KDMSessionsWidget( this );
236 tab
->addTab( sessions
, i18n("Shutdown (&5)") );
237 connect( sessions
, SIGNAL(changed()), SLOT(changed()) );
239 users
= new KDMUsersWidget( this );
240 tab
->addTab( users
, i18n("Users (&6)") );
241 connect( users
, SIGNAL(changed()), SLOT(changed()) );
242 connect( users
, SIGNAL(setMinMaxUID( int,int )), SLOT(slotMinMaxUID( int,int )) );
243 connect( this, SIGNAL(addUsers( const QMap
<QString
,int> & )),
244 users
, SLOT(slotAddUsers( const QMap
<QString
,int> & )) );
245 connect( this, SIGNAL(delUsers( const QMap
<QString
,int> & )),
246 users
, SLOT(slotDelUsers( const QMap
<QString
,int> & )) );
247 connect( this, SIGNAL(clearUsers()), users
, SLOT(slotClearUsers()) );
249 convenience
= new KDMConvenienceWidget( this );
250 tab
->addTab( convenience
, i18n("Convenience (&7)") );
251 connect( convenience
, SIGNAL(changed()), SLOT(changed()) );
252 connect( this, SIGNAL(addUsers( const QMap
<QString
,int> & )),
253 convenience
, SLOT(slotAddUsers( const QMap
<QString
,int> & )) );
254 connect( this, SIGNAL(delUsers( const QMap
<QString
,int> & )),
255 convenience
, SLOT(slotDelUsers( const QMap
<QString
,int> & )) );
256 connect( this, SIGNAL(clearUsers()), convenience
, SLOT(slotClearUsers()) );
258 if (getuid() != 0 || !config
->isConfigWritable( true )) {
259 general
->makeReadOnly();
260 dialog
->makeReadOnly();
261 background
->makeReadOnly();
262 theme
->makeReadOnly();
263 users
->makeReadOnly();
264 sessions
->makeReadOnly();
265 convenience
->makeReadOnly();
267 top
->addWidget( tab
);
270 KDModule::~KDModule()
275 void KDModule::load()
286 emit
changed( false );
290 void KDModule::save()
301 emit
changed( false );
305 void KDModule::defaults()
310 background
->defaults();
313 sessions
->defaults();
314 convenience
->defaults();
319 void KDModule::propagateUsers()
323 QMap
<QString
,int> lusers
;
324 QMap
<QString
, QPair
<int,QStringList
> >::const_iterator it
;
325 QStringList::ConstIterator jt
;
326 QMap
<QString
,int>::Iterator gmapi
;
327 for (it
= usermap
.constBegin(); it
!= usermap
.constEnd(); ++it
) {
328 int uid
= it
.value().first
;
329 if (!uid
|| (uid
>= minshowuid
&& uid
<= maxshowuid
)) {
330 lusers
[it
.key()] = uid
;
331 for (jt
= it
.value().second
.begin(); jt
!= it
.value().second
.end(); ++jt
)
332 if ((gmapi
= groupmap
.find( *jt
)) == groupmap
.end()) {
334 lusers
['@' + *jt
] = -uid
;
339 emit
addUsers( lusers
);
343 void KDModule::slotMinMaxUID( int min
, int max
)
346 QMap
<QString
,int> alusers
, dlusers
;
347 QMap
<QString
, QPair
<int,QStringList
> >::const_iterator it
;
348 QStringList::ConstIterator jt
;
349 QMap
<QString
,int>::Iterator gmapi
;
350 for (it
= usermap
.constBegin(); it
!= usermap
.constEnd(); ++it
) {
351 int uid
= it
.value().first
;
354 if ((uid
>= minshowuid
&& uid
<= maxshowuid
) &&
355 !(uid
>= min
&& uid
<= max
))
357 dlusers
[it
.key()] = uid
;
358 for (jt
= it
.value().second
.begin();
359 jt
!= it
.value().second
.end(); ++jt
) {
360 gmapi
= groupmap
.find( *jt
);
362 groupmap
.erase( gmapi
);
363 dlusers
['@' + *jt
] = -uid
;
366 } else if ((uid
>= min
&& uid
<= max
) &&
367 !(uid
>= minshowuid
&& uid
<= maxshowuid
))
369 alusers
[it
.key()] = uid
;
370 for (jt
= it
.value().second
.begin();
371 jt
!= it
.value().second
.end(); ++jt
)
372 if ((gmapi
= groupmap
.find( *jt
)) == groupmap
.end()) {
374 alusers
['@' + *jt
] = -uid
;
379 emit
delUsers( dlusers
);
380 emit
addUsers( alusers
);
386 void KDModule::slotUseThemeChanged( bool use
)
388 dialog_stack
->setCurrentIndex( use
);
389 background_stack
->setCurrentIndex( use
);
390 theme_stack
->setCurrentIndex( use
);