1/*
2 * Copyright 2007-2016 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
60using std::nothrow;
61
62// define if you want to have an apply button
63//#define HAVE_APPLY_BUTTON
64
65
66const uint32 kMsgAccountsRightClicked = 'arcl';
67const uint32 kMsgAccountSelected = 'acsl';
68const uint32 kMsgAddAccount = 'adac';
69const uint32 kMsgRemoveAccount = 'rmac';
70
71const uint32 kMsgIntervalUnitChanged = 'iuch';
72
73const uint32 kMsgShowStatusWindowChanged = 'shst';
74const uint32 kMsgStatusLookChanged = 'lkch';
75const uint32 kMsgStatusWorkspaceChanged = 'wsch';
76
77const uint32 kMsgSaveSettings = 'svst';
78const uint32 kMsgRevertSettings = 'rvst';
79const uint32 kMsgCancelSettings = 'cnst';
80
81
82
83AccountItem::AccountItem(const char* label, BMailAccountSettings* account,
84	item_types type)
85	:
86	BStringItem(label),
87	fAccount(account),
88	fType(type)
89{
90}
91
92
93void
94AccountItem::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
103void
104AccountItem::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
118class AccountsListView : public BListView {
119public:
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
162private:
163			BHandler*			fTarget;
164};
165
166
167class 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
203ConfigWindow::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", B_WIDTH_FROM_WIDEST);
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
344ConfigWindow::~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
353BView*
354ConfigWindow::_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
406void
407ConfigWindow::_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
426void
427ConfigWindow::_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
440void
441ConfigWindow::_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/stop the mail_daemon depending on the settings
503	BMailDaemon daemon;
504	if (fSaveSettings) {
505		if (settings.DaemonAutoStarts() && !daemon.IsRunning())
506			daemon.Launch();
507		else if (!settings.DaemonAutoStarts() && daemon.IsRunning())
508			daemon.Quit();
509	}
510}
511
512
513bool
514ConfigWindow::QuitRequested()
515{
516	_SaveSettings();
517
518	be_app->PostMessage(B_QUIT_REQUESTED);
519	return true;
520}
521
522
523void
524ConfigWindow::MessageReceived(BMessage *msg)
525{
526	float fontFactor = be_plain_font->Size() / 12.0f;
527	BRect autoConfigRect(0, 0, 400 * fontFactor, 300 * fontFactor);
528	BRect frame;
529
530	AutoConfigWindow *autoConfigWindow = NULL;
531	switch (msg->what) {
532		case B_COLORS_UPDATED:
533		{
534			rgb_color textColor;
535			if (msg->FindColor(ui_color_name(B_PANEL_TEXT_COLOR), &textColor)
536					== B_OK) {
537				BFont font;
538				fHowToTextView->SetFontAndColor(&font, 0, &textColor);
539			}
540			break;
541		}
542
543		case kMsgAccountsRightClicked:
544		{
545			BPoint point;
546			msg->FindPoint("point", &point);
547			int32 index = msg->FindInt32("index");
548			AccountItem* clickedItem = dynamic_cast<AccountItem*>(
549				fAccountsListView->ItemAt(index));
550			if (clickedItem == NULL || clickedItem->Type() != ACCOUNT_ITEM)
551				break;
552
553			BPopUpMenu rightClickMenu("accounts", false, false);
554
555			BMenuItem* inMenuItem = new BMenuItem(B_TRANSLATE("Incoming"),
556				NULL);
557			BMenuItem* outMenuItem = new BMenuItem(B_TRANSLATE("Outgoing"),
558				NULL);
559			rightClickMenu.AddItem(inMenuItem);
560			rightClickMenu.AddItem(outMenuItem);
561
562			BMailAccountSettings* settings = clickedItem->Account();
563			if (settings->IsInboundEnabled())
564				inMenuItem->SetMarked(true);
565			if (settings->IsOutboundEnabled())
566				outMenuItem->SetMarked(true);
567
568			BMenuItem* selectedItem = rightClickMenu.Go(point);
569			if (selectedItem == NULL)
570				break;
571			if (selectedItem == inMenuItem) {
572				AccountItem* item = dynamic_cast<AccountItem*>(
573					fAccountsListView->ItemAt(index + 1));
574				if (item == NULL)
575					break;
576				if (settings->IsInboundEnabled()) {
577					settings->SetInboundEnabled(false);
578					item->SetEnabled(false);
579				} else {
580					settings->SetInboundEnabled(true);
581					item->SetEnabled(true);
582				}
583			} else {
584				AccountItem* item = dynamic_cast<AccountItem*>(
585					fAccountsListView->ItemAt(index + 2));
586				if (item == NULL)
587					break;
588				if (settings->IsOutboundEnabled()) {
589					settings->SetOutboundEnabled(false);
590					item->SetEnabled(false);
591				} else {
592					settings->SetOutboundEnabled(true);
593					item->SetEnabled(true);
594				}
595			}
596		}
597
598		case kMsgAccountSelected:
599		{
600			int32 index;
601			if (msg->FindInt32("index", &index) != B_OK || index < 0) {
602				// deselect current item
603				_ReplaceConfigView(_BuildHowToView());
604				break;
605			}
606			AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(index);
607			if (item != NULL)
608				_AccountSelected(item);
609			break;
610		}
611
612		case kMsgAddAccount:
613		{
614			frame = Frame();
615			autoConfigRect.OffsetTo(
616				frame.left + (frame.Width() - autoConfigRect.Width()) / 2,
617				frame.top + (frame.Width() - autoConfigRect.Height()) / 2);
618			autoConfigWindow = new AutoConfigWindow(autoConfigRect, this);
619			autoConfigWindow->Show();
620			break;
621		}
622
623		case kMsgRemoveAccount:
624		{
625			int32 index = fAccountsListView->CurrentSelection();
626			if (index >= 0) {
627				AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(
628					index);
629				if (item != NULL) {
630					_RemoveAccount(item->Account());
631					_ReplaceConfigView(_BuildHowToView());
632				}
633			}
634			break;
635		}
636
637		case kMsgIntervalUnitChanged:
638		{
639			int32 index;
640			if (msg->FindInt32("index",&index) == B_OK)
641				fIntervalControl->SetEnabled(index != 0);
642			break;
643		}
644
645		case kMsgShowStatusWindowChanged:
646		{
647			// the status window stuff is the only "live" setting
648			BMessenger messenger("application/x-vnd.Be-POST");
649			if (messenger.IsValid())
650				messenger.SendMessage(msg);
651			break;
652		}
653
654		case kMsgRevertSettings:
655			_RevertToLastSettings();
656			break;
657
658		case kMsgSaveSettings:
659			fSaveSettings = true;
660			_SaveSettings();
661			AccountUpdated(fLastSelectedAccount);
662			_ReplaceConfigView(_BuildHowToView());
663			fAccountsListView->DeselectAll();
664			break;
665
666		default:
667			BWindow::MessageReceived(msg);
668			break;
669	}
670}
671
672
673BMailAccountSettings*
674ConfigWindow::AddAccount()
675{
676	BMailAccountSettings* account = new BMailAccountSettings;
677	if (!account)
678		return NULL;
679	fAccounts.AddItem(account);
680	_AddAccountToView(account);
681	return account;
682}
683
684
685void
686ConfigWindow::AccountUpdated(BMailAccountSettings* account)
687{
688	if (account == NULL)
689		return;
690
691	for (int i = 0; i < fAccountsListView->CountItems(); i++) {
692		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
693		if (item->Account() == account) {
694			if (item->Type() == ACCOUNT_ITEM) {
695				item->SetText(account->Name());
696				fAccountsListView->Invalidate();
697			}
698		}
699	}
700}
701
702
703status_t
704ConfigWindow::_SetToGeneralSettings(BMailSettings* settings)
705{
706	if (settings == NULL)
707		return B_BAD_VALUE;
708
709	status_t status = settings->InitCheck();
710	if (status != B_OK)
711		return status;
712
713	// retrieval frequency
714	uint32 interval = uint32(settings->AutoCheckInterval() / 60000000L);
715	fCheckMailCheckBox->SetValue(interval != 0 ? B_CONTROL_ON : B_CONTROL_OFF);
716
717	if (interval == 0)
718		interval = 5;
719
720	BString intervalText;
721	intervalText.SetToFormat("%" B_PRIu32, interval);
722	fIntervalControl->SetText(intervalText.String());
723
724	int32 showStatusIndex = settings->ShowStatusWindow();
725	BMenuItem* item = fStatusModeField->Menu()->ItemAt(showStatusIndex);
726	if (item != NULL) {
727		item->SetMarked(true);
728		// send live update to the server by simulating a menu click
729		BMessage msg(kMsgShowStatusWindowChanged);
730		msg.AddInt32("ShowStatusWindow", showStatusIndex);
731		PostMessage(&msg);
732	}
733
734	return B_OK;
735}
736
737
738void
739ConfigWindow::_RevertToLastSettings()
740{
741	// revert general settings
742	BMailSettings settings;
743
744	status_t status = _SetToGeneralSettings(&settings);
745	if (status != B_OK) {
746		char text[256];
747		sprintf(text, B_TRANSLATE(
748				"\nThe general settings couldn't be reverted.\n\n"
749				"Error retrieving general settings:\n%s\n"),
750			strerror(status));
751		BAlert* alert = new BAlert(B_TRANSLATE("Error"), text,
752			B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
753		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
754		alert->Go();
755	}
756
757	// revert account data
758
759	if (fAccountsListView->CurrentSelection() != -1)
760		_ReplaceConfigView(_BuildHowToView());
761
762	for (int32 i = 0; i < fAccounts.CountItems(); i++) {
763		BMailAccountSettings* account = fAccounts.ItemAt(i);
764		_RemoveAccountFromListView(account);
765		delete account;
766	}
767
768	fAccounts.MakeEmpty();
769	_LoadAccounts();
770}
771
772
773void
774ConfigWindow::_AddAccountToView(BMailAccountSettings* account)
775{
776	BString label;
777	label << account->Name();
778
779	AccountItem* item;
780	item = new AccountItem(label, account, ACCOUNT_ITEM);
781	fAccountsListView->AddItem(item);
782
783	item = new AccountItem(B_TRANSLATE("\t\t�� Incoming"), account, INBOUND_ITEM);
784	fAccountsListView->AddItem(item);
785	if (!account->IsInboundEnabled())
786		item->SetEnabled(false);
787
788	item = new AccountItem(B_TRANSLATE("\t\t�� Outgoing"), account,
789		OUTBOUND_ITEM);
790	fAccountsListView->AddItem(item);
791	if (!account->IsOutboundEnabled())
792		item->SetEnabled(false);
793
794	item = new AccountItem(B_TRANSLATE("\t\t�� E-mail filters"), account,
795		FILTER_ITEM);
796	fAccountsListView->AddItem(item);
797}
798
799
800void
801ConfigWindow::_RemoveAccount(BMailAccountSettings* account)
802{
803	_RemoveAccountFromListView(account);
804	fAccounts.RemoveItem(account);
805	fToDeleteAccounts.AddItem(account);
806}
807
808
809void
810ConfigWindow::_RemoveAccountFromListView(BMailAccountSettings* account)
811{
812	if (fLastSelectedAccount == account) {
813		_ReplaceConfigView(_BuildHowToView());
814		fLastSelectedAccount = NULL;
815	}
816
817	for (int i = fAccountsListView->CountItems(); i-- > 0;) {
818		AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i);
819		if (item->Account() == account) {
820			fAccountsListView->RemoveItem(i);
821			delete item;
822		}
823	}
824}
825
826
827void
828ConfigWindow::_AccountSelected(AccountItem* item)
829{
830	AccountUpdated(fLastSelectedAccount);
831
832	BMailAccountSettings* account = item->Account();
833	fLastSelectedAccount = account;
834
835	BView* view = NULL;
836	switch (item->Type()) {
837		case ACCOUNT_ITEM:
838			view = new AccountConfigView(account);
839			break;
840
841		case INBOUND_ITEM:
842			view = new ProtocolSettingsView(account->InboundAddOnRef(),
843				*account, account->InboundSettings());
844			break;
845
846		case OUTBOUND_ITEM:
847			view = new ProtocolSettingsView(account->OutboundAddOnRef(),
848				*account, account->OutboundSettings());
849			break;
850
851		case FILTER_ITEM:
852			view = new FiltersConfigView(*account);
853			break;
854	}
855
856	_ReplaceConfigView(view);
857}
858
859
860void
861ConfigWindow::_ReplaceConfigView(BView* view)
862{
863	while (BView* child = fConfigView->ChildAt(0)) {
864		fConfigView->RemoveChild(child);
865		delete child;
866	}
867
868	if (view != NULL)
869		fConfigView->AddChild(view);
870}
871