1/*
2
3Shutdown dialog
4
5Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
6Copyright (C) 2000-2003,2005 Oswald Buddenhagen <ossi@kde.org>
7
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23*/
24
25#include "kdmshutdown.h"
26#include "kdm_greet.h"
27#include "utils.h"
28
29#include <kdialog.h>
30#include <klocale.h>
31#include <kprocess.h>
32#include <kseparator.h>
33#include <kstandarddirs.h>
34#include <KStandardGuiItem>
35#include <kuser.h>
36
37#include <QAction>
38#include <QApplication>
39#include <QCheckBox>
40#include <QComboBox>
41#include <QDateTime>
42#include <QFrame>
43#include <QGroupBox>
44#include <QHeaderView>
45#include <QLabel>
46#include <QLineEdit>
47#include <QMenu>
48#include <QStylePainter>
49#include <QStyle>
50#include <QTreeWidget>
51#include <QTreeWidgetItem>
52
53#include <stdlib.h>
54
55int KDMShutdownBase::curPlugin = -1;
56PluginList KDMShutdownBase::pluginList;
57
58KDMShutdownBase::KDMShutdownBase(int _uid, QWidget *_parent)
59 : inherited(_parent)
60 , box(new QVBoxLayout(this))
61#ifdef HAVE_VTS
62 , willShut(true)
63#endif
64 , mayNuke(false)
65 , doesNuke(false)
66 , mayOk(true)
67 , maySched(false)
68 , rootlab(0)
69 , verify(0)
70 , needRoot(-1)
71 , uid(_uid)
72{
73}
74
75KDMShutdownBase::~KDMShutdownBase()
76{
77 hide();
78 delete verify;
79}
80
81void
82KDMShutdownBase::complete(QWidget *prevWidget)
83{
84 QSizePolicy fp(QSizePolicy::Fixed, QSizePolicy::Fixed);
85
86 if (uid &&
87 ((willShut && _allowShutdown == SHUT_ROOT) ||
88 (mayNuke && _allowNuke == SHUT_ROOT)))
89 {
90 rootlab = new QLabel(i18n("Root authorization required."), this);
91 box->addWidget(rootlab);
92 if (curPlugin < 0) {
93 curPlugin = 0;
94 pluginList = KGVerify::init(_pluginsShutdown);
95 }
96 verify = new KGStdVerify(this, this,
97 prevWidget, "root",
98 pluginList, KGreeterPlugin::Authenticate,
99 KGreeterPlugin::Shutdown);
100 verify->selectPlugin(curPlugin);
101 box->addLayout(verify->getLayout());
102 QAction *action = new QAction(this);
103 action->setShortcut(Qt::ALT + Qt::Key_A);
104 connect(action, SIGNAL(triggered(bool)), SLOT(slotActivatePlugMenu()));
105 }
106
107 box->addWidget(new KSeparator(Qt::Horizontal, this));
108
109 QBoxLayout *hlay = new QHBoxLayout();
110 box->addLayout(hlay);
111 hlay->addStretch(1);
112 if (mayOk) {
113 okButton = new KPushButton(KStandardGuiItem::ok(), this);
114 okButton->setSizePolicy(fp);
115 okButton->setDefault(true);
116 hlay->addWidget(okButton);
117 hlay->addStretch(1);
118 connect(okButton, SIGNAL(clicked()), SLOT(accept()));
119 }
120 if (maySched) {
121 KPushButton *schedButton =
122 new KPushButton(KGuiItem(i18nc("@action:inmenu verb", "&Schedule...")), this);
123 schedButton->setSizePolicy(fp);
124 hlay->addWidget(schedButton);
125 hlay->addStretch(1);
126 connect(schedButton, SIGNAL(clicked()), SLOT(slotSched()));
127 }
128 cancelButton = new KPushButton(KStandardGuiItem::cancel(), this);
129 cancelButton->setSizePolicy(fp);
130 if (!mayOk)
131 cancelButton->setDefault(true);
132 hlay->addWidget(cancelButton);
133 hlay->addStretch(1);
134 connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));
135
136 updateNeedRoot();
137
138 adjustSize();
139 layout()->activate();
140}
141
142void
143KDMShutdownBase::slotActivatePlugMenu()
144{
145 if (needRoot) {
146 QMenu *cmnu = verify->getPlugMenu();
147 if (!cmnu)
148 return;
149 QSize sh(cmnu->sizeHint() / 2);
150 cmnu->exec(geometry().center() - QPoint(sh.width(), sh.height()));
151 }
152}
153
154void
155KDMShutdownBase::accept()
156{
157 if (needRoot == 1)
158 verify->accept();
159 else
160 accepted();
161}
162
163void
164KDMShutdownBase::slotSched()
165{
166 done(Schedule);
167}
168
169void
170KDMShutdownBase::updateNeedRoot()
171{
172 int nNeedRoot = uid &&
173 (((willShut && _allowShutdown == SHUT_ROOT) ||
174 (_allowNuke == SHUT_ROOT && doesNuke)));
175 if (verify && nNeedRoot != needRoot) {
176 if (needRoot == 1)
177 verify->abort();
178 needRoot = nNeedRoot;
179 rootlab->setEnabled(needRoot);
180 verify->setEnabled(needRoot);
181 if (needRoot)
182 verify->start();
183 }
184}
185
186void
187KDMShutdownBase::accepted()
188{
189 inherited::done(needRoot ? (int)Authed : (int)Accepted);
190}
191
192void
193KDMShutdownBase::verifyPluginChanged(int id)
194{
195 curPlugin = id;
196 adjustSize();
197}
198
199void
200KDMShutdownBase::verifyOk()
201{
202 accepted();
203}
204
205void
206KDMShutdownBase::verifyFailed()
207{
208 okButton->setEnabled(false);
209 cancelButton->setEnabled(false);
210}
211
212void
213KDMShutdownBase::verifyRetry()
214{
215 okButton->setEnabled(true);
216 cancelButton->setEnabled(true);
217}
218
219void
220KDMShutdownBase::verifySetUser(const QString &)
221{
222}
223
224
225static void
226doShutdown(int type, const QString &os)
227{
228 gSet(1);
229 gSendInt(G_Shutdown);
230 gSendInt(type);
231 gSendInt(0);
232 gSendInt(0);
233 gSendInt(SHUT_FORCE);
234 gSendInt(0); /* irrelevant, will timeout immediately anyway */
235 gSendStr(os.toUtf8().data());
236 gSet(0);
237}
238
239
240static bool
241getBootOptions(QStringList *options, int *defaultTarget, int *oldTarget)
242{
243 bool ret = false;
244 gSet(1);
245 gSendInt(G_ListBootOpts);
246 if (gRecvInt() == BO_OK) {
247 *options = qStringList(gRecvStrArr(0));
248 *defaultTarget = gRecvInt();
249 *oldTarget = gRecvInt();
250 ret = true;
251 }
252 gSet(0);
253 return ret;
254}
255
256KDMShutdown::KDMShutdown(int _uid, QWidget *_parent)
257 : inherited(_uid, _parent)
258{
259 QSizePolicy fp(QSizePolicy::Fixed, QSizePolicy::Fixed);
260
261 QHBoxLayout *hlay = new QHBoxLayout();
262 box->addLayout(hlay);
263
264 howGroup = new QGroupBox(i18n("Shutdown Type"), this);
265 hlay->addWidget(howGroup, 0, Qt::AlignTop);
266
267 QRadioButton *rb;
268 rb = new KDMRadioButton(i18n("&Turn off computer"), howGroup);
269 rb->setChecked(true);
270 rb->setFocus();
271
272 restart_rb = new KDMRadioButton(i18n("&Restart computer"), howGroup);
273
274 QBoxLayout *hwlay = new QVBoxLayout(howGroup);
275 hwlay->addWidget(rb);
276 hwlay->addWidget(restart_rb);
277
278 connect(rb, SIGNAL(doubleClicked()), SLOT(accept()));
279 connect(restart_rb, SIGNAL(doubleClicked()), SLOT(accept()));
280
281 QStringList options;
282 int defaultTarget;
283 if (getBootOptions(&options, &defaultTarget, &oldTarget)) { /* XXX show dialog on failure */
284 targets = new QComboBox();
285 targets->addItems(options);
286 targets->setCurrentIndex(oldTarget == -1 ? defaultTarget : oldTarget);
287 QHBoxLayout *hb = new QHBoxLayout();
288 hwlay->addLayout(hb);
289 hb->addSpacing(
290 style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)
291 + hb->spacing());
292 hb->addWidget(targets);
293 connect(targets, SIGNAL(activated(int)), SLOT(slotTargetChanged()));
294 }
295
296 howGroup->setSizePolicy(fp);
297
298 schedGroup = new QGroupBox(i18nc("@title:group ... of shutdown", "Scheduling"), this);
299 hlay->addWidget(schedGroup, 0, Qt::AlignTop);
300
301 le_start = new QLineEdit(schedGroup);
302 QLabel *lab1 = new QLabel(i18n("&Start:"), schedGroup);
303 lab1->setBuddy(le_start);
304
305 le_timeout = new QLineEdit(schedGroup);
306 QLabel *lab2 = new QLabel(i18n("T&imeout:"), schedGroup);
307 lab2->setBuddy(le_timeout);
308
309 cb_force = new QCheckBox(i18n("&Force after timeout"), schedGroup);
310 if (_allowNuke != SHUT_NONE) {
311 connect(cb_force, SIGNAL(clicked()), SLOT(slotWhenChanged()));
312 mayNuke = true;
313 } else {
314 cb_force->setEnabled(false);
315 }
316
317 QGridLayout *grid = new QGridLayout(schedGroup);
318 grid->addWidget(lab1, 0, 0, Qt::AlignRight);
319 grid->addWidget(le_start, 0, 1);
320 grid->addWidget(lab2, 1, 0, Qt::AlignRight);
321 grid->addWidget(le_timeout, 1, 1);
322 grid->addWidget(cb_force, 2, 0, 1, 2);
323
324 schedGroup->setSizePolicy(fp);
325
326 le_start->setText("0");
327 if (_defSdMode == SHUT_SCHEDULE) {
328 le_timeout->setText("-1");
329 } else {
330 le_timeout->setText("0");
331 if (_defSdMode == SHUT_FORCENOW && cb_force->isEnabled())
332 cb_force->setChecked(true);
333 }
334
335 complete(schedGroup);
336}
337
338static int
339getDate(const char *str)
340{
341 KProcess prc;
342 prc.setOutputChannelMode(KProcess::OnlyStdoutChannel);
343 prc << "/bin/date" << "+%s" << "-d" << str;
344 if (prc.execute())
345 return -1;
346 return prc.readAll().simplified().toInt();
347}
348
349void
350KDMShutdown::accept()
351{
352 if (le_start->text() == "0" || le_start->text() == "now") {
353 sch_st = time(0);
354 } else if (le_start->text()[0] == '+') {
355 sch_st = time(0) + le_start->text().toInt();
356 } else if ((sch_st = getDate(le_start->text().toLatin1())) < 0) {
357 KFMsgBox::box(this, errorbox, i18n("Entered start date is invalid."));
358 le_start->setFocus();
359 return;
360 }
361 if (le_timeout->text() == "-1" || le_timeout->text().startsWith("inf")) {
362 sch_to = TO_INF;
363 } else if (le_timeout->text()[0] == '+') {
364 sch_to = sch_st + le_timeout->text().toInt();
365 } else if ((sch_to = getDate(le_timeout->text().toLatin1())) < 0) {
366 KFMsgBox::box(this, errorbox, i18n("Entered timeout date is invalid."));
367 le_timeout->setFocus();
368 return;
369 }
370
371 inherited::accept();
372}
373
374void
375KDMShutdown::slotTargetChanged()
376{
377 restart_rb->setChecked(true);
378}
379
380void
381KDMShutdown::slotWhenChanged()
382{
383 doesNuke = cb_force->isChecked();
384 updateNeedRoot();
385}
386
387void
388KDMShutdown::accepted()
389{
390 gSet(1);
391 gSendInt(G_Shutdown);
392 gSendInt(restart_rb->isChecked() ? SHUT_REBOOT : SHUT_HALT);
393 gSendInt(sch_st);
394 gSendInt(sch_to);
395 gSendInt(cb_force->isChecked() ? SHUT_FORCE : SHUT_CANCEL);
396 gSendInt(_allowShutdown == SHUT_ROOT ? 0 : -2);
397 gSendStr((restart_rb->isChecked() &&
398 targets && targets->currentIndex() != oldTarget) ?
399 targets->currentText().toLocal8Bit().data() : 0);
400 gSet(0);
401 inherited::accepted();
402}
403
404void
405KDMShutdown::scheduleShutdown(QWidget *_parent)
406{
407 gSet(1);
408 gSendInt(G_QueryShutdown);
409 int how = gRecvInt();
410 int start = gRecvInt();
411 int timeout = gRecvInt();
412 int force = gRecvInt();
413 int uid = gRecvInt();
414 char *os = gRecvStr();
415 gSet(0);
416 if (how) {
417 int ret =
418 KDMCancelShutdown(how, start, timeout, force, uid, os,
419 _parent).exec();
420 if (!ret)
421 return;
422 doShutdown(0, 0);
423 uid = ret == Authed ? 0 : -1;
424 } else {
425 uid = -1;
426 }
427 free(os);
428 KDMShutdown(uid, _parent).exec();
429}
430
431
432KDMRadioButton::KDMRadioButton(const QString &label, QWidget *parent)
433 : inherited(label, parent)
434{
435}
436
437void
438KDMRadioButton::mouseDoubleClickEvent(QMouseEvent *)
439{
440 emit doubleClicked();
441}
442
443
444KDMDelayedPushButton::KDMDelayedPushButton(const KGuiItem &item, QWidget *parent)
445 : inherited(item, parent)
446{
447 popt.setSingleShot(true);
448 popt.setInterval(style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this));
449}
450
451void KDMDelayedPushButton::setDelayedMenu(QMenu *p)
452{
453 setMenu(p);
454 disconnect(this, 0, this, 0); // Internal button -> popup connection
455 if (p) {
456 connect(this, SIGNAL(pressed()), &popt, SLOT(start()));
457 connect(this, SIGNAL(released()), &popt, SLOT(stop()));
458 connect(&popt, SIGNAL(timeout()), SLOT(showMenu()));
459 }
460}
461
462KDMSlimShutdown::KDMSlimShutdown(QWidget *_parent)
463 : inherited(_parent)
464{
465 QHBoxLayout *hbox = new QHBoxLayout(this);
466
467 QFrame *lfrm = new QFrame(this);
468 hbox->addWidget(lfrm, Qt::AlignCenter);
469 QLabel *icon = new QLabel(lfrm);
470 icon->setPixmap(QPixmap(KStandardDirs::locate("data", "kdm/pics/shutdown.png")));
471 icon->setFixedSize(icon->sizeHint());
472 lfrm->setFixedSize(icon->sizeHint());
473
474 QVBoxLayout *buttonlay = new QVBoxLayout();
475 hbox->addLayout(buttonlay);
476
477 buttonlay->addStretch(1);
478
479 KPushButton *btnHalt = new
480 KPushButton(KGuiItem(i18n("&Turn Off Computer"), "system-shutdown"), this);
481 buttonlay->addWidget(btnHalt);
482 connect(btnHalt, SIGNAL(clicked()), SLOT(slotHalt()));
483
484 buttonlay->addSpacing(KDialog::spacingHint());
485
486 KDMDelayedPushButton *btnReboot = new
487 KDMDelayedPushButton(KGuiItem(i18n("&Restart Computer"), "system-reboot"), this);
488 buttonlay->addWidget(btnReboot);
489 connect(btnReboot, SIGNAL(clicked()), SLOT(slotReboot()));
490
491 int dummy, cur;
492 if (getBootOptions(&targetList, &dummy, &cur)) {
493 QMenu *targets = new QMenu(this);
494 for (int i = 0; i < targetList.size(); i++)
495 (targets->addAction(i == cur ?
496 i18nc("current option in boot loader",
497 "%1 (current)", targetList[i]) :
498 targetList[i]))->setData(i);
499 btnReboot->setDelayedMenu(targets);
500 connect(targets, SIGNAL(triggered(QAction*)),
501 SLOT(slotReboot(QAction*)));
502 }
503
504 buttonlay->addStretch(1);
505
506 if (_scheduledSd != SHUT_NEVER) {
507 KPushButton *btnSched = new
508 KPushButton(KGuiItem(i18nc("@action:button verb", "&Schedule...")), this);
509 buttonlay->addWidget(btnSched);
510 connect(btnSched, SIGNAL(clicked()), SLOT(slotSched()));
511
512 buttonlay->addStretch(1);
513 }
514
515 buttonlay->addWidget(new KSeparator(this));
516
517 buttonlay->addSpacing(0);
518
519 KPushButton *btnBack = new KPushButton(KStandardGuiItem::cancel(), this);
520 buttonlay->addWidget(btnBack);
521 connect(btnBack, SIGNAL(clicked()), SLOT(reject()));
522
523 buttonlay->addSpacing(KDialog::spacingHint());
524}
525
526void
527KDMSlimShutdown::slotSched()
528{
529 reject();
530 KDMShutdown::scheduleShutdown();
531}
532
533void
534KDMSlimShutdown::slotHalt()
535{
536 if (checkShutdown(SHUT_HALT, 0))
537 doShutdown(SHUT_HALT, 0);
538}
539
540void
541KDMSlimShutdown::slotReboot()
542{
543 if (checkShutdown(SHUT_REBOOT, 0))
544 doShutdown(SHUT_REBOOT, 0);
545}
546
547void
548KDMSlimShutdown::slotReboot(QAction *action)
549{
550 int opt = action->data().toInt();
551 if (checkShutdown(SHUT_REBOOT, targetList[opt]))
552 doShutdown(SHUT_REBOOT, targetList[opt]);
553}
554
555bool
556KDMSlimShutdown::checkShutdown(int type, const QString &os)
557{
558 reject();
559 QList<DpySpec> sess = fetchSessions(lstRemote | lstTTY);
560 if (sess.isEmpty() && _allowShutdown != SHUT_ROOT)
561 return true;
562 int ret = KDMConfShutdown(-1, sess, type, os).exec();
563 if (ret == Schedule) {
564 KDMShutdown::scheduleShutdown();
565 return false;
566 }
567 return ret;
568}
569
570void
571KDMSlimShutdown::externShutdown(int type, const QString &os, int uid, bool ask)
572{
573 QList<DpySpec> sess = fetchSessions(lstRemote | lstTTY);
574 if (ask || !sess.isEmpty() || (uid && _allowShutdown == SHUT_ROOT)) {
575 int ret = KDMConfShutdown(uid, sess, type, os).exec();
576 if (ret == Schedule) {
577 KDMShutdown(uid).exec();
578 return;
579 } else if (!ret) {
580 return;
581 }
582 }
583 doShutdown(type, os);
584}
585
586#define SHUT_CONSOLE_HELP I18N_NOOP(\
587 "<br/>Switching to console mode will terminate all local X servers and" \
588 " leave you with console logins only. Graphical mode is automatically" \
589 " resumed 10 seconds after the last console session ends or after" \
590 " 40 seconds if no-one logs in in the first place.<br/>")
591
592KDMConfShutdown::KDMConfShutdown(int _uid, const QList<DpySpec> &sessions, int type,
593 const QString &os, QWidget *_parent)
594 : inherited(_uid, _parent)
595{
596#ifdef HAVE_VTS
597 if (type == SHUT_CONSOLE)
598 willShut = false;
599#endif
600 QLabel *lbl = new QLabel(QString("<qt><center><b><nobr>"
601 "%1%2"
602 "</nobr></b></center>"
603#ifdef HAVE_VTS
604 "%3"
605#endif
606 "</qt>")
607 .arg((type == SHUT_HALT) ?
608 i18n("Turn Off Computer") :
609#ifdef HAVE_VTS
610 (type == SHUT_CONSOLE) ?
611 i18n("Switch to Console") :
612#endif
613 i18n("Restart Computer"))
614 .arg(!os.isEmpty() ?
615 i18n("<br/>(Next boot: %1)", os) :
616 QString())
617#ifdef HAVE_VTS
618 .arg((type == SHUT_CONSOLE) ?
619 i18n(SHUT_CONSOLE_HELP) :
620 QString())
621#endif
622 );
623 lbl->setWordWrap(true);
624 box->addWidget(lbl);
625
626 if (!sessions.isEmpty()) {
627 if (willShut && _scheduledSd != SHUT_NEVER)
628 maySched = true;
629 mayNuke = doesNuke = true;
630 if (_allowNuke == SHUT_NONE)
631 mayOk = false;
632 QLabel *lab = new QLabel(mayOk ?
633 i18n("Abort active sessions:") :
634 i18n("No permission to abort active sessions:"),
635 this);
636 box->addWidget(lab);
637 QTreeWidget *lv = new QTreeWidget(this);
638 lv->setRootIsDecorated(false);
639 lv->setSelectionMode(QAbstractItemView::NoSelection);
640 lv->setAllColumnsShowFocus(true);
641 lv->setUniformRowHeights(true);
642 lv->setEditTriggers(QAbstractItemView::NoEditTriggers);
643 lv->setColumnCount(2);
644 lv->setHeaderLabels(QStringList()
645 << i18nc("@title:column", "Session")
646 << i18nc("@title:column ... of session", "Location"));
647 int ns = 0;
648 QString user, loc;
649 foreach (const DpySpec &sess, sessions) {
650 decodeSession(sess, user, loc);
651 new QTreeWidgetItem(lv, QStringList() << user << loc);
652 ns++;
653 }
654 int fw = lv->frameWidth() * 2;
655 int hh = lv->header()->sizeHint().height();
656 int ih = lv->itemDelegate()->sizeHint(
657 QStyleOptionViewItem(), lv->model()->index(0, 0)).height();
658 lv->setFixedHeight(fw + hh + ih * (ns < 3 ? 3 : ns > 10 ? 10 : ns));
659 box->addWidget(lv);
660 complete(lv);
661 int cw[2];
662 for (int i = 0; i < 2; i++)
663 cw[i] = qMax(static_cast<QAbstractItemView *>(lv)->sizeHintForColumn(i),
664 lv->header()->sectionSizeHint(i));
665 int w = lv->maximumViewportSize().width(), w2 = w / 2;
666 int m = (w < cw[0] + cw[1]) ?
667 (cw[0] + (w - cw[1])) / 2 :
668 (cw[0] > w2) ? cw[0] : (cw[1] > w2) ? (w - cw[1]) : w2;
669 lv->header()->resizeSection(0, m);
670 } else {
671 complete(0);
672 }
673}
674
675
676KDMCancelShutdown::KDMCancelShutdown(int how, int start, int timeout,
677 int force, int uid, const QString &os,
678 QWidget *_parent)
679 : inherited(-1, _parent)
680{
681 if (force == SHUT_FORCE) {
682 if (_allowNuke == SHUT_NONE)
683 mayOk = false;
684 else if (_allowNuke == SHUT_ROOT)
685 mayNuke = doesNuke = true;
686 }
687 QLabel *lab = new QLabel(mayOk ?
688 i18n("Cancel pending shutdown:") :
689 i18n("No permission to cancel pending shutdown:"),
690 this);
691 box->addWidget(lab);
692 QDateTime qdt;
693 QString strt, end;
694 if (start < time(0)) {
695 strt = i18nc("start of shutdown:", "now");
696 } else {
697 qdt.setTime_t(start);
698 strt = qdt.toString(Qt::LocalDate);
699 }
700 if (timeout == TO_INF) {
701 end = i18nc("timeout of shutdown:", "infinite");
702 } else {
703 qdt.setTime_t(timeout);
704 end = qdt.toString(Qt::LocalDate);
705 }
706 QString trg =
707 i18n("Owner: %1"
708 "\nType: %2%5"
709 "\nStart: %3"
710 "\nTimeout: %4",
711 uid == -2 ?
712 i18nc("owner of shutdown:", "console user") :
713 uid == -1 ?
714 i18nc("owner of shutdown:", "control socket") :
715 KUser(uid).loginName() ,
716 how == SHUT_HALT ?
717 i18n("turn off computer") :
718 i18n("restart computer") ,
719 strt, end ,
720 !os.isEmpty() ?
721 i18n("\nNext boot: %1", os) :
722 QString());
723 if (timeout != TO_INF)
724 trg += i18n("\nAfter timeout: %1",
725 force == SHUT_FORCE ?
726 i18nc("after timeout:", "abort all sessions") :
727 force == SHUT_FORCEMY ?
728 i18nc("after timeout:", "abort own sessions") :
729 i18nc("after timeout:", "cancel shutdown"));
730 lab = new QLabel(trg, this);
731 box->addWidget(lab);
732 complete(0);
733}
734
735#include "kdmshutdown.moc"
736