1 | /* |
2 | |
3 | Conversation widget for kdm greeter |
4 | |
5 | Copyright (C) 2008 Dirk Mueller <mueller@kde.org> |
6 | Copyright (C) 2008 Oswald Buddenhagen <ossi@kde.org> |
7 | |
8 | based on classic kdm greeter: |
9 | |
10 | Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org> |
11 | Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org> |
12 | |
13 | This program is free software; you can redistribute it and/or modify |
14 | it under the terms of the GNU General Public License as published by |
15 | the Free Software Foundation; either version 2 of the License, or |
16 | (at your option) any later version. |
17 | |
18 | This program is distributed in the hope that it will be useful, |
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | GNU General Public License for more details. |
22 | |
23 | You should have received a copy of the GNU General Public License |
24 | along with this program; if not, write to the Free Software |
25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
26 | |
27 | */ |
28 | |
29 | #include "kgreet_generic.h" |
30 | |
31 | #include <kglobal.h> |
32 | #include <klocale.h> |
33 | #include <klineedit.h> |
34 | #include <kuser.h> |
35 | |
36 | #include <QLayout> |
37 | #include <QLabel> |
38 | #include <QTextDocument> |
39 | |
40 | extern KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info; // defined at bottom |
41 | |
42 | static int echoMode; |
43 | |
44 | class KDMPasswordEdit : public KLineEdit { |
45 | public: |
46 | KDMPasswordEdit(QWidget *parent = 0) : KLineEdit(parent) |
47 | { |
48 | if (::echoMode == -1) |
49 | setPasswordMode(true); |
50 | else |
51 | setEchoMode(::echoMode ? Password : NoEcho); |
52 | setContextMenuPolicy(Qt::NoContextMenu); |
53 | } |
54 | }; |
55 | |
56 | KGenericGreeter::KGenericGreeter(KGreeterPluginHandler *_handler, |
57 | QWidget *parent, |
58 | const QString &_fixedEntity, |
59 | Function _func, Context _ctx) : |
60 | QObject(), |
61 | KGreeterPlugin(_handler), |
62 | m_lineEdit(0), |
63 | fixedUser(_fixedEntity), |
64 | func(_func), |
65 | ctx(_ctx), |
66 | exp(-1), |
67 | running(false) |
68 | { |
69 | m_parentWidget = new QWidget(parent); |
70 | m_parentWidget->setObjectName("talker" ); |
71 | // XXX set some minimal size |
72 | widgetList << m_parentWidget; |
73 | m_grid = new QGridLayout(m_parentWidget); |
74 | m_grid->setMargin(0); |
75 | |
76 | if (ctx == ExUnlock || ctx == ExChangeTok) |
77 | fixedUser = KUser().loginName(); |
78 | } |
79 | |
80 | // virtual |
81 | KGenericGreeter::~KGenericGreeter() |
82 | { |
83 | abort(); |
84 | delete m_parentWidget; |
85 | } |
86 | |
87 | void // virtual |
88 | KGenericGreeter::loadUsers(const QStringList &users) |
89 | { |
90 | m_users = users; |
91 | } |
92 | |
93 | void // virtual |
94 | KGenericGreeter::presetEntity(const QString &entity, int /* field */) |
95 | { |
96 | // assert(!running); |
97 | curUser = entity; |
98 | } |
99 | |
100 | QString // virtual |
101 | KGenericGreeter::getEntity() const |
102 | { |
103 | return fixedUser.isEmpty() ? curUser : fixedUser; |
104 | } |
105 | |
106 | void // virtual |
107 | KGenericGreeter::setUser(const QString &user) |
108 | { |
109 | // assert(running); |
110 | // assert(fixedUser.isEmpty()); |
111 | if (!(kgreeterplugin_info.flags & KGreeterPluginInfo::Presettable)) |
112 | return; // Not interested in PAM telling us who logged in |
113 | if (exp) { |
114 | abort(); |
115 | start(); |
116 | } |
117 | curUser = user; |
118 | if (m_lineEdit) { // could be null if plugin is misconfigured |
119 | m_lineEdit->setText(user); |
120 | m_lineEdit->selectAll(); |
121 | m_lineEdit->setFocus(); |
122 | } |
123 | } |
124 | |
125 | void // virtual |
126 | KGenericGreeter::setEnabled(bool enable) |
127 | { |
128 | // assert(func == Authenticate && ctx == Shutdown); |
129 | // XXX this is likely to bear some bogosity |
130 | foreach (QWidget *w, m_children) |
131 | w->setEnabled(enable); |
132 | if (enable && m_lineEdit) |
133 | m_lineEdit->setFocus(); |
134 | } |
135 | |
136 | bool // virtual |
137 | KGenericGreeter::textMessage(const char *text, bool err) |
138 | { |
139 | if (err) |
140 | return false; |
141 | |
142 | if (m_infoMsgs.isEmpty()) |
143 | revive(); |
144 | QString qtext = QString::fromUtf8(text); |
145 | m_infoMsgs.append(qtext); |
146 | QLabel *label = new QLabel(qtext, m_parentWidget); |
147 | m_grid->addWidget(label, m_line++, 0, 1, 2); |
148 | m_children.append(label); |
149 | |
150 | return true; |
151 | } |
152 | |
153 | void // virtual |
154 | KGenericGreeter::textPrompt(const char *prompt, bool echo, bool /* nonBlocking */) |
155 | { |
156 | exp = |
157 | exp >= 0 || |
158 | func != Authenticate || |
159 | !(kgreeterplugin_info.flags & KGreeterPluginInfo::Presettable); |
160 | |
161 | if (!exp && !fixedUser.isEmpty()) { |
162 | handler->gplugReturnText(fixedUser.toLocal8Bit(), |
163 | KGreeterPluginHandler::IsUser); |
164 | return; |
165 | } |
166 | |
167 | if (m_infoMsgs.isEmpty()) |
168 | revive(); |
169 | else |
170 | m_infoMsgs.clear(); |
171 | |
172 | QLabel *label = new QLabel(QString::fromUtf8(prompt).trimmed()); |
173 | m_grid->addWidget(label, m_line, 0); |
174 | m_children.append(label); |
175 | m_echo = echo; |
176 | if (echo) { |
177 | m_lineEdit = new KLineEdit; |
178 | m_lineEdit->setContextMenuPolicy(Qt::NoContextMenu); |
179 | if (!exp) { |
180 | if (!m_users.isEmpty()) { |
181 | KCompletion *userNamesCompletion = new KCompletion; |
182 | userNamesCompletion->setItems(m_users); |
183 | m_lineEdit->setCompletionObject(userNamesCompletion); |
184 | m_lineEdit->setAutoDeleteCompletionObject(true); |
185 | m_lineEdit->setCompletionMode(KGlobalSettings::CompletionAuto); |
186 | } |
187 | if (!curUser.isEmpty()) { |
188 | m_lineEdit->setText(curUser); |
189 | m_lineEdit->selectAll(); |
190 | connect(m_lineEdit, SIGNAL(selectionChanged()), SLOT(slotChanged())); |
191 | } |
192 | connect(m_lineEdit, SIGNAL(editingFinished()), SLOT(slotLoginLostFocus())); |
193 | } |
194 | connect(m_lineEdit, SIGNAL(editingFinished()), SLOT(slotChanged())); |
195 | connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(slotChanged())); |
196 | } else { |
197 | m_lineEdit = new KDMPasswordEdit; |
198 | } |
199 | m_lineEdit->setMinimumWidth( |
200 | m_lineEdit->fontMetrics().width("This is a long password" )); |
201 | m_grid->addWidget(m_lineEdit, m_line, 1); |
202 | m_children.append(m_lineEdit); |
203 | m_lineEdit->show(); |
204 | m_lineEdit->setFocus(); |
205 | } |
206 | |
207 | bool // virtual |
208 | KGenericGreeter::binaryPrompt(const char *, bool) |
209 | { |
210 | // FIXME |
211 | return true; |
212 | } |
213 | |
214 | void // virtual |
215 | KGenericGreeter::start() |
216 | { |
217 | exp = -1; |
218 | running = true; |
219 | handler->gplugStart(); |
220 | } |
221 | |
222 | void // virtual |
223 | KGenericGreeter::suspend() |
224 | { |
225 | } |
226 | |
227 | void // virtual |
228 | KGenericGreeter::resume() |
229 | { |
230 | } |
231 | |
232 | void // virtual |
233 | KGenericGreeter::next() |
234 | { |
235 | if (m_lineEdit) { |
236 | m_lineEdit->setEnabled(false); |
237 | QString text = m_lineEdit->text(); |
238 | m_lineEdit = 0; |
239 | handler->gplugReturnText(text.toLocal8Bit(), |
240 | !m_echo ? |
241 | KGreeterPluginHandler::IsSecret : |
242 | !exp ? |
243 | KGreeterPluginHandler::IsUser : 0); |
244 | } |
245 | } |
246 | |
247 | void // virtual |
248 | KGenericGreeter::abort() |
249 | { |
250 | running = false; |
251 | if (exp >= 0) { |
252 | exp = -1; |
253 | handler->gplugReturnText(0, 0); |
254 | } |
255 | } |
256 | |
257 | void // virtual |
258 | KGenericGreeter::succeeded() |
259 | { |
260 | failed(); // redefining terms :-D |
261 | } |
262 | |
263 | void // virtual |
264 | KGenericGreeter::failed() |
265 | { |
266 | // assert(running || timed_login); |
267 | if (!m_infoMsgs.isEmpty()) { |
268 | QString text = "<qt>" ; |
269 | foreach (const QString &msg, m_infoMsgs) |
270 | text += "<p>" + Qt::escape(msg) + "</p>" ; |
271 | text += "</qt>" ; |
272 | revive(); |
273 | handler->gplugMsgBox(QMessageBox::Information, text); |
274 | } else { |
275 | foreach (QWidget *w, m_children) |
276 | w->setEnabled(false); |
277 | } |
278 | exp = -1; |
279 | running = false; |
280 | } |
281 | |
282 | void // virtual |
283 | KGenericGreeter::revive() |
284 | { |
285 | // assert(!running); |
286 | foreach (QWidget *w, m_children) |
287 | w->deleteLater(); |
288 | m_children.clear(); |
289 | m_infoMsgs.clear(); |
290 | m_lineEdit = 0; |
291 | m_line = 0; |
292 | } |
293 | |
294 | void // virtual |
295 | KGenericGreeter::clear() |
296 | { |
297 | // assert(!running && !passwd1Edit); |
298 | revive(); |
299 | curUser = QString::null; |
300 | } |
301 | |
302 | |
303 | // private |
304 | void |
305 | KGenericGreeter::slotLoginLostFocus() |
306 | { |
307 | m_lineEdit->setText(m_lineEdit->text().trimmed()); |
308 | if (curUser != m_lineEdit->text()) { |
309 | curUser = m_lineEdit->text(); |
310 | handler->gplugSetUser(curUser); |
311 | } |
312 | } |
313 | |
314 | void |
315 | KGenericGreeter::slotChanged() |
316 | { |
317 | handler->gplugChanged(); |
318 | } |
319 | |
320 | // factory |
321 | static bool init(const QString &, |
322 | QVariant(*getConf)(void *, const char *, const QVariant &), |
323 | void *ctx) |
324 | { |
325 | echoMode = getConf(ctx, "EchoMode" , QVariant(-1)).toInt(); |
326 | // Fielded entities are not supported per se. |
327 | // This implies that the first field is the presettable entity, if any. |
328 | if (getConf(ctx, "generic.Presettable" , QVariant(false)).toBool()) |
329 | kgreeterplugin_info.flags |= KGreeterPluginInfo::Presettable; |
330 | KGlobal::locale()->insertCatalog("kgreet_generic" ); |
331 | return true; |
332 | } |
333 | |
334 | static void done(void) |
335 | { |
336 | KGlobal::locale()->removeCatalog("kgreet_generic" ); |
337 | } |
338 | |
339 | static KGreeterPlugin * |
340 | create(KGreeterPluginHandler *handler, |
341 | QWidget *parent, |
342 | const QString &fixedEntity, |
343 | KGreeterPlugin::Function func, |
344 | KGreeterPlugin::Context ctx) |
345 | { |
346 | return new KGenericGreeter(handler, parent, fixedEntity, func, ctx); |
347 | } |
348 | |
349 | KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info = { |
350 | I18N_NOOP2("@item:inmenu authentication method" , "Generic" ), "generic" , |
351 | KGreeterPluginInfo::Local, |
352 | init, done, create |
353 | }; |
354 | |
355 | #include "kgreet_generic.moc" |
356 | |