Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kcontrol / kdm / main.cpp
blobdb240fc1f3f99bdfa47fa0510cffefd99bbae7ff
1 /*
2 * main.cpp
4 * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
6 * Requires the Qt widget libraries, available at no cost at
7 * http://www.troll.no/
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.
24 #include "main.h"
26 #include <config-workspace.h>
28 #include "background.h"
29 #include "kdm-gen.h"
30 #include "kdm-dlg.h"
31 #include "kdm-users.h"
32 #include "kdm-shut.h"
33 #include "kdm-conv.h"
34 #include "kdm-theme.h"
36 #include <k3urldrag.h>
37 #include <kaboutdata.h>
38 #include <kimageio.h>
39 #include <klocale.h>
40 #include <kmessagebox.h>
41 #include <kdebug.h>
42 #include <kmimetype.h>
43 #include <kconfig.h>
44 #include <kpluginfactory.h>
45 #include <kpluginloader.h>
47 #include <QDropEvent>
48 #include <QFile>
49 #include <QLabel>
50 #include <QStackedWidget>
51 #include <QTabWidget>
52 #include <QVBoxLayout>
54 #include <sys/types.h>
55 #include <unistd.h>
56 #include <locale.h>
57 #include <pwd.h>
58 #include <grp.h>
61 K_PLUGIN_FACTORY(KDMFactory, registerPlugin<KDModule>();)
62 K_EXPORT_PLUGIN(KDMFactory( "kdmconfig" ))
64 KUrl *decodeImgDrop( QDropEvent *e, QWidget *wdg )
66 KUrl::List uris;
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 ))
73 return url;
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"
81 "%2",
82 url->fileName(),
83 qs.join( "\n" ));
84 KMessageBox::sorry( wdg, msg );
85 delete url;
87 return 0;
90 KConfig *config;
92 KDModule::KDModule( QWidget *parent, const QVariantList & )
93 : KCModule( KDMFactory::componentData(), parent )
94 , minshowuid( 0 )
95 , maxshowuid( 0 )
96 , updateOK( false )
98 KAboutData *about =
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" );
139 QStringList sl;
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;
145 struct passwd *ps;
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 );
152 else
153 tgmap[ps->pw_gid] = QStringList(un);
156 endpwent();
158 struct group *grp;
159 for (setgrent(); (grp = getgrent()); ) {
160 QString gn( QFile::decodeName( grp->gr_name ) );
161 bool delme = false;
162 if ((tgmapi = tgmap.find( grp->gr_gid )) != tgmap.end()) {
163 if ((*tgmapi).count() == 1 && (*tgmapi).first() == gn)
164 delme = true;
165 else
166 for (QStringList::ConstIterator it = (*tgmapi).begin();
167 it != (*tgmapi).end(); ++it)
168 usermap[*it].second.append( gn );
169 tgmap.erase( tgmapi );
171 if (!*grp->gr_mem ||
172 (delme && !grp->gr_mem[1] && gn == QFile::decodeName( *grp->gr_mem )))
173 continue;
174 do {
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 );
179 } else
180 kWarning() << "group '" << gn << "' contains unknown user '" << un << "'" ;
181 } while (*++grp->gr_mem);
183 endgrent();
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 );
192 top->setMargin(0);
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."),
208 dialog_stack );
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()) );
217 lbl = new QLabel(
218 i18n("The background cannot be configured separately in themed mode."),
219 background_stack );
220 lbl->setAlignment( Qt::AlignCenter );
221 background_stack->addWidget( lbl );
223 theme_stack = new QStackedWidget( this );
224 tab->addTab( theme_stack, i18n("Theme (&4)") );
225 lbl = new QLabel(
226 i18n("Themed mode is disabled. See \"General\" tab."),
227 theme_stack );
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()) );
253 load();
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()
268 delete config;
271 void KDModule::load()
273 general->load();
274 dialog->load();
275 background->load();
276 theme->load();
277 users->load();
278 sessions->load();
279 convenience->load();
280 propagateUsers();
284 void KDModule::save()
286 general->save();
287 dialog->save();
288 background->save();
289 theme->save();
290 users->save();
291 sessions->save();
292 convenience->save();
293 config->sync();
297 void KDModule::defaults()
299 if (getuid() == 0) {
300 general->defaults();
301 dialog->defaults();
302 background->defaults();
303 theme->defaults();
304 users->defaults();
305 sessions->defaults();
306 convenience->defaults();
307 propagateUsers();
311 void KDModule::propagateUsers()
313 groupmap.clear();
314 emit clearUsers();
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()) {
325 groupmap[*jt] = 1;
326 lusers['@' + *jt] = -uid;
327 } else
328 (*gmapi)++;
331 emit addUsers( lusers );
332 updateOK = true;
335 void KDModule::slotMinMaxUID( int min, int max )
337 if (updateOK) {
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;
344 if (!uid)
345 continue;
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 );
353 if (!--(*gmapi)) {
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()) {
365 groupmap[*jt] = 1;
366 alusers['@' + *jt] = -uid;
367 } else
368 (*gmapi)++;
371 emit delUsers( dlusers );
372 emit addUsers( alusers );
374 minshowuid = min;
375 maxshowuid = max;
378 void KDModule::slotUseThemeChanged( bool use )
380 dialog_stack->setCurrentIndex( use );
381 background_stack->setCurrentIndex( use );
382 theme_stack->setCurrentIndex( use );
385 #include "main.moc"