xref: /haiku/src/preferences/mail/ConfigWindow.cpp (revision f0650dc98fed895fc134a359aab99c27de6a0c6a)
1 /*
2  * Copyright 2007-2015 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 
9 //! Main E-Mail config window
10 
11 
12 #include "ConfigWindow.h"
13 
14 #include <new>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <Alert.h>
19 #include <AppFileInfo.h>
20 #include <Application.h>
21 #include <Bitmap.h>
22 #include <Box.h>
23 #include <Button.h>
24 #include <Catalog.h>
25 #include <CheckBox.h>
26 #include <ControlLook.h>
27 #include <Directory.h>
28 #include <Entry.h>
29 #include <FindDirectory.h>
30 #include <LayoutBuilder.h>
31 #include <ListView.h>
32 #include <Locale.h>
33 #include <MailDaemon.h>
34 #include <MailSettings.h>
35 #include <MenuBar.h>
36 #include <MenuField.h>
37 #include <MenuItem.h>
38 #include <Path.h>
39 #include <PopUpMenu.h>
40 #include <Region.h>
41 #include <Resources.h>
42 #include <Roster.h>
43 #include <Screen.h>
44 #include <ScrollView.h>
45 #include <SeparatorView.h>
46 #include <StringView.h>
47 #include <TabView.h>
48 #include <TextControl.h>
49 #include <TextView.h>
50 
51 #include <MailPrivate.h>
52 
53 #include "AutoConfigWindow.h"
54 
55 
56 #undef B_TRANSLATION_CONTEXT
57 #define B_TRANSLATION_CONTEXT "Config Window"
58 
59 
60 using std::nothrow;
61 
62 // define if you want to have an apply button
63 //#define HAVE_APPLY_BUTTON
64 
65 
66 const uint32 kMsgAccountsRightClicked = 'arcl';
67 const uint32 kMsgAccountSelected = 'acsl';
68 const uint32 kMsgAddAccount = 'adac';
69 const uint32 kMsgRemoveAccount = 'rmac';
70 
71 const uint32 kMsgIntervalUnitChanged = 'iuch';
72 
73 const uint32 kMsgShowStatusWindowChanged = 'shst';
74 const uint32 kMsgStatusLookChanged = 'lkch';
75 const uint32 kMsgStatusWorkspaceChanged = 'wsch';
76 
77 const uint32 kMsgSaveSettings = 'svst';
78 const uint32 kMsgRevertSettings = 'rvst';
79 const uint32 kMsgCancelSettings = 'cnst';
80 
81 
82 
83 AccountItem::AccountItem(const char* label, BMailAccountSettings* account,
84 	item_types type)
85 	:
86 	BStringItem(label),
87 	fAccount(account),
88 	fType(type)
89 {
90 }
91 
92 
93 void
94 AccountItem::Update(BView* owner, const BFont* font)
95 {
96 	if (fType == ACCOUNT_ITEM)
97 		font = be_bold_font;
98 
99 	BStringItem::Update(owner, font);
100 }
101 
102 
103 void
104 AccountItem::DrawItem(BView* owner, BRect rect, bool complete)
105 {
106 	owner->PushState();
107 	if (fType == ACCOUNT_ITEM)
108 		owner->SetFont(be_bold_font);
109 
110 	BStringItem::DrawItem(owner, rect, complete);
111 	owner->PopState();
112 }
113 
114 
115 //	#pragma mark -
116 
117 
118 class AccountsListView : public BListView {
119 public:
120 	AccountsListView(BHandler* target)
121 		:
122 		BListView(NULL, B_SINGLE_SELECTION_LIST),
123 		fTarget(target)
124 	{
125 	}
126 
127 	void
128 	KeyDown(const char *bytes, int32 numBytes)
129 	{
130 		if (numBytes != 1)
131 			return;
132 
133 		if ((*bytes == B_DELETE) || (*bytes == B_BACKSPACE))
134 			Window()->PostMessage(kMsgRemoveAccount);
135 
136 		BListView::KeyDown(bytes,numBytes);
137 	}
138 
139 	void
140 	MouseDown(BPoint point)
141 	{
142 		BListView::MouseDown(point);
143 
144 		BPoint dummy;
145 		uint32 buttons;
146 		GetMouse(&dummy, &buttons);
147 		if (buttons != B_SECONDARY_MOUSE_BUTTON)
148 			return;
149 
150 		int32 index = IndexOf(point);
151 		if (index < 0)
152 			return;
153 
154 		BMessage message(kMsgAccountsRightClicked);
155 		ConvertToScreen(&point);
156 		message.AddPoint("point", point);
157 		message.AddInt32("index", index);
158 		BMessenger messenger(fTarget);
159 		messenger.SendMessage(&message);
160 	}
161 
162 private:
163 			BHandler*			fTarget;
164 };
165 
166 
167 class BitmapView : public BView {
168 	public:
169 		BitmapView(BBitmap *bitmap)
170 			:
171 			BView(NULL, B_WILL_DRAW)
172 		{
173 			fBitmap = bitmap;
174 
175 			SetDrawingMode(B_OP_ALPHA);
176 			SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
177 			SetExplicitSize(bitmap->Bounds().Size());
178 		}
179 
180 		~BitmapView()
181 		{
182 			delete fBitmap;
183 		}
184 
185 		virtual void AttachedToWindow()
186 		{
187 			AdoptParentColors();
188 		}
189 
190 		virtual void Draw(BRect updateRect)
191 		{
192 			DrawBitmap(fBitmap, updateRect, updateRect);
193 		}
194 
195 	private:
196 		BBitmap *fBitmap;
197 };
198 
199 
200 //	#pragma mark -
201 
202 
203 ConfigWindow::ConfigWindow()
204 	:
205 	BWindow(BRect(100, 100, 600, 540), B_TRANSLATE_SYSTEM_NAME("E-mail"),
206 		B_TITLED_WINDOW,
207 		B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
208 	fLastSelectedAccount(NULL),
209 	fSaveSettings(false)
210 {
211 	BTabView* tabView = new BTabView("tab");
212 	tabView->SetBorder(B_NO_BORDER);
213 
214 	// accounts listview
215 
216 	BView* view = new BView("accounts", 0);
217 	tabView->AddTab(view);
218 	tabView->TabAt(0)->SetLabel(B_TRANSLATE("Accounts"));
219 
220 	fAccountsListView = new AccountsListView(this);
221 	fAccountsListView->SetExplicitPreferredSize(BSize(
222 		fAccountsListView->StringWidth("W") * 22, B_SIZE_UNSET));
223 
224 	BButton* addButton = new BButton(NULL, B_TRANSLATE("Add"),
225 		new BMessage(kMsgAddAccount));
226 	fRemoveButton = new BButton(NULL, B_TRANSLATE("Remove"),
227 		new BMessage(kMsgRemoveAccount));
228 
229 	fConfigView = new BView(NULL, 0);
230 	fConfigView->SetLayout(new BGroupLayout(B_VERTICAL));
231 	fConfigView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
232 	fConfigView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
233 
234 	BScrollView* scroller = new BScrollView(NULL, fAccountsListView, 0,
235 		false, true);
236 
237 	BLayoutBuilder::Group<>(view, B_HORIZONTAL)
238 		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
239 			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING)
240 		.AddGroup(B_VERTICAL)
241 			.Add(scroller)
242 			.AddGroup(B_HORIZONTAL)
243 				.Add(addButton)
244 				.Add(fRemoveButton)
245 			.End()
246 		.End()
247 		.Add(fConfigView, 2.0f);
248 
249 	_ReplaceConfigView(_BuildHowToView());
250 
251 	// general settings
252 
253 	view = new BView("general", 0);
254 	view->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
255 	tabView->AddTab(view);
256 	tabView->TabAt(1)->SetLabel(B_TRANSLATE("Settings"));
257 
258 	fCheckMailCheckBox = new BCheckBox("check", B_TRANSLATE("Check every"),
259 		NULL);
260 	fIntervalControl = new BTextControl("time", B_TRANSLATE("minutes"), NULL,
261 		NULL);
262 
263 	BPopUpMenu* statusPopUp = new BPopUpMenu(B_EMPTY_STRING);
264 	const char* statusModes[] = {
265 		B_TRANSLATE_COMMENT("Never", "show status window"),
266 		B_TRANSLATE("While sending"),
267 		B_TRANSLATE("While sending and receiving")};
268 	for (size_t i = 0; i < sizeof(statusModes) / sizeof(statusModes[0]); i++) {
269 		BMessage* msg = new BMessage(kMsgShowStatusWindowChanged);
270 		BMenuItem* item = new BMenuItem(statusModes[i], msg);
271 		statusPopUp->AddItem(item);
272 		msg->AddInt32("ShowStatusWindow", i);
273 	}
274 
275 	fStatusModeField = new BMenuField("show status",
276 		B_TRANSLATE("Show notifications:"), statusPopUp);
277 
278 	BMessage* msg = new BMessage(B_REFS_RECEIVED);
279 	BButton* editMenuButton = new BButton(B_EMPTY_STRING,
280 		B_TRANSLATE("Edit mailbox menu…"), msg);
281 	editMenuButton->SetTarget(BMessenger("application/x-vnd.Be-TRAK"));
282 
283 	BPath path;
284 	find_directory(B_USER_SETTINGS_DIRECTORY, &path);
285 	path.Append("Mail/Menu Links");
286 	BEntry entry(path.Path());
287 	if (entry.InitCheck() == B_OK && entry.Exists()) {
288 		entry_ref ref;
289 		entry.GetRef(&ref);
290 		msg->AddRef("refs", &ref);
291 	} else
292 		editMenuButton->SetEnabled(false);
293 
294 	BLayoutBuilder::Group<>(view, B_VERTICAL)
295 		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
296 			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING)
297 //		.AddGlue()
298 		.AddGroup(B_HORIZONTAL, 0.f)
299 			.AddGlue()
300 			.Add(fCheckMailCheckBox)
301 			.AddStrut(be_control_look->DefaultLabelSpacing())
302 			.Add(fIntervalControl->CreateTextViewLayoutItem())
303 			.AddStrut(be_control_look->DefaultLabelSpacing())
304 			.Add(fIntervalControl->CreateLabelLayoutItem())
305 			.AddGlue()
306 		.End()
307 		.AddGroup(B_HORIZONTAL, 0.f)
308 			.AddGlue()
309 			.Add(fStatusModeField->CreateLabelLayoutItem())
310 			.Add(fStatusModeField->CreateMenuBarLayoutItem())
311 			.AddGlue()
312 		.End()
313 		.Add(editMenuButton)
314 		.AddGlue();
315 
316 	// save/revert buttons
317 
318 	BButton* applyButton = new BButton("apply", B_TRANSLATE("Apply"),
319 		new BMessage(kMsgSaveSettings));
320 	BButton* revertButton = new BButton("revert", B_TRANSLATE("Revert"),
321 		new BMessage(kMsgRevertSettings));
322 
323 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
324 		.SetInsets(0, B_USE_DEFAULT_SPACING, 0, B_USE_WINDOW_SPACING)
325 		.Add(tabView)
326 		.Add(new BSeparatorView(B_HORIZONTAL))
327 		.AddGroup(B_HORIZONTAL, 0)
328 			.Add(revertButton)
329 			.AddGlue()
330 			.Add(applyButton)
331 			.SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
332 				B_USE_WINDOW_SPACING, 0);
333 
334 	_LoadSettings();
335 
336 	fAccountsListView->SetSelectionMessage(new BMessage(kMsgAccountSelected));
337 	fAccountsListView->MakeFocus(true);
338 
339 	ResizeToPreferred();
340 	CenterOnScreen();
341 }
342 
343 
344 ConfigWindow::~ConfigWindow()
345 {
346 	while (fAccounts.CountItems() > 0)
347 		_RemoveAccount(fAccounts.ItemAt(0));
348 	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++)
349 		delete fToDeleteAccounts.ItemAt(i);
350 }
351 
352 
353 BView*
354 ConfigWindow::_BuildHowToView()
355 {
356 	BView* groupView = new BView("howTo", 0);
357 
358 	BitmapView* bitmapView = NULL;
359 	app_info info;
360 	if (be_app->GetAppInfo(&info) == B_OK) {
361 		BFile appFile(&info.ref, B_READ_ONLY);
362 		BAppFileInfo appFileInfo(&appFile);
363 		if (appFileInfo.InitCheck() == B_OK) {
364 			BBitmap* bitmap = new (std::nothrow) BBitmap(BRect(0, 0, 63, 63),
365 				B_RGBA32);
366 			if (appFileInfo.GetIcon(bitmap, B_LARGE_ICON) == B_OK)
367 				bitmapView = new BitmapView(bitmap);
368 			else
369 				delete bitmap;
370 		}
371 	}
372 
373 	fHowToTextView = new BTextView(NULL, B_WILL_DRAW);
374 	fHowToTextView->SetAlignment(B_ALIGN_CENTER);
375 	fHowToTextView->SetText(B_TRANSLATE(
376 		"Create a new account with the Add button.\n\n"
377 		"Remove an account with the Remove button on the selected item.\n\n"
378 		"Select an item in the list to change its settings."));
379 
380 	fHowToTextView->MakeEditable(false);
381 	fHowToTextView->MakeSelectable(false);
382 
383 	BFont font(be_plain_font);
384 	float fontFactor = font.Size() / 12.0f;
385 
386 	fHowToTextView->SetExplicitPreferredSize(
387 		BSize(300 * fontFactor,400 * fontFactor));
388 
389 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
390 	fHowToTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor);
391 
392 	BLayoutBuilder::Group<>(groupView, B_VERTICAL)
393 		.AddGlue()
394 		.Add(fHowToTextView)
395 		.AddGlue();
396 
397 	if (bitmapView != NULL)
398 		groupView->GetLayout()->AddView(1, bitmapView);
399 
400 	fHowToTextView->AdoptSystemColors();
401 
402 	return groupView;
403 }
404 
405 
406 void
407 ConfigWindow::_LoadSettings()
408 {
409 	// load accounts
410 	for (int i = 0; i < fAccounts.CountItems(); i++)
411 		delete fAccounts.ItemAt(i);
412 	fAccounts.MakeEmpty();
413 
414 	_LoadAccounts();
415 
416 	// load in general settings
417 	BMailSettings settings;
418 	status_t status = _SetToGeneralSettings(&settings);
419 	if (status != B_OK) {
420 		fprintf(stderr, B_TRANSLATE("Error retrieving general settings: %s\n"),
421 			strerror(status));
422 	}
423 }
424 
425 
426 void
427 ConfigWindow::_LoadAccounts()
428 {
429 	BMailAccounts accounts;
430 	for (int32 i = 0; i < accounts.CountAccounts(); i++)
431 		fAccounts.AddItem(new BMailAccountSettings(*accounts.AccountAt(i)));
432 
433 	for (int i = 0; i < fAccounts.CountItems(); i++) {
434 		BMailAccountSettings* account = fAccounts.ItemAt(i);
435 		_AddAccountToView(account);
436 	}
437 }
438 
439 
440 void
441 ConfigWindow::_SaveSettings()
442 {
443 	// collect changed accounts
444 	BMessage changedAccounts(BPrivate::kMsgAccountsChanged);
445 	for (int32 i = 0; i < fAccounts.CountItems(); i++) {
446 		BMailAccountSettings* account = fAccounts.ItemAt(i);
447 		if (account && account->HasBeenModified())
448 			changedAccounts.AddInt32("account", account->AccountID());
449 	}
450 	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) {
451 		BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i);
452 		changedAccounts.AddInt32("account", account->AccountID());
453 	}
454 
455 	// cleanup account directory
456 	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) {
457 		BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i);
458 		BEntry entry(account->AccountFile());
459 		entry.Remove();
460 		delete account;
461 	}
462 	fToDeleteAccounts.MakeEmpty();
463 
464 	// Apply and save general settings
465 
466 	BMailSettings settings;
467 	if (fSaveSettings) {
468 		bigtime_t interval = 0;
469 		if (fCheckMailCheckBox->Value() == B_CONTROL_ON) {
470 			// figure out time interval
471 			float floatInterval;
472 			sscanf(fIntervalControl->Text(), "%f", &floatInterval);
473 			interval = bigtime_t(60000000L * floatInterval);
474 		}
475 
476 		settings.SetAutoCheckInterval(interval);
477 		settings.SetDaemonAutoStarts(!fAccounts.IsEmpty());
478 
479 		// status mode (alway, fetching/retrieving, ...)
480 		int32 index = fStatusModeField->Menu()->IndexOf(
481 			fStatusModeField->Menu()->FindMarked());
482 		settings.SetShowStatusWindow(index);
483 
484 		settings.Save();
485 	}
486 
487 	// Save accounts
488 
489 	if (fSaveSettings) {
490 		for (int i = 0; i < fAccounts.CountItems(); i++)
491 			fAccounts.ItemAt(i)->Save();
492 	}
493 
494 	BMessenger messenger(B_MAIL_DAEMON_SIGNATURE);
495 	if (messenger.IsValid()) {
496 		// server should reload general settings
497 		messenger.SendMessage(BPrivate::kMsgSettingsUpdated);
498 		// notify server about changed accounts
499 		messenger.SendMessage(&changedAccounts);
500 	}
501 
502 	// Start the mail_daemon if auto start was selected
503 	BMailDaemon daemon;
504 	if (fSaveSettings && settings.DaemonAutoStarts() && !daemon.IsRunning())
505 		daemon.Launch();
506 }
507 
508 
509 bool
510 ConfigWindow::QuitRequested()
511 {
512 	_SaveSettings();
513 
514 	be_app->PostMessage(B_QUIT_REQUESTED);
515 	return true;
516 }
517 
518 
519 void
520 ConfigWindow::MessageReceived(BMessage *msg)
521 {
522 	float fontFactor = be_plain_font->Size() / 12.0f;
523 	BRect autoConfigRect(0, 0, 400 * fontFactor, 300 * fontFactor);
524 	BRect frame;
525 
526 	AutoConfigWindow *autoConfigWindow = NULL;
527 	switch (msg->what) {
528 		case B_COLORS_UPDATED:
529 		{
530 			rgb_color textColor;
531 			if (msg->FindColor(ui_color_name(B_PANEL_TEXT_COLOR), &textColor)
532 					== B_OK) {
533 				BFont font;
534 				fHowToTextView->SetFontAndColor(&font, 0, &textColor);
535 			}
536 			break;
537 		}
538 
539 		case kMsgAccountsRightClicked:
540 		{
541 			BPoint point;
542 			msg->FindPoint("point", &point);
543 			int32 index = msg->FindInt32("index");
544 			AccountItem* clickedItem = dynamic_cast<AccountItem*>(
545 				fAccountsListView->ItemAt(index));
546 			if (clickedItem == NULL || clickedItem->Type() != ACCOUNT_ITEM)
547 				break;
548 
549 			BPopUpMenu rightClickMenu("accounts", false, false);
550 
551 			BMenuItem* inMenuItem = new BMenuItem(B_TRANSLATE("Incoming"),
552 				NULL);
553 			BMenuItem* outMenuItem = new BMenuItem(B_TRANSLATE("Outgoing"),
554 				NULL);
555 			rightClickMenu.AddItem(inMenuItem);
556 			rightClickMenu.AddItem(outMenuItem);
557 
558 			BMailAccountSettings* settings = clickedItem->Account();
559 			if (settings->IsInboundEnabled())
560 				inMenuItem->SetMarked(true);
561 			if (settings->IsOutboundEnabled())
562 				outMenuItem->SetMarked(true);
563 
564 			BMenuItem* selectedItem = rightClickMenu.Go(point);
565 			if (selectedItem == NULL)
566 				break;
567 			if (selectedItem == inMenuItem) {
568 				AccountItem* item = dynamic_cast<AccountItem*>(
569 					fAccountsListView->ItemAt(index + 1));
570 				if (item == NULL)
571 					break;
572 				if (settings->IsInboundEnabled()) {
573 					settings->SetInboundEnabled(false);
574 					item->SetEnabled(false);
575 				} else {
576 					settings->SetInboundEnabled(true);
577 					item->SetEnabled(true);
578 				}
579 			} else {
580 				AccountItem* item = dynamic_cast<AccountItem*>(
581 					fAccountsListView->ItemAt(index + 2));
582 				if (item == NULL)
583 					break;
584 				if (settings->IsOutboundEnabled()) {
585 					settings->SetOutboundEnabled(false);
586 					item->SetEnabled(false);
587 				} else {
588 					settings->SetOutboundEnabled(true);
589 					item->SetEnabled(true);
590 				}
591 			}
592 		}
593 
594 		case kMsgAccountSelected:
595 		{
596 			int32 index;
597 			if (msg->FindInt32("index", &index) != B_OK || index < 0) {
598 				// deselect current item
599 				_ReplaceConfigView(_BuildHowToView());
600 				break;
601 			}
602 			AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(index);
603 			if (item != NULL)
604 				_AccountSelected(item);
605 			break;
606 		}
607 
608 		case kMsgAddAccount:
609 		{
610 			frame = Frame();
611 			autoConfigRect.OffsetTo(
612 				frame.left + (frame.Width() - autoConfigRect.Width()) / 2,
613 				frame.top + (frame.Width() - autoConfigRect.Height()) / 2);
614 			autoConfigWindow = new AutoConfigWindow(autoConfigRect, this);
615 			autoConfigWindow->Show();
616 			break;
617 		}
618 
619 		case kMsgRemoveAccount:
620 		{
621 			int32 index = fAccountsListView->CurrentSelection();
622 			if (index >= 0) {
623 				AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(
624 					index);
625 				if (item != NULL) {
626 					_RemoveAccount(item->Account());
627 					_ReplaceConfigView(_BuildHowToView());
628 				}
629 			}
630 			break;
631 		}
632 
633 		case kMsgIntervalUnitChanged:
634 		{
635 			int32 index;
636 			if (msg->FindInt32("index",&index) == B_OK)
637 				fIntervalControl->SetEnabled(index != 0);
638 			break;
639 		}
640 
641 		case kMsgShowStatusWindowChanged:
642 		{
643 			// the status window stuff is the only "live" setting
644 			BMessenger messenger("application/x-vnd.Be-POST");
645 			if (messenger.IsValid())
646 				messenger.SendMessage(msg);
647 			break;
648 		}
649 
650 		case kMsgRevertSettings:
651 			_RevertToLastSettings();
652 			break;
653 
654 		case kMsgSaveSettings:
655 			fSaveSettings = true;
656 			_SaveSettings();
657 			AccountUpdated(fLastSelectedAccount);
658 			_ReplaceConfigView(_BuildHowToView());
659 			fAccountsListView->DeselectAll();
660 			break;
661 
662 		default:
663 			BWindow::MessageReceived(msg);
664 			break;
665 	}
666 }
667 
668 
669 BMailAccountSettings*
670 ConfigWindow::AddAccount()
671 {
672 	BMailAccountSettings* account = new BMailAccountSettings;
673 	if (!account)
674 		return NULL;
675 	fAccounts.AddItem(account);
676 	_AddAccountToView(account);
677 	return account;
678 }
679 
680 
681 void
682 ConfigWindow::AccountUpdated(BMailAccountSettings* account)
683 {
684 	if (account == NULL)
685 		return;
686 
687 	for (int i = 0; i < fAccountsListView->CountItems(); i++) {
688 		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
689 		if (item->Account() == account) {
690 			if (item->Type() == ACCOUNT_ITEM) {
691 				item->SetText(account->Name());
692 				fAccountsListView->Invalidate();
693 			}
694 		}
695 	}
696 }
697 
698 
699 status_t
700 ConfigWindow::_SetToGeneralSettings(BMailSettings* settings)
701 {
702 	if (settings == NULL)
703 		return B_BAD_VALUE;
704 
705 	status_t status = settings->InitCheck();
706 	if (status != B_OK)
707 		return status;
708 
709 	// retrieval frequency
710 	uint32 interval = uint32(settings->AutoCheckInterval() / 60000000L);
711 	fCheckMailCheckBox->SetValue(interval != 0 ? B_CONTROL_ON : B_CONTROL_OFF);
712 
713 	if (interval == 0)
714 		interval = 5;
715 
716 	BString intervalText;
717 	intervalText.SetToFormat("%" B_PRIu32, interval);
718 	fIntervalControl->SetText(intervalText.String());
719 
720 	int32 showStatusIndex = settings->ShowStatusWindow();
721 	BMenuItem* item = fStatusModeField->Menu()->ItemAt(showStatusIndex);
722 	if (item != NULL) {
723 		item->SetMarked(true);
724 		// send live update to the server by simulating a menu click
725 		BMessage msg(kMsgShowStatusWindowChanged);
726 		msg.AddInt32("ShowStatusWindow", showStatusIndex);
727 		PostMessage(&msg);
728 	}
729 
730 	return B_OK;
731 }
732 
733 
734 void
735 ConfigWindow::_RevertToLastSettings()
736 {
737 	// revert general settings
738 	BMailSettings settings;
739 
740 	status_t status = _SetToGeneralSettings(&settings);
741 	if (status != B_OK) {
742 		char text[256];
743 		sprintf(text, B_TRANSLATE(
744 				"\nThe general settings couldn't be reverted.\n\n"
745 				"Error retrieving general settings:\n%s\n"),
746 			strerror(status));
747 		BAlert* alert = new BAlert(B_TRANSLATE("Error"), text,
748 			B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
749 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
750 		alert->Go();
751 	}
752 
753 	// revert account data
754 
755 	if (fAccountsListView->CurrentSelection() != -1)
756 		_ReplaceConfigView(_BuildHowToView());
757 
758 	for (int32 i = 0; i < fAccounts.CountItems(); i++) {
759 		BMailAccountSettings* account = fAccounts.ItemAt(i);
760 		_RemoveAccountFromListView(account);
761 		delete account;
762 	}
763 
764 	fAccounts.MakeEmpty();
765 	_LoadAccounts();
766 }
767 
768 
769 void
770 ConfigWindow::_AddAccountToView(BMailAccountSettings* account)
771 {
772 	BString label;
773 	label << account->Name();
774 
775 	AccountItem* item;
776 	item = new AccountItem(label, account, ACCOUNT_ITEM);
777 	fAccountsListView->AddItem(item);
778 
779 	item = new AccountItem(B_TRANSLATE("\t\t· Incoming"), account, INBOUND_ITEM);
780 	fAccountsListView->AddItem(item);
781 	if (!account->IsInboundEnabled())
782 		item->SetEnabled(false);
783 
784 	item = new AccountItem(B_TRANSLATE("\t\t· Outgoing"), account,
785 		OUTBOUND_ITEM);
786 	fAccountsListView->AddItem(item);
787 	if (!account->IsOutboundEnabled())
788 		item->SetEnabled(false);
789 
790 	item = new AccountItem(B_TRANSLATE("\t\t· E-mail filters"), account,
791 		FILTER_ITEM);
792 	fAccountsListView->AddItem(item);
793 }
794 
795 
796 void
797 ConfigWindow::_RemoveAccount(BMailAccountSettings* account)
798 {
799 	_RemoveAccountFromListView(account);
800 	fAccounts.RemoveItem(account);
801 	fToDeleteAccounts.AddItem(account);
802 }
803 
804 
805 void
806 ConfigWindow::_RemoveAccountFromListView(BMailAccountSettings* account)
807 {
808 	if (fLastSelectedAccount == account) {
809 		_ReplaceConfigView(_BuildHowToView());
810 		fLastSelectedAccount = NULL;
811 	}
812 
813 	for (int i = fAccountsListView->CountItems(); i-- > 0;) {
814 		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
815 		if (item->Account() == account) {
816 			fAccountsListView->RemoveItem(i);
817 			delete item;
818 		}
819 	}
820 }
821 
822 
823 void
824 ConfigWindow::_AccountSelected(AccountItem* item)
825 {
826 	AccountUpdated(fLastSelectedAccount);
827 
828 	BMailAccountSettings* account = item->Account();
829 	fLastSelectedAccount = account;
830 
831 	BView* view = NULL;
832 	switch (item->Type()) {
833 		case ACCOUNT_ITEM:
834 			view = new AccountConfigView(account);
835 			break;
836 
837 		case INBOUND_ITEM:
838 			view = new ProtocolSettingsView(account->InboundAddOnRef(),
839 				*account, account->InboundSettings());
840 			break;
841 
842 		case OUTBOUND_ITEM:
843 			view = new ProtocolSettingsView(account->OutboundAddOnRef(),
844 				*account, account->OutboundSettings());
845 			break;
846 
847 		case FILTER_ITEM:
848 			view = new FiltersConfigView(*account);
849 			break;
850 	}
851 
852 	_ReplaceConfigView(view);
853 }
854 
855 
856 void
857 ConfigWindow::_ReplaceConfigView(BView* view)
858 {
859 	while (BView* child = fConfigView->ChildAt(0)) {
860 		fConfigView->RemoveChild(child);
861 		delete child;
862 	}
863 
864 	if (view != NULL)
865 		fConfigView->AddChild(view);
866 }
867