2 * Copyright 2008, François Revol, <revol@free.fr>. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 #include <ScrollView.h>
16 #include "LoginView.h"
18 #undef B_TRANSLATION_CONTEXT
19 #define B_TRANSLATION_CONTEXT "Login View"
26 class PwdItem
: public BStringItem
{
28 PwdItem(struct passwd
*pwd
, uint32 level
= 0,
30 : BStringItem("", level
, expanded
)
33 BString
name(pwd
->pw_gecos
);
34 // TODO: truncate at first ;
35 fLogin
= pwd
->pw_name
;
36 SetText(name
.String());
39 virtual ~PwdItem() {};
40 const char* Login() const { return fLogin
.String(); };
46 LoginView::LoginView(BRect frame
)
47 : BView(frame
, "LoginView", B_FOLLOW_ALL
, B_PULSE_NEEDED
)
49 // TODO: when I don't need to test in BeOS anymore,
50 // rewrite to use layout engine.
51 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
52 SetLowUIColor(ViewUIColor());
54 r
.Set(CSEP
, CSEP
, LW
, Bounds().Height() - 3 * CSEP
- BH
);
55 fUserList
= new BListView(r
, "users");
56 BScrollView
*sv
= new BScrollView("userssv", fUserList
,
57 B_FOLLOW_LEFT
| B_FOLLOW_TOP
, 0, false, true);
59 fUserList
->SetSelectionMessage(new BMessage(kUserSelected
));
60 fUserList
->SetInvocationMessage(new BMessage(kUserInvoked
));
62 r
.Set(LW
+ 30, Bounds().top
+ CSEP
,
63 Bounds().right
- CSEP
, Bounds().top
+ CSEP
+ CSEP
);
64 fLoginControl
= new BTextControl(r
, "login", B_TRANSLATE("Login:"), "",
65 new BMessage(kLoginEdited
));
66 AddChild(fLoginControl
);
68 r
.OffsetBySelf(0, CSEP
+ CSEP
);
69 fPasswordControl
= new BTextControl(r
, "password",
70 B_TRANSLATE("Password:"), "", new BMessage(kPasswordEdited
));
71 fPasswordControl
->TextView()->HideTyping(true);
72 AddChild(fPasswordControl
);
74 r
.OffsetBySelf(0, CSEP
+ CSEP
);
75 fHidePasswordCheckBox
= new BCheckBox(r
, "hidepw",
76 B_TRANSLATE("Hide password"), new BMessage(kHidePassword
));
77 fHidePasswordCheckBox
->SetValue(1);
78 AddChild(fHidePasswordCheckBox
);
81 float buttonWidth
= BW
; //(Bounds().Width() - 4 * CSEP) / 3;
82 BRect
buttonRect(0, Bounds().bottom
- BH
,
83 buttonWidth
, Bounds().bottom
);
84 buttonRect
.OffsetBySelf(CSEP
, -CSEP
);
86 fHaltButton
= new BButton(buttonRect
, "halt", B_TRANSLATE("Halt"),
87 new BMessage(kHaltAction
));
88 fHaltButton
->ResizeToPreferred();
89 AddChild(fHaltButton
);
91 buttonRect
.OffsetBySelf(CSEP
+ fHaltButton
->Frame().Width(), 0);
92 fRebootButton
= new BButton(buttonRect
, "reboot", B_TRANSLATE("Reboot"),
93 new BMessage(kRebootAction
));
95 fRebootButton
->ResizeToPreferred();
96 AddChild(fRebootButton
);
98 BRect
infoRect(buttonRect
);
99 infoRect
.OffsetBySelf(fRebootButton
->Frame().Width() + CSEP
, 0);
101 buttonRect
.OffsetToSelf(Bounds().Width() - CSEP
- buttonWidth
,
102 Bounds().Height() - CSEP
- BH
);
103 fLoginButton
= new BButton(buttonRect
, "ok", B_TRANSLATE("OK"),
104 new BMessage(kAttemptLogin
));
105 fLoginButton
->ResizeToPreferred();
106 AddChild(fLoginButton
);
108 infoRect
.right
= buttonRect
.left
- CSEP
+ 5;
111 fInfoView
= new BStringView(infoRect
, "info", info
.String());
116 LoginView::~LoginView()
121 LoginView::AttachedToWindow()
123 fUserList
->SetTarget(this);
124 fLoginControl
->SetTarget(this);
125 fPasswordControl
->SetTarget(this);
126 fHidePasswordCheckBox
->SetTarget(this);
127 fHaltButton
->SetTarget(be_app_messenger
);
128 fRebootButton
->SetTarget(be_app_messenger
);
129 fLoginButton
->SetTarget(this);
130 Window()->SetDefaultButton(fLoginButton
);
131 //fLoginControl->MakeFocus();
132 fUserList
->MakeFocus();
133 // populate user list
134 BMessenger(this).SendMessage(kAddNextUser
);
136 // size window relative to buttons
137 BRect bounds
= Window()->Bounds();
138 float spacing
= fHaltButton
->Frame().left
;
139 bounds
.bottom
= fLoginButton
->Frame().bottom
+ spacing
;
140 bounds
.right
= fLoginButton
->Frame().right
+ spacing
;
141 Window()->ResizeTo(bounds
.Width(), bounds
.Height());
144 BPoint leftTop
= fInfoView
->Frame().LeftTop();
145 leftTop
.y
+= fHaltButton
->Frame().Height() / 2;
146 leftTop
.y
-= fInfoView
->Bounds().Height() / 2;
147 fInfoView
->MoveTo(leftTop
);
152 LoginView::MessageReceived(BMessage
*message
)
154 switch (message
->what
) {
162 int32 selection
= fUserList
->CurrentSelection();
163 if (selection
> -1) {
164 PwdItem
*item
= dynamic_cast<PwdItem
*>(
165 fUserList
->ItemAt(selection
));
167 fLoginControl
->SetText(item
->Login());
172 fPasswordControl
->MakeFocus();
177 fPasswordControl
->TextView()->HideTyping(
178 fHidePasswordCheckBox
->Value());
182 // if no pass specified and we were selecting the user,
183 // give a chance to enter the password
184 // else we might want to enter an empty password.
185 if (strlen(fPasswordControl
->Text()) < 1
186 && (fUserList
->IsFocus() || fLoginControl
->IsFocus())) {
187 fPasswordControl
->MakeFocus();
190 BMessage
*m
= new BMessage(kAttemptLogin
);
191 m
->AddString("login", fLoginControl
->Text());
192 m
->AddString("password", fPasswordControl
->Text());
193 be_app
->PostMessage(m
, NULL
, this);
197 fPasswordControl
->SetText("");
198 EnableControls(false);
199 fInfoView
->SetText(B_TRANSLATE("Invalid login!"));
201 BPoint savedPos
= Window()->Frame().LeftTop();
202 for (int i
= 0; i
< 10; i
++) {
204 p
.x
+= (i
%2) ? 10 : -10;
206 Window()->UpdateIfNeeded();
209 Window()->MoveTo(savedPos
);
211 EnableControls(true);
220 message
->PrintToStream();
221 BView::MessageReceived(message
);
230 time_t now
= time(NULL
);
231 struct tm
*t
= localtime(&now
);
232 // TODO: use strftime and locale settings
234 info
.RemoveSet("\r\n");
235 fInfoView
->SetText(info
.String());
240 LoginView::AddNextUser()
243 if (fUserList
->CountItems() < 1)
248 if (pwd
&& pwd
->pw_shell
&&
249 strcmp(pwd
->pw_shell
, "false") &&
250 strcmp(pwd
->pw_shell
, "true") &&
251 strcmp(pwd
->pw_shell
, "/bin/false") &&
252 strcmp(pwd
->pw_shell
, "/bin/true")) {
254 PwdItem
*item
= new PwdItem(pwd
);
255 fUserList
->AddItem(item
);
258 BMessenger(this).SendMessage(kAddNextUser
);
265 LoginView::EnableControls(bool enable
)
268 for (i
= 0; i
< fUserList
->CountItems(); i
++) {
269 fUserList
->ItemAt(i
)->SetEnabled(enable
);
271 fLoginControl
->SetEnabled(enable
);
272 fPasswordControl
->SetEnabled(enable
);
273 fHidePasswordCheckBox
->SetEnabled(enable
);
274 fHaltButton
->SetEnabled(enable
);
275 fRebootButton
->SetEnabled(enable
);
276 fLoginButton
->SetEnabled(enable
);