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