/*
 * Copyright 2007-2016 Haiku, Inc. All rights reserved.
 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
 *
 * Distributed under the terms of the MIT License.
 */
 
 
//! Main E-Mail config window
 
 
#include "ConfigWindow.h"
 
#include <new>
#include <stdio.h>
#include <string.h>
 
#include <Alert.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <Bitmap.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <ControlLook.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <LayoutBuilder.h>
#include <ListView.h>
#include <Locale.h>
#include <MailDaemon.h>
#include <MailSettings.h>
#include <MenuBar.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Path.h>
#include <PopUpMenu.h>
#include <Region.h>
#include <Resources.h>
#include <Roster.h>
#include <Screen.h>
#include <ScrollView.h>
#include <SeparatorView.h>
#include <StringView.h>
#include <TabView.h>
#include <TextControl.h>
#include <TextView.h>
 
#include <MailPrivate.h>
 
#include "AutoConfigWindow.h"
 
 
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Config Window"
 
 
using std::nothrow;
 
// define if you want to have an apply button
//#define HAVE_APPLY_BUTTON
 
 
const uint32 kMsgAccountsRightClicked = 'arcl';
const uint32 kMsgAccountSelected = 'acsl';
const uint32 kMsgAddAccount = 'adac';
const uint32 kMsgRemoveAccount = 'rmac';
 
const uint32 kMsgIntervalUnitChanged = 'iuch';
 
const uint32 kMsgShowStatusWindowChanged = 'shst';
const uint32 kMsgStatusLookChanged = 'lkch';
const uint32 kMsgStatusWorkspaceChanged = 'wsch';
 
const uint32 kMsgSaveSettings = 'svst';
const uint32 kMsgRevertSettings = 'rvst';
const uint32 kMsgCancelSettings = 'cnst';
 
 
 
AccountItem::AccountItem(const char* label, BMailAccountSettings* account,
	item_types type)
	:
	BStringItem(label),
	fAccount(account),
	fType(type)
{
}
 
 
void
AccountItem::Update(BView* owner, const BFont* font)
{
	if (fType == ACCOUNT_ITEM)
		font = be_bold_font;
 
	BStringItem::Update(owner, font);
}
 
 
void
AccountItem::DrawItem(BView* owner, BRect rect, bool complete)
{
	owner->PushState();
	if (fType == ACCOUNT_ITEM)
		owner->SetFont(be_bold_font);
 
	BStringItem::DrawItem(owner, rect, complete);
	owner->PopState();
}
 
 
//	#pragma mark -
 
 
class AccountsListView : public BListView {
public:
	AccountsListView(BHandler* target)
		:
		BListView(NULL, B_SINGLE_SELECTION_LIST),
		fTarget(target)
	{
	}
 
	void
	KeyDown(const char *bytes, int32 numBytes)
	{
		if (numBytes != 1)
			return;
 
		if ((*bytes == B_DELETE) || (*bytes == B_BACKSPACE))
			Window()->PostMessage(kMsgRemoveAccount);
 
		BListView::KeyDown(bytes,numBytes);
	}
 
	void
	MouseDown(BPoint point)
	{
		BListView::MouseDown(point);
 
		BPoint dummy;
		uint32 buttons;
		GetMouse(&dummy, &buttons);
		if (buttons != B_SECONDARY_MOUSE_BUTTON)
			return;
 
		int32 index = IndexOf(point);
		if (index < 0)
			return;
 
		BMessage message(kMsgAccountsRightClicked);
		ConvertToScreen(&point);
		message.AddPoint("point", point);
		message.AddInt32("index", index);
		BMessenger messenger(fTarget);
		messenger.SendMessage(&message);
	}
 
private:
			BHandler*			fTarget;
};
 
 
class BitmapView : public BView {
	public:
		BitmapView(BBitmap *bitmap)
			:
			BView(NULL, B_WILL_DRAW)
		{
			fBitmap = bitmap;
 
			SetDrawingMode(B_OP_ALPHA);
			SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
			SetExplicitSize(bitmap->Bounds().Size());
		}
 
		~BitmapView()
		{
			delete fBitmap;
		}
 
		virtual void AttachedToWindow()
		{
			AdoptParentColors();
		}
 
		virtual void Draw(BRect updateRect)
		{
			DrawBitmap(fBitmap, updateRect, updateRect);
		}
 
	private:
		BBitmap *fBitmap;
};
 
 
//	#pragma mark -
 
 
ConfigWindow::ConfigWindow()
	:
	BWindow(BRect(100, 100, 600, 540), B_TRANSLATE_SYSTEM_NAME("E-mail"),
		B_TITLED_WINDOW,
		B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
	fLastSelectedAccount(NULL),
	fSaveSettings(false)
{
	BTabView* tabView = new BTabView("tab", B_WIDTH_FROM_WIDEST);
	tabView->SetBorder(B_NO_BORDER);
 
	// accounts listview
 
	BView* view = new BView("accounts", 0);
	tabView->AddTab(view);
	tabView->TabAt(0)->SetLabel(B_TRANSLATE("Accounts"));
 
	fAccountsListView = new AccountsListView(this);
	fAccountsListView->SetExplicitPreferredSize(BSize(
		fAccountsListView->StringWidth("W") * 22, B_SIZE_UNSET));
 
	BButton* addButton = new BButton(NULL, B_TRANSLATE("Add"),
		new BMessage(kMsgAddAccount));
	fRemoveButton = new BButton(NULL, B_TRANSLATE("Remove"),
		new BMessage(kMsgRemoveAccount));
 
	fConfigView = new BView(NULL, 0);
	fConfigView->SetLayout(new BGroupLayout(B_VERTICAL));
	fConfigView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
	fConfigView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
 
	BScrollView* scroller = new BScrollView(NULL, fAccountsListView, 0,
		false, true);
 
	BLayoutBuilder::Group<>(view, B_HORIZONTAL)
		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING)
		.AddGroup(B_VERTICAL)
			.Add(scroller)
			.AddGroup(B_HORIZONTAL)
				.Add(addButton)
				.Add(fRemoveButton)
			.End()
		.End()
		.Add(fConfigView, 2.0f);
 
	_ReplaceConfigView(_BuildHowToView());
 
	// general settings
 
	view = new BView("general", 0);
	view->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
	tabView->AddTab(view);
	tabView->TabAt(1)->SetLabel(B_TRANSLATE("Settings"));
 
	fCheckMailCheckBox = new BCheckBox("check", B_TRANSLATE("Check every"),
		NULL);
	fIntervalControl = new BTextControl("time", B_TRANSLATE("minutes"), NULL,
		NULL);
 
	BPopUpMenu* statusPopUp = new BPopUpMenu(B_EMPTY_STRING);
	const char* statusModes[] = {
		B_TRANSLATE_COMMENT("Never", "show status window"),
		B_TRANSLATE("While sending"),
		B_TRANSLATE("While sending and receiving")};
	for (size_t i = 0; i < sizeof(statusModes) / sizeof(statusModes[0]); i++) {
		BMessage* msg = new BMessage(kMsgShowStatusWindowChanged);
		BMenuItem* item = new BMenuItem(statusModes[i], msg);
		statusPopUp->AddItem(item);
		msg->AddInt32("ShowStatusWindow", i);
	}
 
	fStatusModeField = new BMenuField("show status",
		B_TRANSLATE("Show notifications:"), statusPopUp);
 
	BMessage* msg = new BMessage(B_REFS_RECEIVED);
	BButton* editMenuButton = new BButton(B_EMPTY_STRING,
		B_TRANSLATE("Edit mailbox menu…"), msg);
	editMenuButton->SetTarget(BMessenger("application/x-vnd.Be-TRAK"));
 
	BPath path;
	find_directory(B_USER_SETTINGS_DIRECTORY, &path);
	path.Append("Mail/Menu Links");
	BEntry entry(path.Path());
	if (entry.InitCheck() == B_OK && entry.Exists()) {
		entry_ref ref;
		entry.GetRef(&ref);
		msg->AddRef("refs", &ref);
	} else
		editMenuButton->SetEnabled(false);
 
	BLayoutBuilder::Group<>(view, B_VERTICAL)
		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING)
//		.AddGlue()
		.AddGroup(B_HORIZONTAL, 0.f)
			.AddGlue()
			.Add(fCheckMailCheckBox)
			.AddStrut(be_control_look->DefaultLabelSpacing())
			.Add(fIntervalControl->CreateTextViewLayoutItem())
			.AddStrut(be_control_look->DefaultLabelSpacing())
			.Add(fIntervalControl->CreateLabelLayoutItem())
			.AddGlue()
		.End()
		.AddGroup(B_HORIZONTAL, 0.f)
			.AddGlue()
			.Add(fStatusModeField->CreateLabelLayoutItem())
			.Add(fStatusModeField->CreateMenuBarLayoutItem())
			.AddGlue()
		.End()
		.Add(editMenuButton)
		.AddGlue();
 
	// save/revert buttons
 
	BButton* applyButton = new BButton("apply", B_TRANSLATE("Apply"),
		new BMessage(kMsgSaveSettings));
	BButton* revertButton = new BButton("revert", B_TRANSLATE("Revert"),
		new BMessage(kMsgRevertSettings));
 
	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
		.SetInsets(0, B_USE_DEFAULT_SPACING, 0, B_USE_WINDOW_SPACING)
		.Add(tabView)
		.Add(new BSeparatorView(B_HORIZONTAL))
		.AddGroup(B_HORIZONTAL, 0)
			.Add(revertButton)
			.AddGlue()
			.Add(applyButton)
			.SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
				B_USE_WINDOW_SPACING, 0);
 
	_LoadSettings();
 
	fAccountsListView->SetSelectionMessage(new BMessage(kMsgAccountSelected));
	fAccountsListView->MakeFocus(true);
 
	ResizeToPreferred();
	CenterOnScreen();
}
 
 
ConfigWindow::~ConfigWindow()
{
	while (fAccounts.CountItems() > 0)
		_RemoveAccount(fAccounts.ItemAt(0));
	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++)
		delete fToDeleteAccounts.ItemAt(i);
}
 
 
BView*
ConfigWindow::_BuildHowToView()
{
	BView* groupView = new BView("howTo", 0);
 
	BitmapView* bitmapView = NULL;
	app_info info;
	if (be_app->GetAppInfo(&info) == B_OK) {
		BFile appFile(&info.ref, B_READ_ONLY);
		BAppFileInfo appFileInfo(&appFile);
		if (appFileInfo.InitCheck() == B_OK) {
			BBitmap* bitmap = new (std::nothrow) BBitmap(BRect(0, 0, 63, 63),
				B_RGBA32);
			if (appFileInfo.GetIcon(bitmap, B_LARGE_ICON) == B_OK)
				bitmapView = new BitmapView(bitmap);
			else
				delete bitmap;
		}
	}
 
	fHowToTextView = new BTextView(NULL, B_WILL_DRAW);
	fHowToTextView->SetAlignment(B_ALIGN_CENTER);
	fHowToTextView->SetText(B_TRANSLATE(
		"Create a new account with the Add button.\n\n"
		"Remove an account with the Remove button on the selected item.\n\n"
		"Select an item in the list to change its settings."));
 
	fHowToTextView->MakeEditable(false);
	fHowToTextView->MakeSelectable(false);
 
	BFont font(be_plain_font);
	float fontFactor = font.Size() / 12.0f;
 
	fHowToTextView->SetExplicitPreferredSize(
		BSize(300 * fontFactor,400 * fontFactor));
 
	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
	fHowToTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor);
 
	BLayoutBuilder::Group<>(groupView, B_VERTICAL)
		.AddGlue()
		.Add(fHowToTextView)
		.AddGlue();
 
	if (bitmapView != NULL)
		groupView->GetLayout()->AddView(1, bitmapView);
 
	fHowToTextView->AdoptSystemColors();
 
	return groupView;
}
 
 
void
ConfigWindow::_LoadSettings()
{
	// load accounts
	for (int i = 0; i < fAccounts.CountItems(); i++)
		delete fAccounts.ItemAt(i);
	fAccounts.MakeEmpty();
 
	_LoadAccounts();
 
	// load in general settings
	BMailSettings settings;
	status_t status = _SetToGeneralSettings(&settings);
	if (status != B_OK) {
		fprintf(stderr, B_TRANSLATE("Error retrieving general settings: %s\n"),
			strerror(status));
	}
}
 
 
void
ConfigWindow::_LoadAccounts()
{
	BMailAccounts accounts;
	for (int32 i = 0; i < accounts.CountAccounts(); i++)
		fAccounts.AddItem(new BMailAccountSettings(*accounts.AccountAt(i)));
 
	for (int i = 0; i < fAccounts.CountItems(); i++) {
		BMailAccountSettings* account = fAccounts.ItemAt(i);
		_AddAccountToView(account);
	}
}
 
 
void
ConfigWindow::_SaveSettings()
{
	// collect changed accounts
	BMessage changedAccounts(BPrivate::kMsgAccountsChanged);
	for (int32 i = 0; i < fAccounts.CountItems(); i++) {
		BMailAccountSettings* account = fAccounts.ItemAt(i);
		if (account && account->HasBeenModified())
			changedAccounts.AddInt32("account", account->AccountID());
	}
	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) {
		BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i);
		changedAccounts.AddInt32("account", account->AccountID());
	}
 
	// cleanup account directory
	for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) {
		BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i);
		BEntry entry(account->AccountFile());
		entry.Remove();
		delete account;
	}
	fToDeleteAccounts.MakeEmpty();
 
	// Apply and save general settings
 
	BMailSettings settings;
	if (fSaveSettings) {
		bigtime_t interval = 0;
		if (fCheckMailCheckBox->Value() == B_CONTROL_ON) {
			// figure out time interval
			float floatInterval;
			sscanf(fIntervalControl->Text(), "%f", &floatInterval);
			interval = bigtime_t(60000000L * floatInterval);
		}
 
		settings.SetAutoCheckInterval(interval);
		settings.SetDaemonAutoStarts(!fAccounts.IsEmpty());
 
		// status mode (alway, fetching/retrieving, ...)
		int32 index = fStatusModeField->Menu()->IndexOf(
			fStatusModeField->Menu()->FindMarked());
		settings.SetShowStatusWindow(index);
 
		settings.Save();
	}
 
	// Save accounts
 
	if (fSaveSettings) {
		for (int i = 0; i < fAccounts.CountItems(); i++)
			fAccounts.ItemAt(i)->Save();
	}
 
	BMessenger messenger(B_MAIL_DAEMON_SIGNATURE);
	if (messenger.IsValid()) {
		// server should reload general settings
		messenger.SendMessage(BPrivate::kMsgSettingsUpdated);
		// notify server about changed accounts
		messenger.SendMessage(&changedAccounts);
	}
 
	// Start/stop the mail_daemon depending on the settings
	BMailDaemon daemon;
	if (fSaveSettings) {
		if (settings.DaemonAutoStarts() && !daemon.IsRunning())
			daemon.Launch();
		else if (!settings.DaemonAutoStarts() && daemon.IsRunning())
			daemon.Quit();
	}
}
 
 
bool
ConfigWindow::QuitRequested()
{
	_SaveSettings();
 
	be_app->PostMessage(B_QUIT_REQUESTED);
	return true;
}
 
 
void
ConfigWindow::MessageReceived(BMessage *msg)
{
	float fontFactor = be_plain_font->Size() / 12.0f;
	BRect autoConfigRect(0, 0, 400 * fontFactor, 300 * fontFactor);
	BRect frame;
 
	AutoConfigWindow *autoConfigWindow = NULL;
	switch (msg->what) {
		case B_COLORS_UPDATED:
		{
			rgb_color textColor;
			if (msg->FindColor(ui_color_name(B_PANEL_TEXT_COLOR), &textColor)
					== B_OK) {
				BFont font;
				fHowToTextView->SetFontAndColor(&font, 0, &textColor);
			}
			break;
		}
 
		case kMsgAccountsRightClicked:
		{
			BPoint point;
			msg->FindPoint("point", &point);
			int32 index = msg->FindInt32("index");
			AccountItem* clickedItem = dynamic_cast<AccountItem*>(
				fAccountsListView->ItemAt(index));
			if (clickedItem == NULL || clickedItem->Type() != ACCOUNT_ITEM)
				break;
 
			BPopUpMenu rightClickMenu("accounts", false, false);
 
			BMenuItem* inMenuItem = new BMenuItem(B_TRANSLATE("Incoming"),
				NULL);
			BMenuItem* outMenuItem = new BMenuItem(B_TRANSLATE("Outgoing"),
				NULL);
			rightClickMenu.AddItem(inMenuItem);
			rightClickMenu.AddItem(outMenuItem);
 
			BMailAccountSettings* settings = clickedItem->Account();
			if (settings->IsInboundEnabled())
				inMenuItem->SetMarked(true);
			if (settings->IsOutboundEnabled())
				outMenuItem->SetMarked(true);
 
			BMenuItem* selectedItem = rightClickMenu.Go(point);
			if (selectedItem == NULL)
				break;
			if (selectedItem == inMenuItem) {
				AccountItem* item = dynamic_cast<AccountItem*>(
					fAccountsListView->ItemAt(index + 1));
				if (item == NULL)
					break;
				if (settings->IsInboundEnabled()) {
					settings->SetInboundEnabled(false);
					item->SetEnabled(false);
				} else {
					settings->SetInboundEnabled(true);
					item->SetEnabled(true);
				}
			} else {
				AccountItem* item = dynamic_cast<AccountItem*>(
					fAccountsListView->ItemAt(index + 2));
				if (item == NULL)
					break;
				if (settings->IsOutboundEnabled()) {
					settings->SetOutboundEnabled(false);
					item->SetEnabled(false);
				} else {
					settings->SetOutboundEnabled(true);
					item->SetEnabled(true);
				}
			}
		}
 
		case kMsgAccountSelected:
		{
			int32 index;
			if (msg->FindInt32("index", &index) != B_OK || index < 0) {
				// deselect current item
				_ReplaceConfigView(_BuildHowToView());
				break;
			}
			AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(index);
			if (item != NULL)
				_AccountSelected(item);
			break;
		}
 
		case kMsgAddAccount:
		{
			frame = Frame();
			autoConfigRect.OffsetTo(
				frame.left + (frame.Width() - autoConfigRect.Width()) / 2,
				frame.top + (frame.Width() - autoConfigRect.Height()) / 2);
			autoConfigWindow = new AutoConfigWindow(autoConfigRect, this);
			autoConfigWindow->Show();
			break;
		}
 
		case kMsgRemoveAccount:
		{
			int32 index = fAccountsListView->CurrentSelection();
			if (index >= 0) {
				AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(
					index);
				if (item != NULL) {
					_RemoveAccount(item->Account());
					_ReplaceConfigView(_BuildHowToView());
				}
			}
			break;
		}
 
		case kMsgIntervalUnitChanged:
		{
			int32 index;
			if (msg->FindInt32("index",&index) == B_OK)
				fIntervalControl->SetEnabled(index != 0);
			break;
		}
 
		case kMsgShowStatusWindowChanged:
		{
			// the status window stuff is the only "live" setting
			BMessenger messenger("application/x-vnd.Be-POST");
			if (messenger.IsValid())
				messenger.SendMessage(msg);
			break;
		}
 
		case kMsgRevertSettings:
			_RevertToLastSettings();
			break;
 
		case kMsgSaveSettings:
			fSaveSettings = true;
			_SaveSettings();
			AccountUpdated(fLastSelectedAccount);
			_ReplaceConfigView(_BuildHowToView());
			fAccountsListView->DeselectAll();
			break;
 
		default:
			BWindow::MessageReceived(msg);
			break;
	}
}
 
 
BMailAccountSettings*
ConfigWindow::AddAccount()
{
	BMailAccountSettings* account = new BMailAccountSettings;
	if (!account)
		return NULL;
	fAccounts.AddItem(account);
	_AddAccountToView(account);
	return account;
}
 
 
void
ConfigWindow::AccountUpdated(BMailAccountSettings* account)
{
	if (account == NULL)
		return;
 
	for (int i = 0; i < fAccountsListView->CountItems(); i++) {
		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
		if (item->Account() == account) {
			if (item->Type() == ACCOUNT_ITEM) {
				item->SetText(account->Name());
				fAccountsListView->Invalidate();
			}
		}
	}
}
 
 
status_t
ConfigWindow::_SetToGeneralSettings(BMailSettings* settings)
{
	if (settings == NULL)
		return B_BAD_VALUE;
 
	status_t status = settings->InitCheck();
	if (status != B_OK)
		return status;
 
	// retrieval frequency
	uint32 interval = uint32(settings->AutoCheckInterval() / 60000000L);
	fCheckMailCheckBox->SetValue(interval != 0 ? B_CONTROL_ON : B_CONTROL_OFF);
 
	if (interval == 0)
		interval = 5;
 
	BString intervalText;
	intervalText.SetToFormat("%" B_PRIu32, interval);
	fIntervalControl->SetText(intervalText.String());
 
	int32 showStatusIndex = settings->ShowStatusWindow();
	BMenuItem* item = fStatusModeField->Menu()->ItemAt(showStatusIndex);
	if (item != NULL) {
		item->SetMarked(true);
		// send live update to the server by simulating a menu click
		BMessage msg(kMsgShowStatusWindowChanged);
		msg.AddInt32("ShowStatusWindow", showStatusIndex);
		PostMessage(&msg);
	}
 
	return B_OK;
}
 
 
void
ConfigWindow::_RevertToLastSettings()
{
	// revert general settings
	BMailSettings settings;
 
	status_t status = _SetToGeneralSettings(&settings);
	if (status != B_OK) {
		char text[256];
		sprintf(text, B_TRANSLATE(
				"\nThe general settings couldn't be reverted.\n\n"
				"Error retrieving general settings:\n%s\n"),
			strerror(status));
		BAlert* alert = new BAlert(B_TRANSLATE("Error"), text,
			B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
		alert->Go();
	}
 
	// revert account data
 
	if (fAccountsListView->CurrentSelection() != -1)
		_ReplaceConfigView(_BuildHowToView());
 
	for (int32 i = 0; i < fAccounts.CountItems(); i++) {
		BMailAccountSettings* account = fAccounts.ItemAt(i);
		_RemoveAccountFromListView(account);
		delete account;
	}
 
	fAccounts.MakeEmpty();
	_LoadAccounts();
}
 
 
void
ConfigWindow::_AddAccountToView(BMailAccountSettings* account)
{
	BString label;
	label << account->Name();
 
	AccountItem* item;
	item = new AccountItem(label, account, ACCOUNT_ITEM);
	fAccountsListView->AddItem(item);
 
	item = new AccountItem(B_TRANSLATE("\t\t· Incoming"), account, INBOUND_ITEM);
	fAccountsListView->AddItem(item);
	if (!account->IsInboundEnabled())
		item->SetEnabled(false);
 
	item = new AccountItem(B_TRANSLATE("\t\t· Outgoing"), account,
		OUTBOUND_ITEM);
	fAccountsListView->AddItem(item);
	if (!account->IsOutboundEnabled())
		item->SetEnabled(false);
 
	item = new AccountItem(B_TRANSLATE("\t\t· E-mail filters"), account,
		FILTER_ITEM);
	fAccountsListView->AddItem(item);
}
 
 
void
ConfigWindow::_RemoveAccount(BMailAccountSettings* account)
{
	_RemoveAccountFromListView(account);
	fAccounts.RemoveItem(account);
	fToDeleteAccounts.AddItem(account);
}
 
 
void
ConfigWindow::_RemoveAccountFromListView(BMailAccountSettings* account)
{
	if (fLastSelectedAccount == account) {
		_ReplaceConfigView(_BuildHowToView());
		fLastSelectedAccount = NULL;
	}
 
	for (int i = fAccountsListView->CountItems(); i-- > 0;) {
		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
		if (item->Account() == account) {
			fAccountsListView->RemoveItem(i);
			delete item;
		}
	}
}
 
 
void
ConfigWindow::_AccountSelected(AccountItem* item)
{
	AccountUpdated(fLastSelectedAccount);
 
	BMailAccountSettings* account = item->Account();
	fLastSelectedAccount = account;
 
	BView* view = NULL;
	switch (item->Type()) {
		case ACCOUNT_ITEM:
			view = new AccountConfigView(account);
			break;
 
		case INBOUND_ITEM:
			view = new ProtocolSettingsView(account->InboundAddOnRef(),
				*account, account->InboundSettings());
			break;
 
		case OUTBOUND_ITEM:
			view = new ProtocolSettingsView(account->OutboundAddOnRef(),
				*account, account->OutboundSettings());
			break;
 
		case FILTER_ITEM:
			view = new FiltersConfigView(*account);
			break;
	}
 
	_ReplaceConfigView(view);
}
 
 
void
ConfigWindow::_ReplaceConfigView(BView* view)
{
	while (BView* child = fConfigView->ChildAt(0)) {
		fConfigView->RemoveChild(child);
		delete child;
	}
 
	if (view != NULL)
		fConfigView->AddChild(view);
}

V773 Visibility scope of the 'alert' pointer was exited without releasing the memory. A memory leak is possible.