xref: /haiku/src/kits/mail/ProtocolConfigView.cpp (revision 1c09002cbee8e797a0f8bbfc5678dfadd39ee1a7)
1 /* BMailProtocolConfigView - the standard config view for all protocols
2 **
3 ** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
4 */
5 
6 
7 #include <TextControl.h>
8 #include <MenuField.h>
9 #include <PopUpMenu.h>
10 #include <String.h>
11 #include <Message.h>
12 #include <MenuItem.h>
13 #include <CheckBox.h>
14 
15 #include <stdlib.h>
16 #include <stdio.h>
17 
18 #include <MDRLanguage.h>
19 
20 class _EXPORT BMailProtocolConfigView;
21 
22 #include <crypt.h>
23 
24 #include "ProtocolConfigView.h"
25 
26 
27 const char* kPartialDownloadLimit = "partial_download_limit";
28 
29 
30 BodyDownloadConfig::BodyDownloadConfig()
31 	:
32 	BView(BRect(0,0,50,50), "body_config", B_FOLLOW_ALL_SIDES, 0)
33 {
34 	const char *partial_text = MDR_DIALECT_CHOICE (
35 		"Partially download messages larger than",
36 		"部分ダウンロードする");
37 
38 	BRect r(0, 0, 280, 15);
39 	fPartialBox = new BCheckBox(r, "size_if", partial_text,
40 		new BMessage('SIZF'));
41 	fPartialBox->ResizeToPreferred();
42 
43 	r = fPartialBox->Frame();
44 	r.OffsetBy(17,r.Height() + 1);
45 	r.right = r.left + be_plain_font->StringWidth("0000") + 10;
46 	fSizeBox = new BTextControl(r, "size", "", "", NULL);
47 
48 	r.OffsetBy(r.Width() + 5,0);
49 	fBytesLabel = new BStringView(r, "kb", "KB");
50 	AddChild(fBytesLabel);
51 	fSizeBox->SetDivider(0);
52 
53 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
54 	AddChild(fPartialBox);
55 	AddChild(fSizeBox);
56 	ResizeToPreferred();
57 }
58 
59 
60 void
61 BodyDownloadConfig::SetTo(MailAddonSettings& addonSettings)
62 {
63 	const BMessage* settings = &addonSettings.Settings();
64 
65 	int32 limit = 0;
66 	if (settings->HasInt32(kPartialDownloadLimit))
67 		limit = settings->FindInt32(kPartialDownloadLimit);
68 	if (limit < 0) {
69 		fPartialBox->SetValue(B_CONTROL_OFF);
70 		fSizeBox->SetText("0");
71 		fSizeBox->SetEnabled(false);
72 	} else {
73 		limit = int32(limit / 1024);
74 		BString kb;
75 		kb << limit;
76 		fSizeBox->SetText(kb);
77 		fPartialBox->SetValue(B_CONTROL_ON);
78 		fSizeBox->SetEnabled(true);
79 	}
80 }
81 
82 
83 void
84 BodyDownloadConfig::MessageReceived(BMessage *msg)
85 {
86 	if (msg->what != 'SIZF')
87 		return BView::MessageReceived(msg);
88 	fSizeBox->SetEnabled(fPartialBox->Value());
89 }
90 
91 
92 void
93 BodyDownloadConfig::AttachedToWindow()
94 {
95 	fPartialBox->SetTarget(this);
96 	fPartialBox->ResizeToPreferred();
97 }
98 
99 
100 void
101 BodyDownloadConfig::GetPreferredSize(float *width, float *height)
102 {
103 	*height = fSizeBox->Frame().bottom + 5;
104 	*width = 200;
105 }
106 
107 
108 status_t
109 BodyDownloadConfig::Archive(BMessage* into, bool) const
110 {
111 	into->RemoveName(kPartialDownloadLimit);
112 	if (fPartialBox->Value() == B_CONTROL_ON)
113 		into->AddInt32(kPartialDownloadLimit, atoi(fSizeBox->Text()) * 1024);
114 	else
115 		into->AddInt32(kPartialDownloadLimit, -1);
116 
117 	return B_OK;
118 }
119 
120 
121 namespace {
122 
123 //--------------------Support functions and #defines---------------
124 #define enable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(true)
125 #define disable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(false)
126 
127 BTextControl *AddTextField (BRect &rect, const char *name, const char *label);
128 BMenuField *AddMenuField (BRect &rect, const char *name, const char *label);
129 float FindWidestLabel(BView *view);
130 
131 static float sItemHeight;
132 
133 inline const char *
134 TextControl(BView *parent,const char *name)
135 {
136 	BTextControl *control = (BTextControl *)(parent->FindView(name));
137 	if (control != NULL)
138 		return control->Text();
139 
140 	return "";
141 }
142 
143 
144 BTextControl *
145 AddTextField(BRect &rect, const char *name, const char *label)
146 {
147 	BTextControl *text_control = new BTextControl(rect,name,label,"",NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
148 //	text_control->SetDivider(be_plain_font->StringWidth(label));
149 	rect.OffsetBy(0,sItemHeight);
150 	return text_control;
151 }
152 
153 
154 BMenuField *AddMenuField (BRect &rect, const char *name, const char *label) {
155 	BPopUpMenu *menu = new BPopUpMenu("Select");
156 	BMenuField *control = new BMenuField(rect,name,label,menu,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
157 	control->SetDivider(be_plain_font->StringWidth(label) + 6);
158 	rect.OffsetBy(0,sItemHeight);
159 	return control;
160 }
161 
162 
163 inline BCheckBox *
164 AddCheckBox(BRect &rect, const char *name, const char *label, BMessage *msg = NULL)
165 {
166 	BCheckBox *control = new BCheckBox(rect,name,label,msg);
167 	rect.OffsetBy(0,sItemHeight);
168 	return control;
169 }
170 
171 
172 inline void
173 SetTextControl(BView *parent, const char *name, const char *text)
174 {
175 	BTextControl *control = (BTextControl *)(parent->FindView(name));
176 	if (control != NULL)
177 		control->SetText(text);
178 }
179 
180 
181 float
182 FindWidestLabel(BView *view)
183 {
184 	float width = 0;
185 	for (int32 i = view->CountChildren();i-- > 0;) {
186 		if (BControl *control = dynamic_cast<BControl *>(view->ChildAt(i))) {
187 			float labelWidth = control->StringWidth(control->Label());
188 			if (labelWidth > width)
189 				width = labelWidth;
190 		}
191 	}
192 	return width;
193 }
194 
195 } // unnamed namspace
196 
197 
198 //----------------Real code----------------------
199 BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask)
200 	:
201 	BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT
202 		| B_FOLLOW_TOP, B_WILL_DRAW),
203 	fBodyDownloadConfig(NULL)
204 {
205 	BRect rect(5,5,245,25);
206 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
207 
208 	// determine font height
209 	font_height fontHeight;
210 	GetFontHeight(&fontHeight);
211 	sItemHeight = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 13;
212 	rect.bottom = rect.top - 2 + sItemHeight;
213 
214 	if (options_mask & B_MAIL_PROTOCOL_HAS_HOSTNAME)
215 		AddChild(AddTextField(rect,"host",MDR_DIALECT_CHOICE ("Mail server:","サーバ名 :")));
216 
217 	if (options_mask & B_MAIL_PROTOCOL_HAS_USERNAME)
218 		AddChild(AddTextField(rect,"user",MDR_DIALECT_CHOICE ("Username:","ユーザーID:")));
219 
220 	if (options_mask & B_MAIL_PROTOCOL_HAS_PASSWORD) {
221 		BTextControl *control = AddTextField(rect,"pass",MDR_DIALECT_CHOICE ("Password:","パスワード:"));
222 		control->TextView()->HideTyping(true);
223 		AddChild(control);
224 	}
225 
226 	if (options_mask & B_MAIL_PROTOCOL_HAS_FLAVORS)
227 		AddChild(AddMenuField(rect,"flavor","Connection type:"));
228 
229 	if (options_mask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS)
230 		AddChild(AddMenuField(rect,"auth_method",MDR_DIALECT_CHOICE ("Login type:","認証方法 :")));
231 
232 	// set divider
233 	float width = FindWidestLabel(this);
234 	for (int32 i = CountChildren();i-- > 0;) {
235 		if (BTextControl *text = dynamic_cast<BTextControl *>(ChildAt(i)))
236 			text->SetDivider(width + 6);
237 	}
238 
239 	if (options_mask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) {
240 		AddChild(AddCheckBox(rect, "leave_mail_on_server",
241 			MDR_DIALECT_CHOICE ("Leave mail on server",
242 				"受信後にサーバ内のメールを削除しない"), new BMessage('lmos')));
243 		BCheckBox* box = AddCheckBox(rect, "delete_remote_when_local",
244 			MDR_DIALECT_CHOICE ("Remove mail from server when deleted",
245 				"端末で削除されたらサーバ保存分も削除"));
246 		box->SetEnabled(false);
247 		AddChild(box);
248 	}
249 
250 	if (options_mask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) {
251 		fBodyDownloadConfig = new BodyDownloadConfig();
252 		fBodyDownloadConfig->MoveBy(0, rect.bottom + 5);
253 		AddChild(fBodyDownloadConfig);
254 	}
255 
256 	// resize views
257 	float height;
258 	GetPreferredSize(&width,&height);
259 	ResizeTo(width,height);
260 	for (int32 i = CountChildren();i-- > 0;) {
261 		// this doesn't work with BTextControl, does anyone know why? -- axeld.
262 		if (BView *view = ChildAt(i))
263 			view->ResizeTo(width - 10,view->Bounds().Height());
264 	}
265 }
266 
267 
268 BMailProtocolConfigView::~BMailProtocolConfigView()
269 {
270 }
271 
272 
273 void
274 BMailProtocolConfigView::SetTo(MailAddonSettings& settings)
275 {
276  	const BMessage* archive = &settings.Settings();
277 
278 	BString host = archive->FindString("server");
279 	if (archive->HasInt32("port"))
280 		host << ':' << archive->FindInt32("port");
281 
282 	SetTextControl(this,"host", host.String());
283 	SetTextControl(this,"user", archive->FindString("username"));
284 
285 	char *password = get_passwd(archive, "cpasswd");
286 	if (password) {
287 		SetTextControl(this,"pass", password);
288 		delete[] password;
289 	} else
290 		SetTextControl(this,"pass", archive->FindString("password"));
291 
292 	if (archive->HasInt32("flavor")) {
293 		BMenuField *menu = (BMenuField *)(FindView("flavor"));
294 		if (menu != NULL) {
295 			if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("flavor")))
296 				item->SetMarked(true);
297 		}
298 	}
299 
300 	if (archive->HasInt32("auth_method")) {
301 		BMenuField *menu = (BMenuField *)(FindView("auth_method"));
302 		if (menu != NULL) {
303 			if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("auth_method"))) {
304 				item->SetMarked(true);
305 				if (item->Command() != 'none') {
306 					enable_control("user");
307 					enable_control("pass");
308 				}
309 			}
310 		}
311 	}
312 
313 
314 	BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server"));
315 	if (box != NULL)
316 		box->SetValue(archive->FindBool("leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
317 
318 	box = (BCheckBox *)(FindView("delete_remote_when_local"));
319 	if (box != NULL) {
320 		box->SetValue(archive->FindBool("delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
321 
322 		if (archive->FindBool("leave_mail_on_server"))
323 			box->SetEnabled(true);
324 		else
325 			box->SetEnabled(false);
326 	}
327 
328 	if (fBodyDownloadConfig)
329 		fBodyDownloadConfig->SetTo(settings);
330 }
331 
332 
333 void
334 BMailProtocolConfigView::AddFlavor(const char *label)
335 {
336 	BMenuField *menu = (BMenuField *)(FindView("flavor"));
337 	if (menu != NULL) {
338 		menu->Menu()->AddItem(new BMenuItem(label,NULL));
339 		if (menu->Menu()->FindMarked() == NULL)
340 			menu->Menu()->ItemAt(0)->SetMarked(true);
341 	}
342 }
343 
344 
345 void
346 BMailProtocolConfigView::AddAuthMethod(const char *label,bool needUserPassword)
347 {
348 	BMenuField *menu = (BMenuField *)(FindView("auth_method"));
349 	if (menu != NULL) {
350 		BMenuItem *item = new BMenuItem(label,new BMessage(needUserPassword ? 'some' : 'none'));
351 
352 		menu->Menu()->AddItem(item);
353 
354 		if (menu->Menu()->FindMarked() == NULL) {
355 			menu->Menu()->ItemAt(0)->SetMarked(true);
356 			MessageReceived(menu->Menu()->ItemAt(0)->Message());
357 		}
358 	}
359 }
360 
361 
362 void
363 BMailProtocolConfigView::AttachedToWindow()
364 {
365 	BMenuField *menu = (BMenuField *)(FindView("auth_method"));
366 	if (menu != NULL)
367 		menu->Menu()->SetTargetForItems(this);
368 
369 	BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server"));
370 	if (box != NULL)
371 		box->SetTarget(this);
372 }
373 
374 
375 void
376 BMailProtocolConfigView::MessageReceived(BMessage *msg)
377 {
378 	switch (msg->what) {
379 		case 'some':
380 			enable_control("user");
381 			enable_control("pass");
382 			break;
383 		case 'none':
384 			disable_control("user");
385 			disable_control("pass");
386 			break;
387 
388 		case 'lmos':
389 			if (msg->FindInt32("be:value") == 1) {
390 				enable_control("delete_remote_when_local");
391 			} else {
392 				disable_control("delete_remote_when_local");
393 			}
394 			break;
395 	}
396 }
397 
398 
399 status_t
400 BMailProtocolConfigView::Archive(BMessage *into, bool deep) const
401 {
402 	const char *host = TextControl((BView *)this,"host");
403 	int32 port = -1;
404 	BString host_name = host;
405 	if (host_name.FindFirst(':') > -1) {
406 		port = atol(host_name.String() + host_name.FindFirst(':') + 1);
407 		host_name.Truncate(host_name.FindFirst(':'));
408 	}
409 
410 	if (into->ReplaceString("server",host_name.String()) != B_OK)
411 		into->AddString("server",host_name.String());
412 
413 	// since there is no need for the port option, remove it here
414 	into->RemoveName("port");
415 	if (port != -1)
416 		into->AddInt32("port",port);
417 
418 	if (into->ReplaceString("username",TextControl((BView *)this,"user")) != B_OK)
419 		into->AddString("username",TextControl((BView *)this,"user"));
420 
421 	// remove old unencrypted passwords
422 	into->RemoveName("password");
423 
424 	set_passwd(into,"cpasswd",TextControl((BView *)this,"pass"));
425 
426 	BMenuField *field;
427 	int32 index = -1;
428 
429 	if ((field = (BMenuField *)(FindView("flavor"))) != NULL) {
430 		BMenuItem *item = field->Menu()->FindMarked();
431 		if (item != NULL)
432 			index = field->Menu()->IndexOf(item);
433 	}
434 
435 	if (into->ReplaceInt32("flavor",index) != B_OK)
436 		into->AddInt32("flavor",index);
437 
438 	index = -1;
439 
440 	if ((field = (BMenuField *)(FindView("auth_method"))) != NULL) {
441 		BMenuItem *item = field->Menu()->FindMarked();
442 		if (item != NULL)
443 			index = field->Menu()->IndexOf(item);
444 	}
445 
446 	if (into->ReplaceInt32("auth_method",index) != B_OK)
447 		into->AddInt32("auth_method",index);
448 
449 	if (FindView("leave_mail_on_server") != NULL) {
450 		BControl* control = (BControl*)FindView("leave_mail_on_server");
451 		bool on = (control->Value() == B_CONTROL_ON);
452 		if (into->ReplaceBool("leave_mail_on_server", on) != B_OK)
453 			into->AddBool("leave_mail_on_server", on);
454 
455 		control = (BControl*)FindView("delete_remote_when_local");
456 		on = (control->Value() == B_CONTROL_ON);
457 		if (into->ReplaceBool("delete_remote_when_local", on)) {
458 			into->AddBool("delete_remote_when_local", on);
459 		}
460 	} else {
461 		if (into->ReplaceBool("leave_mail_on_server", false) != B_OK)
462 			into->AddBool("leave_mail_on_server", false);
463 
464 		if (into->ReplaceBool("delete_remote_when_local", false) != B_OK)
465 			into->AddBool("delete_remote_when_local", false);
466 	}
467 
468 	if (fBodyDownloadConfig)
469 		fBodyDownloadConfig->Archive(into, deep);
470 	return B_OK;
471 }
472 
473 
474 void
475 BMailProtocolConfigView::GetPreferredSize(float *width, float *height)
476 {
477 	float minWidth = 250;
478 	if (BView *view = FindView("delete_remote_when_local")) {
479 		float ignore;
480 		view->GetPreferredSize(&minWidth,&ignore);
481 	}
482 	if (minWidth < 250)
483 		minWidth = 250;
484 	*width = minWidth + 10;
485 	*height = (CountChildren() * sItemHeight) + 5;
486 
487 	if (fBodyDownloadConfig) {
488 		float bodyW, bodyH;
489 		fBodyDownloadConfig->GetPreferredSize(&bodyW, &bodyH);
490 		*height+= bodyH;
491 	}
492 }
493 
494