not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / kdm / main.cpp
blob9c677b04428e0974efb68d824578a97278c9c6fd
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 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 ))
72 return url;
74 QStringList qs = KImageIO::pattern().split( '\n' );
75 qs.removeFirst();
77 QString msg = i18n( "%1 "
78 "does not appear to be an image file.\n"
79 "Please use files with these extensions:\n"
80 "%2",
81 url->fileName(),
82 qs.join( "\n" ));
83 KMessageBox::sorry( wdg, msg );
84 delete url;
86 return 0;
89 KConfig *config;
91 KDModule::KDModule( QWidget *parent, const QVariantList & )
92 : KCModule( KDMFactory::componentData(), parent )
93 , minshowuid( 0 )
94 , maxshowuid( 0 )
95 , updateOK( false )
97 KAboutData *about =
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" );
108 setQuickHelp( i18n(
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" );
140 QStringList sl;
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;
146 struct passwd *ps;
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 );
153 else
154 tgmap[ps->pw_gid] = QStringList(un);
157 endpwent();
159 struct group *grp;
160 for (setgrent(); (grp = getgrent()); ) {
161 QString gn( QFile::decodeName( grp->gr_name ) );
162 bool delme = false;
163 if ((tgmapi = tgmap.find( grp->gr_gid )) != tgmap.end()) {
164 if ((*tgmapi).count() == 1 && (*tgmapi).first() == gn)
165 delme = true;
166 else
167 for (QStringList::ConstIterator it = (*tgmapi).constBegin();
168 it != (*tgmapi).constEnd(); ++it)
169 usermap[*it].second.append( gn );
170 tgmap.erase( tgmapi );
172 if (!*grp->gr_mem ||
173 (delme && !grp->gr_mem[1] && gn == QFile::decodeName( *grp->gr_mem )))
174 continue;
175 do {
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 );
180 } else
181 kWarning() << "group '" << gn << "' contains unknown user '" << un << "'" ;
182 } while (*++grp->gr_mem);
184 endgrent();
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 );
193 top->setMargin( 0 );
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."),
209 dialog_stack );
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()) );
218 lbl = new QLabel(
219 i18n("The background cannot be configured separately in themed mode."),
220 background_stack );
221 lbl->setAlignment( Qt::AlignCenter );
222 background_stack->addWidget( lbl );
224 theme_stack = new QStackedWidget( this );
225 tab->addTab( theme_stack, i18n("Theme (&4)") );
226 lbl = new QLabel(
227 i18n("Themed mode is disabled. See \"General\" tab."),
228 theme_stack );
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()
272 delete config;
275 void KDModule::load()
277 general->load();
278 dialog->load();
279 background->load();
280 theme->load();
281 users->load();
282 sessions->load();
283 convenience->load();
284 propagateUsers();
286 emit changed( false );
290 void KDModule::save()
292 general->save();
293 dialog->save();
294 background->save();
295 theme->save();
296 users->save();
297 sessions->save();
298 convenience->save();
299 config->sync();
301 emit changed( false );
305 void KDModule::defaults()
307 if (getuid() == 0) {
308 general->defaults();
309 dialog->defaults();
310 background->defaults();
311 theme->defaults();
312 users->defaults();
313 sessions->defaults();
314 convenience->defaults();
315 propagateUsers();
319 void KDModule::propagateUsers()
321 groupmap.clear();
322 emit clearUsers();
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()) {
333 groupmap[*jt] = 1;
334 lusers['@' + *jt] = -uid;
335 } else
336 (*gmapi)++;
339 emit addUsers( lusers );
340 updateOK = true;
343 void KDModule::slotMinMaxUID( int min, int max )
345 if (updateOK) {
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;
352 if (!uid)
353 continue;
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 );
361 if (!--(*gmapi)) {
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()) {
373 groupmap[*jt] = 1;
374 alusers['@' + *jt] = -uid;
375 } else
376 (*gmapi)++;
379 emit delUsers( dlusers );
380 emit addUsers( alusers );
382 minshowuid = min;
383 maxshowuid = max;
386 void KDModule::slotUseThemeChanged( bool use )
388 dialog_stack->setCurrentIndex( use );
389 background_stack->setCurrentIndex( use );
390 theme_stack->setCurrentIndex( use );
393 #include "main.moc"