xref: /haiku/src/preferences/mail/ConfigWindow.cpp (revision b3de82492af3b6412ffaf7eb87fd6e1995755685)
1 /*
2  * Copyright 2007-2008, Haiku, Inc. All rights reserved.
3  * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 //! main E-Mail config window
9 
10 #include "ConfigWindow.h"
11 #include "CenterContainer.h"
12 #include "Account.h"
13 #include "AutoConfigWindow.h"
14 
15 #include <Application.h>
16 #include <ListView.h>
17 #include <ScrollView.h>
18 #include <StringView.h>
19 #include <Button.h>
20 #include <CheckBox.h>
21 #include <MenuField.h>
22 #include <TextControl.h>
23 #include <TextView.h>
24 #include <MenuItem.h>
25 #include <Screen.h>
26 #include <PopUpMenu.h>
27 #include <MenuBar.h>
28 #include <TabView.h>
29 #include <Box.h>
30 #include <Alert.h>
31 #include <Bitmap.h>
32 #include <Roster.h>
33 #include <Resources.h>
34 #include <Region.h>
35 
36 #include <AppFileInfo.h>
37 #include <Entry.h>
38 #include <Directory.h>
39 #include <FindDirectory.h>
40 #include <Path.h>
41 
42 #include <MailSettings.h>
43 
44 #include <new>
45 #include <stdio.h>
46 #include <string.h>
47 
48 #include <MDRLanguage.h>
49 
50 using std::nothrow;
51 
52 // define if you want to have an apply button
53 //#define HAVE_APPLY_BUTTON
54 
55 const char *kEMail = "bemaildaemon-talk@bug-br.org.br";
56 const char *kMailto = "mailto:bemaildaemon-talk@bug-br.org.br";
57 const char *kBugsitePretty = "Bug-Tracker at SourceForge.net";
58 const char *kBugsite = "http://sourceforge.net/tracker/?func=add&group_id=26926&atid=388726";
59 const char *kWebsite = "http://www.haiku-os.org";
60 const rgb_color kLinkColor = { 40, 40, 180, 255 };
61 
62 
63 const uint32 kMsgAccountSelected = 'acsl';
64 const uint32 kMsgAddAccount = 'adac';
65 const uint32 kMsgRemoveAccount = 'rmac';
66 
67 const uint32 kMsgIntervalUnitChanged = 'iuch';
68 
69 const uint32 kMsgShowStatusWindowChanged = 'shst';
70 const uint32 kMsgStatusLookChanged = 'lkch';
71 const uint32 kMsgStatusWorkspaceChanged = 'wsch';
72 
73 const uint32 kMsgApplySettings = 'apst';
74 const uint32 kMsgSaveSettings = 'svst';
75 const uint32 kMsgRevertSettings = 'rvst';
76 const uint32 kMsgCancelSettings = 'cnst';
77 
78 class AccountsListView : public BListView {
79 	public:
80 		AccountsListView(BRect rect) : BListView(rect,NULL,B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL) {}
81 		virtual	void KeyDown(const char *bytes, int32 numBytes) {
82 			if (numBytes != 1)
83 				return;
84 
85 			if ((*bytes == B_DELETE) || (*bytes == B_BACKSPACE))
86 				Window()->PostMessage(kMsgRemoveAccount);
87 
88 			BListView::KeyDown(bytes,numBytes);
89 		}
90 };
91 
92 class BitmapView : public BView
93 {
94 	public:
95 		BitmapView(BBitmap *bitmap) : BView(bitmap->Bounds(), NULL,
96 			B_FOLLOW_NONE, B_WILL_DRAW)
97 		{
98 			fBitmap = bitmap;
99 
100 			SetDrawingMode(B_OP_ALPHA);
101 			SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
102 		}
103 
104 		~BitmapView()
105 		{
106 			delete fBitmap;
107 		}
108 
109 		virtual void AttachedToWindow()
110 		{
111 			SetViewColor(Parent()->ViewColor());
112 
113 			MoveTo((Parent()->Bounds().Width() - Bounds().Width()) / 2,
114 				Frame().top);
115 		}
116 
117 		virtual void Draw(BRect updateRect)
118 		{
119 			DrawBitmap(fBitmap, updateRect, updateRect);
120 		}
121 
122 	private:
123 		BBitmap *fBitmap;
124 };
125 
126 
127 class AboutTextView : public BTextView
128 {
129 	public:
130 		AboutTextView(BRect rect) : BTextView(rect, NULL,
131 			rect.OffsetToCopy(B_ORIGIN), B_FOLLOW_NONE, B_WILL_DRAW)
132 		{
133 			int32 major = 0,middle = 0,minor = 0,variety = 0,internal = 1;
134 
135 			// get version information for app
136 
137 			app_info appInfo;
138 			if (be_app->GetAppInfo(&appInfo) == B_OK) {
139 				BFile file(&appInfo.ref, B_READ_ONLY);
140 				if (file.InitCheck() == B_OK) {
141 					BAppFileInfo info(&file);
142 					if (info.InitCheck() == B_OK) {
143 						version_info versionInfo;
144 						if (info.GetVersionInfo(&versionInfo,
145 							B_APP_VERSION_KIND) == B_OK) {
146 							major = versionInfo.major;
147 							middle = versionInfo.middle;
148 							minor = versionInfo.minor;
149 							variety = versionInfo.variety;
150 							internal = versionInfo.internal;
151 						}
152 					}
153 				}
154 			}
155 			// prepare version variety string
156 			const char *varietyStrings[] = {"Development","Alpha","Beta","Gamma","Golden master","Final"};
157 			char varietyString[32];
158 			strcpy(varietyString,varietyStrings[variety % 6]);
159 			if (variety < 5)
160 				sprintf(varietyString + strlen(varietyString),"/%li",internal);
161 
162 			char s[512];
163 			sprintf(s,	"Mail Daemon Replacement\n\n"
164 						"by Haiku, Inc. All rights reserved.\n\n"
165 						"Version %ld.%ld.%ld %s\n\n"
166 						"See LICENSE file included in the installation package for more information.\n\n\n\n"
167 						"You can contact us at:\n"
168 						"%s\n\n"
169 						"Please submit bug reports using the %s\n\n"
170 						"Project homepage at:\n%s",
171 						major,middle,minor,varietyString,
172 						kEMail,kBugsitePretty,kWebsite);
173 
174 			SetText(s);
175 			MakeEditable(false);
176 			MakeSelectable(false);
177 
178 			SetAlignment(B_ALIGN_CENTER);
179 			SetStylable(true);
180 
181 			// aethetical changes
182 			BFont font;
183 			GetFont(&font);
184 			font.SetSize(24);
185 			SetFontAndColor(0,23,&font,B_FONT_SIZE);
186 
187 			// center the view vertically
188 			rect = TextRect();  rect.OffsetTo(0,(Bounds().Height() - TextHeight(0,42)) / 2);
189 			SetTextRect(rect);
190 
191 			// set the link regions
192 			int start = strstr(s,kEMail) - s;
193 			int finish = start + strlen(kEMail);
194 			GetTextRegion(start,finish,&fMail);
195 			SetFontAndColor(start,finish,NULL,0,&kLinkColor);
196 
197 			start = strstr(s,kBugsitePretty) - s;
198 			finish = start + strlen(kBugsitePretty);
199 			GetTextRegion(start,finish,&fBugsite);
200 			SetFontAndColor(start,finish,NULL,0,&kLinkColor);
201 
202 			start = strstr(s,kWebsite) - s;
203 			finish = start + strlen(kWebsite);
204 			GetTextRegion(start,finish,&fWebsite);
205 			SetFontAndColor(start,finish,NULL,0,&kLinkColor);
206 		}
207 
208 		virtual void Draw(BRect updateRect)
209 		{
210 			BTextView::Draw(updateRect);
211 
212 			BRect rect(fMail.Frame());
213 			StrokeLine(BPoint(rect.left,rect.bottom-2),BPoint(rect.right,rect.bottom-2));
214 			rect = fBugsite.Frame();
215 			StrokeLine(BPoint(rect.left,rect.bottom-2),BPoint(rect.right,rect.bottom-2));
216 			rect = fWebsite.Frame();
217 			StrokeLine(BPoint(rect.left,rect.bottom-2),BPoint(rect.right,rect.bottom-2));
218 		}
219 
220 		virtual void MouseDown(BPoint point)
221 		{
222 			if (fMail.Contains(point)) {
223 				char *arg[] = {(char *)kMailto,NULL};
224 				be_roster->Launch("text/x-email",1,arg);
225 			} else if (fBugsite.Contains(point)) {
226 				char *arg[] = {(char *)kBugsite,NULL};
227 				be_roster->Launch("text/html",1,arg);
228 			} else if (fWebsite.Contains(point)) {
229 				char *arg[] = {(char *)kWebsite, NULL};
230 				be_roster->Launch("text/html", 1, arg);
231 			}
232 		}
233 
234 	private:
235 		BRegion	fWebsite,fMail,fBugsite;
236 };
237 
238 
239 //--------------------------------------------------------------------------------------
240 //	#pragma mark -
241 
242 
243 ConfigWindow::ConfigWindow()
244 	: BWindow(BRect(100.0, 100.0, 580.0, 540.0), "E-mail", B_TITLED_WINDOW,
245 		B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE),
246 	fLastSelectedAccount(NULL),
247 	fSaveSettings(false)
248 {
249 	// create controls
250 
251 	BRect rect(Bounds());
252 	BView *top = new BView(rect,NULL,B_FOLLOW_ALL,0);
253 	top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
254 	AddChild(top);
255 
256 	// determine font height
257 	font_height fontHeight;
258 	top->GetFontHeight(&fontHeight);
259 	int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 5;
260 
261 	rect.InsetBy(5,5);	rect.bottom -= 11 + height;
262 	BTabView *tabView = new BTabView(rect,NULL);
263 
264 	BView *view;
265 	rect = tabView->Bounds();  rect.bottom -= tabView->TabHeight() + 4;
266 	tabView->AddTab(view = new BView(rect,NULL,B_FOLLOW_ALL,0));
267 	tabView->TabAt(0)->SetLabel(MDR_DIALECT_CHOICE ("Accounts","アカウント"));
268 	view->SetViewColor(top->ViewColor());
269 
270 	// accounts listview
271 
272 	rect = view->Bounds().InsetByCopy(8,8);
273 	rect.right = 140 - B_V_SCROLL_BAR_WIDTH;
274 	rect.bottom -= height + 12;
275 	fAccountsListView = new AccountsListView(rect);
276 	view->AddChild(new BScrollView(NULL,fAccountsListView,B_FOLLOW_ALL,0,false,true));
277 	rect.right += B_V_SCROLL_BAR_WIDTH;
278 
279 	rect.top = rect.bottom + 8;  rect.bottom = rect.top + height;
280 	BRect sizeRect = rect;
281 	sizeRect.right = sizeRect.left + 30 + view->StringWidth(MDR_DIALECT_CHOICE ("Add","追加"));
282 	view->AddChild(new BButton(sizeRect,NULL,MDR_DIALECT_CHOICE ("Add","追加"),
283 		new BMessage(kMsgAddAccount),B_FOLLOW_BOTTOM));
284 
285 	sizeRect.left = sizeRect.right+3;
286 	sizeRect.right = sizeRect.left + 30 + view->StringWidth(MDR_DIALECT_CHOICE ("Remove","削除"));
287 	view->AddChild(fRemoveButton = new BButton(sizeRect,NULL,MDR_DIALECT_CHOICE ("Remove","削除"),
288 		new BMessage(kMsgRemoveAccount),B_FOLLOW_BOTTOM));
289 
290 	// accounts config view
291 	rect = view->Bounds();
292 	rect.left = fAccountsListView->Frame().right + B_V_SCROLL_BAR_WIDTH + 16;
293 	rect.right -= 10;
294 	view->AddChild(fConfigView = new CenterContainer(rect));
295 
296 	MakeHowToView();
297 
298 	// general settings
299 
300 	rect = tabView->Bounds();	rect.bottom -= tabView->TabHeight() + 4;
301 	tabView->AddTab(view = new CenterContainer(rect));
302 	tabView->TabAt(1)->SetLabel(MDR_DIALECT_CHOICE ("Settings","一般"));
303 
304 	rect = view->Bounds().InsetByCopy(8,8);
305 	rect.right -= 1;	rect.bottom = rect.top + height * 5 + 15;
306 	BBox *box = new BBox(rect);
307 	box->SetLabel(MDR_DIALECT_CHOICE ("Mail checking","メールチェック間隔"));
308 	view->AddChild(box);
309 
310 	rect = box->Bounds().InsetByCopy(8,8);
311 	rect.top += 7;	rect.bottom = rect.top + height + 5;
312 	BRect tile = rect.OffsetByCopy(0,1);
313 	int32 labelWidth = (int32)view->StringWidth(MDR_DIALECT_CHOICE ("Check every","メールチェック間隔:"))+6;
314 	tile.right = 80 + labelWidth;
315 	fIntervalControl = new BTextControl(tile,"time",MDR_DIALECT_CHOICE ("Check every","メールチェック間隔:"),
316 	NULL,NULL);
317 	fIntervalControl->SetDivider(labelWidth);
318 	box->AddChild(fIntervalControl);
319 
320 	BPopUpMenu *frequencyPopUp = new BPopUpMenu(B_EMPTY_STRING);
321 	const char *frequencyStrings[] = {
322 		MDR_DIALECT_CHOICE ("never","チェックしない"),
323 		MDR_DIALECT_CHOICE ("minutes","分毎チェック"),
324 		MDR_DIALECT_CHOICE ("hours","時間毎チェック"),
325 		MDR_DIALECT_CHOICE ("days","日間毎チェック")};
326 	BMenuItem *item;
327 	for (int32 i = 0;i < 4;i++)
328 	{
329 		frequencyPopUp->AddItem(item = new BMenuItem(frequencyStrings[i],new BMessage(kMsgIntervalUnitChanged)));
330 		if (i == 1)
331 			item->SetMarked(true);
332 	}
333 	tile.left = tile.right + 5;  tile.right = rect.right;
334 	tile.OffsetBy(0,-1);
335 	fIntervalUnitField = new BMenuField(tile,"frequency", B_EMPTY_STRING, frequencyPopUp);
336 	fIntervalUnitField->SetDivider(0.0);
337 	box->AddChild(fIntervalUnitField);
338 
339 	rect.OffsetBy(0,height + 9);	rect.bottom -= 2;
340 	fPPPActiveCheckBox = new BCheckBox(rect,"ppp active",
341 		MDR_DIALECT_CHOICE ("Only when dial-up is connected","PPP接続中時のみ"), NULL);
342 	box->AddChild(fPPPActiveCheckBox);
343 
344 	rect.OffsetBy(0,height + 9);	rect.bottom -= 2;
345 	fPPPActiveSendCheckBox = new BCheckBox(rect,"ppp activesend",
346 		MDR_DIALECT_CHOICE ("Schedule outgoing mail when dial-up is disconnected","PPP切断時、送信メールを送信箱に入れる"), NULL);
347 	box->AddChild(fPPPActiveSendCheckBox);
348 
349 	// Miscellaneous settings box
350 
351 	rect = box->Frame();  rect.bottom = rect.top + 3*height + 30;
352 	box = new BBox(rect);
353 	box->SetLabel(MDR_DIALECT_CHOICE ("Miscellaneous","その他の設定"));
354 	view->AddChild(box);
355 
356 	BPopUpMenu *statusPopUp = new BPopUpMenu(B_EMPTY_STRING);
357 	const char *statusModes[] = {
358 		MDR_DIALECT_CHOICE ("Never","表示しない"),
359 		MDR_DIALECT_CHOICE ("While sending","送信時"),
360 		MDR_DIALECT_CHOICE ("While sending and receiving","送受信時"),
361 		MDR_DIALECT_CHOICE ("Always","常に表示")};
362 	BMessage *msg;
363 	for (int32 i = 0;i < 4;i++)
364 	{
365 		statusPopUp->AddItem(item = new BMenuItem(statusModes[i],msg = new BMessage(kMsgShowStatusWindowChanged)));
366 		msg->AddInt32("ShowStatusWindow",i);
367 		if (i == 0)
368 			item->SetMarked(true);
369 	}
370 	rect = box->Bounds().InsetByCopy(8,8);
371 	rect.top += 7;
372 	rect.bottom = rect.top + height + 5;
373 	labelWidth = (int32)view->StringWidth(
374 		MDR_DIALECT_CHOICE ("Show connection status window:","ステータスの表示:")) + 8;
375 	fStatusModeField = new BMenuField(rect,"show status",
376 		MDR_DIALECT_CHOICE ("Show connection status window:","ステータスの表示:"),
377 	statusPopUp);
378 	fStatusModeField->SetDivider(labelWidth);
379 	box->AddChild(fStatusModeField);
380 
381 	rect = fStatusModeField->Frame();;
382 	rect.OffsetBy(0, rect.Height() + 10);
383 	BButton *button = new BButton(rect,B_EMPTY_STRING,
384 		MDR_DIALECT_CHOICE ("Edit mailbox menu…","メニューリンクの設定"),
385 		msg = new BMessage(B_REFS_RECEIVED));
386 	button->ResizeToPreferred();
387 	box->AddChild(button);
388 	button->SetTarget(BMessenger("application/x-vnd.Be-TRAK"));
389 
390 	BPath path;
391 	find_directory(B_USER_SETTINGS_DIRECTORY, &path);
392 	path.Append("Mail/Menu Links");
393 	BEntry entry(path.Path());
394 	if (entry.InitCheck() == B_OK && entry.Exists()) {
395 		entry_ref ref;
396 		entry.GetRef(&ref);
397 		msg->AddRef("refs", &ref);
398 	}
399 	else
400 		button->SetEnabled(false);
401 
402 	rect = button->Frame();
403 	rect.OffsetBy(rect.Width() + 30,0);
404 	fAutoStartCheckBox = new BCheckBox(rect,"start daemon",
405 		MDR_DIALECT_CHOICE ("Start mail services on startup","Mail Servicesを自動起動"),NULL);
406 	fAutoStartCheckBox->ResizeToPreferred();
407 	box->AddChild(fAutoStartCheckBox);
408 
409 	// save/revert buttons
410 
411 	top->AddChild(tabView);
412 
413 	rect = tabView->Frame();
414 	rect.top = rect.bottom + 5;  rect.bottom = rect.top + height + 5;
415 	BButton *saveButton = new BButton(rect,"apply",
416 		MDR_DIALECT_CHOICE ("Apply","適用"),
417 		new BMessage(kMsgSaveSettings));
418 	float w,h;
419 	saveButton->GetPreferredSize(&w,&h);
420 	saveButton->ResizeTo(w,h);
421 	saveButton->MoveTo(rect.right - w, rect.top);
422 	top->AddChild(saveButton);
423 
424 	BButton *revertButton = new BButton(rect,"revert",
425 		MDR_DIALECT_CHOICE ("Revert","復元"),
426 		new BMessage(kMsgRevertSettings));
427 	revertButton->GetPreferredSize(&w,&h);
428 	revertButton->ResizeTo(w,h);
429 	revertButton->MoveTo(saveButton->Frame().left - 25 - w, rect.top);
430 	top->AddChild(revertButton);
431 
432 	LoadSettings();
433 		// this will also move our window to the stored position
434 
435 	fAccountsListView->SetSelectionMessage(new BMessage(kMsgAccountSelected));
436 	fAccountsListView->MakeFocus(true);
437 }
438 
439 
440 ConfigWindow::~ConfigWindow()
441 {
442 }
443 
444 
445 void
446 ConfigWindow::MakeHowToView()
447 {
448 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
449 	BResources *resources = BApplication::AppResources();
450 	if (resources) {
451 		size_t length;
452 		char *buffer = (char *)resources->FindResource(B_LARGE_ICON_TYPE, 101, &length);
453 		if (buffer) {
454 			BBitmap *bitmap = new (nothrow) BBitmap(BRect(0, 0, 63, 63), B_CMAP8);
455 			if (bitmap && bitmap->InitCheck() == B_OK) {
456 				// copy and enlarge a 32x32 8-bit bitmap
457 				char *bits = (char *)bitmap->Bits();
458 				for (int32 i = 0, j = -64; i < (int32)length; i++) {
459 					if ((i % 32) == 0)
460 						j += 64;
461 
462 					char *b = bits + (i << 1) + j;
463 					b[0] = b[1] = b[64] = b[65] = buffer[i];
464 				}
465 				fConfigView->AddChild(new BitmapView(bitmap));
466 			} else
467 				delete bitmap;
468 		}
469 	}
470 #else
471 	app_info info;
472 	if (be_app->GetAppInfo(&info) == B_OK) {
473 		BFile appFile(&info.ref, B_READ_ONLY);
474 		BAppFileInfo appFileInfo(&appFile);
475 		if (appFileInfo.InitCheck() == B_OK) {
476 			BBitmap *bitmap = new (nothrow) BBitmap(BRect(0, 0, 63, 63), B_RGBA32);
477 			if (appFileInfo.GetIcon(bitmap, B_LARGE_ICON) == B_OK) {
478 				fConfigView->AddChild(new BitmapView(bitmap));
479 			} else
480 				delete bitmap;
481 		}
482 	}
483 #endif // HAIKU_TARGET_PLATFORM_HAIKU
484 
485 	BRect rect = fConfigView->Bounds();
486 	BTextView *text = new BTextView(rect, NULL, rect, B_FOLLOW_NONE, B_WILL_DRAW);
487 	text->SetViewColor(fConfigView->Parent()->ViewColor());
488 	text->SetAlignment(B_ALIGN_CENTER);
489 	text->SetText(
490 		MDR_DIALECT_CHOICE ("\n\nCreate a new account with the Add button.\n\n"
491 		"Remove an account with the Remove button on the selected item.\n\n"
492 		"Select an item in the list to change its settings.",
493 		"\n\nアカウントの新規作成は\"追加\"ボタンを\n使います。"
494 		"\n\nアカウント自体またはアカウントの\n送受信設定を削除するには\n項目を選択して\"削除\"ボタンを使います。"
495 		"\n\nアカウント内容の変更は、\nマウスで項目をクリックしてください。"));
496 	rect = text->Bounds();
497 	text->ResizeTo(rect.Width(), text->TextHeight(0, 42));
498 	text->SetTextRect(rect);
499 
500 	text->MakeEditable(false);
501 	text->MakeSelectable(false);
502 
503 	fConfigView->AddChild(text);
504 
505 	static_cast<CenterContainer *>(fConfigView)->Layout();
506 }
507 
508 
509 void
510 ConfigWindow::LoadSettings()
511 {
512 	Accounts::Delete();
513 	Accounts::Create(fAccountsListView, fConfigView);
514 
515 	// load in general settings
516 	BMailSettings settings;
517 	status_t status = SetToGeneralSettings(&settings);
518 	if (status == B_OK) {
519 		// move own window
520 		MoveTo(settings.ConfigWindowFrame().LeftTop());
521 	} else {
522 		fprintf(stderr, MDR_DIALECT_CHOICE("Error retrieving general settings: %s\n",
523 			"一般設定の収得に失敗: %s\n"), strerror(status));
524 	}
525 
526 	BScreen screen(this);
527 	BRect screenFrame(screen.Frame().InsetByCopy(0, 5));
528 	if (!screenFrame.Contains(Frame().LeftTop())
529 		|| !screenFrame.Contains(Frame().RightBottom()))
530 		status = B_ERROR;
531 
532 	if (status != B_OK) {
533 		// center window on screen
534 		MoveTo((screenFrame.Width() - Frame().Width()) / 2,
535 			(screenFrame.Height() - Frame().Height()) / 2);
536 	}
537 }
538 
539 
540 void
541 ConfigWindow::SaveSettings()
542 {
543 	// remove config views
544 	((CenterContainer *)fConfigView)->DeleteChildren();
545 
546 	/*** save general settings ***/
547 
548 	// figure out time interval
549 	float interval;
550 	sscanf(fIntervalControl->Text(),"%f",&interval);
551 	float multiplier = 0;
552 	switch (fIntervalUnitField->Menu()->IndexOf(fIntervalUnitField->Menu()->FindMarked())) {
553 		case 1:		// minutes
554 			multiplier = 60;
555 			break;
556 		case 2:		// hours
557 			multiplier = 60 * 60;
558 			break;
559 		case 3:		// days
560 			multiplier = 24 * 60 * 60;
561 			break;
562 	}
563 	time_t time = (time_t)(multiplier * interval);
564 
565 	// apply and save general settings
566 	BMailSettings settings;
567 	if (fSaveSettings) {
568 		settings.SetAutoCheckInterval(time * 1e6);
569 		settings.SetCheckOnlyIfPPPUp(fPPPActiveCheckBox->Value() == B_CONTROL_ON);
570 		settings.SetSendOnlyIfPPPUp(fPPPActiveSendCheckBox->Value() == B_CONTROL_ON);
571 		settings.SetDaemonAutoStarts(fAutoStartCheckBox->Value() == B_CONTROL_ON);
572 
573 		// status mode (alway, fetching/retrieving, ...)
574 		int32 index = fStatusModeField->Menu()->IndexOf(fStatusModeField->Menu()->FindMarked());
575 		settings.SetShowStatusWindow(index);
576 
577 	} else {
578 		// restore status window look
579 		settings.SetStatusWindowLook(settings.StatusWindowLook());
580 	}
581 
582 	settings.SetConfigWindowFrame(Frame());
583 	settings.Save();
584 
585 	/*** save accounts ***/
586 
587 	if (fSaveSettings)
588 		Accounts::Save();
589 
590 	// start the mail_daemon if auto start was selected
591 	if (fSaveSettings && fAutoStartCheckBox->Value() == B_CONTROL_ON
592 		&& !be_roster->IsRunning("application/x-vnd.Be-POST"))
593 	{
594 		be_roster->Launch("application/x-vnd.Be-POST");
595 	}
596 }
597 
598 
599 bool
600 ConfigWindow::QuitRequested()
601 {
602 	SaveSettings();
603 
604 	Accounts::Delete();
605 
606 	be_app->PostMessage(B_QUIT_REQUESTED);
607 	return true;
608 }
609 
610 
611 void
612 ConfigWindow::MessageReceived(BMessage *msg)
613 {
614 	BRect autoConfigRect(0, 0, 400, 300);
615 	BRect frame;
616 
617 	AutoConfigWindow *autoConfigWindow = NULL;
618 	switch (msg->what) {
619 		case kMsgAccountSelected:
620 		{
621 			int32 index;
622 			if (msg->FindInt32("index", &index) != B_OK || index < 0) {
623 				// deselect current item
624 				((CenterContainer *)fConfigView)->DeleteChildren();
625 				MakeHowToView();
626 				break;
627 			}
628 			AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(index);
629 			if (item)
630 				item->account->Selected(item->type);
631 			break;
632 		}
633 		case kMsgAddAccount:
634 		{
635 			frame = Frame();
636 			autoConfigRect.OffsetTo(frame.left + (frame.Width() - autoConfigRect.Width()) / 2,
637 										frame.top + (frame.Width() - autoConfigRect.Height()) / 2);
638 			autoConfigWindow = new AutoConfigWindow(autoConfigRect,
639 															this);
640 			autoConfigWindow->Show();
641 			break;
642 		}
643 		case kMsgRemoveAccount:
644 		{
645 			int32 index = fAccountsListView->CurrentSelection();
646 			if (index >= 0) {
647 				AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(index);
648 				if (item) {
649 					item->account->Remove(item->type);
650 					MakeHowToView();
651 				}
652 			}
653 			break;
654 		}
655 
656 		case kMsgIntervalUnitChanged:
657 		{
658 			int32 index;
659 			if (msg->FindInt32("index",&index) == B_OK)
660 				fIntervalControl->SetEnabled(index != 0);
661 			break;
662 		}
663 
664 		case kMsgShowStatusWindowChanged:
665 		{
666 			// the status window stuff is the only "live" setting
667 			BMessenger messenger("application/x-vnd.Be-POST");
668 			if (messenger.IsValid())
669 				messenger.SendMessage(msg);
670 			break;
671 		}
672 
673 		case kMsgRevertSettings:
674 			RevertToLastSettings();
675 			break;
676 		case kMsgSaveSettings:
677 			fSaveSettings = true;
678 			SaveSettings();
679 			MakeHowToView();
680 			break;
681 
682 		default:
683 			BWindow::MessageReceived(msg);
684 			break;
685 	}
686 }
687 
688 
689 status_t
690 ConfigWindow::SetToGeneralSettings(BMailSettings *settings)
691 {
692 	if (!settings)
693 		return B_BAD_VALUE;
694 
695 	status_t status = settings->InitCheck();
696 	if (status != B_OK)
697 		return status;
698 
699 	// retrieval frequency
700 
701 	time_t interval = time_t(settings->AutoCheckInterval() / 1e6L);
702 	char text[25];
703 	text[0] = 0;
704 	int timeIndex = 0;
705 	if (interval >= 60) {
706 		timeIndex = 1;
707 		sprintf(text, "%ld", interval / (60));
708 	}
709 	if (interval >= (60*60)) {
710 		timeIndex = 2;
711 		sprintf(text, "%ld", interval / (60*60));
712 	}
713 	if (interval >= (60*60*24)) {
714 		timeIndex = 3;
715 		sprintf(text, "%ld", interval / (60*60*24));
716 	}
717 	fIntervalControl->SetText(text);
718 
719 	if (BMenuItem *item = fIntervalUnitField->Menu()->ItemAt(timeIndex))
720 		item->SetMarked(true);
721 	fIntervalControl->SetEnabled(timeIndex != 0);
722 
723 	fPPPActiveCheckBox->SetValue(settings->CheckOnlyIfPPPUp());
724 	fPPPActiveSendCheckBox->SetValue(settings->SendOnlyIfPPPUp());
725 
726 	fAutoStartCheckBox->SetValue(settings->DaemonAutoStarts());
727 
728 	if (BMenuItem *item = fStatusModeField->Menu()->ItemAt(settings->ShowStatusWindow()))
729 		item->SetMarked(true);
730 
731 	return B_OK;
732 }
733 
734 
735 void
736 ConfigWindow::RevertToLastSettings()
737 {
738 	// revert general settings
739 	BMailSettings settings;
740 
741 	// restore status window look
742 	settings.SetStatusWindowLook(settings.StatusWindowLook());
743 
744 	status_t status = SetToGeneralSettings(&settings);
745 	if (status != B_OK)
746 	{
747 		char text[256];
748 		sprintf(text,
749 			MDR_DIALECT_CHOICE ("\nThe general settings couldn't be reverted.\n\n"
750 			"Error retrieving general settings:\n%s\n",
751 			"\n一般設定を戻せませんでした。\n\n一般設定収得エラー:\n%s\n"),
752 			strerror(status));
753 		(new BAlert("Error",text,"OK",NULL,NULL,B_WIDTH_AS_USUAL,B_WARNING_ALERT))->Go();
754 	}
755 
756 	// revert account data
757 
758 	if (fAccountsListView->CurrentSelection() != -1)
759 		((CenterContainer *)fConfigView)->DeleteChildren();
760 
761 	Accounts::Delete();
762 	Accounts::Create(fAccountsListView,fConfigView);
763 
764 	if (fConfigView->CountChildren() == 0)
765 		MakeHowToView();
766 }
767 
768