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