1 /* 2 * Copyright 2007-2011, 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 <Application.h> 19 #include <Catalog.h> 20 #include <ListView.h> 21 #include <ScrollView.h> 22 #include <StringView.h> 23 #include <Button.h> 24 #include <CheckBox.h> 25 #include <MenuField.h> 26 #include <TextControl.h> 27 #include <TextView.h> 28 #include <MenuItem.h> 29 #include <Screen.h> 30 #include <PopUpMenu.h> 31 #include <MenuBar.h> 32 #include <TabView.h> 33 #include <Box.h> 34 #include <Alert.h> 35 #include <Bitmap.h> 36 #include <Roster.h> 37 #include <Resources.h> 38 #include <Region.h> 39 40 #include <AppFileInfo.h> 41 #include <Entry.h> 42 #include <Directory.h> 43 #include <FindDirectory.h> 44 #include <Path.h> 45 46 #include <Catalog.h> 47 #include <Locale.h> 48 49 #include <MailDaemon.h> 50 #include <MailSettings.h> 51 52 #include "AutoConfigWindow.h" 53 #include "CenterContainer.h" 54 55 56 #undef B_TRANSLATE_CONTEXT 57 #define B_TRANSLATE_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 fConfigPanel(NULL) 90 { 91 } 92 93 94 void 95 AccountItem::Update(BView* owner, const BFont* font) 96 { 97 if (fType == ACCOUNT_ITEM) 98 font = be_bold_font; 99 100 BStringItem::Update(owner,font); 101 } 102 103 104 void 105 AccountItem::DrawItem(BView* owner, BRect rect, bool complete) 106 { 107 owner->PushState(); 108 if (fType == ACCOUNT_ITEM) 109 owner->SetFont(be_bold_font); 110 111 BStringItem::DrawItem(owner, rect, complete); 112 owner->PopState(); 113 } 114 115 116 void 117 AccountItem::SetConfigPanel(BView* panel) 118 { 119 fConfigPanel = panel; 120 } 121 122 123 BView* 124 AccountItem::ConfigPanel() 125 { 126 return fConfigPanel; 127 } 128 129 130 // #pragma mark - 131 132 133 class AccountsListView : public BListView { 134 public: 135 AccountsListView(BRect rect, BHandler* target) 136 : 137 BListView(rect, NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL), 138 fTarget(target) 139 { 140 } 141 142 void 143 KeyDown(const char *bytes, int32 numBytes) 144 { 145 if (numBytes != 1) 146 return; 147 148 if ((*bytes == B_DELETE) || (*bytes == B_BACKSPACE)) 149 Window()->PostMessage(kMsgRemoveAccount); 150 151 BListView::KeyDown(bytes,numBytes); 152 } 153 154 void 155 MouseDown(BPoint point) 156 { 157 BListView::MouseDown(point); 158 159 BPoint dummy; 160 uint32 buttons; 161 GetMouse(&dummy, &buttons); 162 if (buttons != B_SECONDARY_MOUSE_BUTTON) 163 return; 164 165 int32 index = IndexOf(point); 166 if (index < 0) 167 return; 168 169 BMessage message(kMsgAccountsRightClicked); 170 ConvertToScreen(&point); 171 message.AddPoint("point", point); 172 message.AddInt32("index", index); 173 BMessenger messenger(fTarget); 174 messenger.SendMessage(&message); 175 } 176 177 private: 178 BHandler* fTarget; 179 }; 180 181 182 class BitmapView : public BView { 183 public: 184 BitmapView(BBitmap *bitmap) 185 : 186 BView(bitmap->Bounds(), NULL, B_FOLLOW_NONE, B_WILL_DRAW) 187 { 188 fBitmap = bitmap; 189 190 SetDrawingMode(B_OP_ALPHA); 191 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 192 } 193 194 ~BitmapView() 195 { 196 delete fBitmap; 197 } 198 199 virtual void AttachedToWindow() 200 { 201 SetViewColor(Parent()->ViewColor()); 202 203 MoveTo((Parent()->Bounds().Width() - Bounds().Width()) / 2, 204 Frame().top); 205 } 206 207 virtual void Draw(BRect updateRect) 208 { 209 DrawBitmap(fBitmap, updateRect, updateRect); 210 } 211 212 private: 213 BBitmap *fBitmap; 214 }; 215 216 217 // #pragma mark - 218 219 220 ConfigWindow::ConfigWindow() 221 : 222 BWindow(BRect(100, 100, 600, 540), B_TRANSLATE_SYSTEM_NAME("E-mail"), 223 B_TITLED_WINDOW, 224 B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE), 225 fLastSelectedAccount(NULL), 226 fSaveSettings(false) 227 { 228 // create controls 229 BRect rect(Bounds()); 230 BView *top = new BView(rect, NULL, B_FOLLOW_ALL, 0); 231 top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 232 AddChild(top); 233 234 // determine font height 235 font_height fontHeight; 236 top->GetFontHeight(&fontHeight); 237 int32 height = (int32)(fontHeight.ascent + fontHeight.descent 238 + fontHeight.leading) + 5; 239 240 rect.InsetBy(10, 10); 241 rect.bottom -= 18 + height; 242 BTabView *tabView = new BTabView(rect, NULL); 243 244 BView *view; 245 rect = tabView->Bounds(); 246 rect.bottom -= tabView->TabHeight() + 4; 247 tabView->AddTab(view = new BView(rect, NULL, B_FOLLOW_ALL, 0)); 248 tabView->TabAt(0)->SetLabel(B_TRANSLATE("Accounts")); 249 view->SetViewColor(top->ViewColor()); 250 251 // accounts listview 252 253 rect = view->Bounds().InsetByCopy(10, 10); 254 rect.right = 190 - B_V_SCROLL_BAR_WIDTH; 255 rect.bottom -= height + 18; 256 fAccountsListView = new AccountsListView(rect, this); 257 view->AddChild(new BScrollView(NULL, fAccountsListView, B_FOLLOW_ALL, 0, 258 false, true)); 259 rect.right += B_V_SCROLL_BAR_WIDTH; 260 261 rect.left -= 2; 262 rect.top = rect.bottom + 10; 263 rect.bottom = rect.top + height; 264 BRect sizeRect = rect; 265 sizeRect.right = sizeRect.left + 30 + view->StringWidth( 266 B_TRANSLATE("Add")); 267 view->AddChild(new BButton(sizeRect, NULL, B_TRANSLATE("Add"), 268 new BMessage(kMsgAddAccount), B_FOLLOW_BOTTOM)); 269 270 sizeRect.left = sizeRect.right + 5; 271 sizeRect.right = sizeRect.left + 30 + view->StringWidth( 272 B_TRANSLATE("Remove")); 273 view->AddChild(fRemoveButton = new BButton( 274 sizeRect, NULL, B_TRANSLATE("Remove"), 275 new BMessage(kMsgRemoveAccount), B_FOLLOW_BOTTOM)); 276 277 // accounts config view 278 rect = view->Bounds(); 279 rect.left = fAccountsListView->Frame().right + B_V_SCROLL_BAR_WIDTH + 16; 280 rect.right -= 10; 281 fConfigView = new CenterContainer(rect); 282 view->AddChild(fConfigView); 283 284 _MakeHowToView(); 285 286 // general settings 287 288 rect = tabView->ContainerView()->Bounds(); 289 tabView->AddTab(view = new CenterContainer(rect)); 290 tabView->TabAt(1)->SetLabel(B_TRANSLATE("Settings")); 291 292 rect = view->Bounds().InsetByCopy(10, 10); 293 rect.bottom = rect.top + height * 5 + 15; 294 BBox *box = new BBox(rect); 295 box->SetLabel(B_TRANSLATE("Mail checking")); 296 view->AddChild(box); 297 298 rect = box->Bounds().InsetByCopy(10, 10); 299 rect.top += 7; 300 rect.bottom = rect.top + height; 301 BRect tile = rect.OffsetByCopy(0, 1); 302 int32 labelWidth = (int32)view->StringWidth(B_TRANSLATE("Check every")) + 6; 303 tile.right = 80 + labelWidth; 304 fIntervalControl = new BTextControl(tile, "time", 305 B_TRANSLATE("Check every"), NULL, NULL); 306 fIntervalControl->SetDivider(labelWidth); 307 box->AddChild(fIntervalControl); 308 309 BPopUpMenu* frequencyPopUp = new BPopUpMenu(B_EMPTY_STRING); 310 const char* frequencyStrings[] = { 311 B_TRANSLATE("never"), 312 B_TRANSLATE("minutes"), 313 B_TRANSLATE("hours"), 314 B_TRANSLATE("days")}; 315 316 for (int32 i = 0; i < 4; i++) { 317 BMenuItem* item = new BMenuItem(frequencyStrings[i], 318 new BMessage(kMsgIntervalUnitChanged)); 319 frequencyPopUp->AddItem(item); 320 } 321 tile.left = tile.right + 5; 322 tile.right = rect.right; 323 tile.OffsetBy(0,-1); 324 fIntervalUnitField = new BMenuField(tile, "frequency", B_EMPTY_STRING, 325 frequencyPopUp); 326 fIntervalUnitField->SetDivider(0.0); 327 box->AddChild(fIntervalUnitField); 328 329 rect.OffsetBy(0,height + 9); 330 rect.bottom -= 2; 331 fPPPActiveCheckBox = new BCheckBox(rect, "ppp active", 332 B_TRANSLATE("Only when dial-up is connected"), NULL); 333 box->AddChild(fPPPActiveCheckBox); 334 335 rect.OffsetBy(0,height + 9); 336 rect.bottom -= 2; 337 fPPPActiveSendCheckBox = new BCheckBox(rect, "ppp activesend", 338 B_TRANSLATE("Schedule outgoing mail when dial-up is disconnected"), 339 NULL); 340 box->AddChild(fPPPActiveSendCheckBox); 341 342 // Miscellaneous settings box 343 344 rect = box->Frame(); rect.bottom = rect.top + 3 * height + 33; 345 box = new BBox(rect); 346 box->SetLabel(B_TRANSLATE("Miscellaneous")); 347 view->AddChild(box); 348 349 BPopUpMenu *statusPopUp = new BPopUpMenu(B_EMPTY_STRING); 350 const char *statusModes[] = { 351 B_TRANSLATE("Never"), 352 B_TRANSLATE("While sending"), 353 B_TRANSLATE("While sending and receiving"), 354 B_TRANSLATE("Always")}; 355 for (int32 i = 0; i < 4; i++) { 356 BMessage* msg = new BMessage(kMsgShowStatusWindowChanged); 357 BMenuItem* item = new BMenuItem(statusModes[i], msg); 358 statusPopUp->AddItem(item); 359 msg->AddInt32("ShowStatusWindow", i); 360 } 361 rect = box->Bounds().InsetByCopy(10, 10); 362 rect.top += 7; 363 rect.bottom = rect.top + height + 5; 364 labelWidth = (int32)view->StringWidth( 365 B_TRANSLATE("Show connection status window:")) + 8; 366 fStatusModeField = new BMenuField(rect, "show status", 367 B_TRANSLATE("Show connection status window:"), statusPopUp); 368 fStatusModeField->SetDivider(labelWidth); 369 box->AddChild(fStatusModeField); 370 371 rect = fStatusModeField->Frame();; 372 rect.OffsetBy(0, rect.Height() + 10); 373 BMessage* msg = new BMessage(B_REFS_RECEIVED); 374 BButton *button = new BButton(rect, B_EMPTY_STRING, 375 B_TRANSLATE("Edit mailbox menu…"), msg); 376 button->ResizeToPreferred(); 377 box->AddChild(button); 378 button->SetTarget(BMessenger("application/x-vnd.Be-TRAK")); 379 380 BPath path; 381 find_directory(B_USER_SETTINGS_DIRECTORY, &path); 382 path.Append("Mail/Menu Links"); 383 BEntry entry(path.Path()); 384 if (entry.InitCheck() == B_OK && entry.Exists()) { 385 entry_ref ref; 386 entry.GetRef(&ref); 387 msg->AddRef("refs", &ref); 388 } 389 else 390 button->SetEnabled(false); 391 392 rect = button->Frame(); 393 rect.OffsetBy(rect.Width() + 30,0); 394 fAutoStartCheckBox = new BCheckBox(rect, "start daemon", 395 B_TRANSLATE("Start mail services on startup"), NULL); 396 fAutoStartCheckBox->ResizeToPreferred(); 397 box->AddChild(fAutoStartCheckBox); 398 399 // save/revert buttons 400 401 top->AddChild(tabView); 402 403 rect = tabView->Frame(); 404 rect.top = rect.bottom + 10; 405 rect.bottom = rect.top + height + 5; 406 BButton *saveButton = new BButton(rect, "apply", B_TRANSLATE("Apply"), 407 new BMessage(kMsgSaveSettings)); 408 float w,h; 409 saveButton->GetPreferredSize(&w, &h); 410 saveButton->ResizeTo(w, h); 411 saveButton->MoveTo(rect.right - w, rect.top); 412 top->AddChild(saveButton); 413 414 BButton *revertButton = new BButton(rect, "revert", B_TRANSLATE("Revert"), 415 new BMessage(kMsgRevertSettings)); 416 revertButton->GetPreferredSize(&w, &h); 417 revertButton->ResizeTo(w,h); 418 revertButton->MoveTo(saveButton->Frame().left - 10 - w, rect.top); 419 top->AddChild(revertButton); 420 421 _LoadSettings(); 422 // this will also move our window to the stored position 423 424 fAccountsListView->SetSelectionMessage(new BMessage(kMsgAccountSelected)); 425 fAccountsListView->MakeFocus(true); 426 } 427 428 429 ConfigWindow::~ConfigWindow() 430 { 431 while (fAccounts.CountItems() > 0) 432 _RemoveAccount(fAccounts.ItemAt(0)); 433 for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) 434 delete fToDeleteAccounts.ItemAt(i); 435 } 436 437 438 void 439 ConfigWindow::_MakeHowToView() 440 { 441 app_info info; 442 if (be_app->GetAppInfo(&info) == B_OK) { 443 BFile appFile(&info.ref, B_READ_ONLY); 444 BAppFileInfo appFileInfo(&appFile); 445 if (appFileInfo.InitCheck() == B_OK) { 446 BBitmap *bitmap = new (nothrow) BBitmap(BRect(0, 0, 63, 63), 447 B_RGBA32); 448 if (appFileInfo.GetIcon(bitmap, B_LARGE_ICON) == B_OK) { 449 fConfigView->AddChild(new BitmapView(bitmap)); 450 } else 451 delete bitmap; 452 } 453 } 454 455 BRect rect = fConfigView->Bounds(); 456 BTextView *text = new BTextView(rect, NULL, rect, B_FOLLOW_NONE, 457 B_WILL_DRAW); 458 text->SetViewColor(fConfigView->Parent()->ViewColor()); 459 text->SetAlignment(B_ALIGN_CENTER); 460 text->SetText(B_TRANSLATE( 461 "\n\nCreate a new account with the Add button.\n\n" 462 "Remove an account with the Remove button on the selected item.\n\n" 463 "Select an item in the list to change its settings.")); 464 rect = text->Bounds(); 465 text->ResizeTo(rect.Width(), text->TextHeight(0, 42)); 466 text->SetTextRect(rect); 467 468 text->MakeEditable(false); 469 text->MakeSelectable(false); 470 471 fConfigView->AddChild(text); 472 473 fConfigView->Layout(); 474 } 475 476 477 void 478 ConfigWindow::_LoadSettings() 479 { 480 // load accounts 481 for (int i = 0; i < fAccounts.CountItems(); i++) 482 delete fAccounts.ItemAt(i); 483 fAccounts.MakeEmpty(); 484 485 _LoadAccounts(); 486 487 // load in general settings 488 BMailSettings settings; 489 status_t status = _SetToGeneralSettings(&settings); 490 if (status == B_OK) { 491 // move own window 492 MoveTo(settings.ConfigWindowFrame().LeftTop()); 493 } else { 494 fprintf(stderr, B_TRANSLATE("Error retrieving general settings: %s\n"), 495 strerror(status)); 496 } 497 498 BScreen screen(this); 499 BRect screenFrame(screen.Frame().InsetByCopy(0, 5)); 500 if (!screenFrame.Contains(Frame().LeftTop()) 501 || !screenFrame.Contains(Frame().RightBottom())) 502 status = B_ERROR; 503 504 if (status != B_OK) { 505 // center window on screen 506 MoveTo((screenFrame.Width() - Frame().Width()) / 2, 507 (screenFrame.Height() - Frame().Height()) / 2); 508 } 509 } 510 511 512 void 513 ConfigWindow::_LoadAccounts() 514 { 515 BMailAccounts accounts; 516 for (int32 i = 0; i < accounts.CountAccounts(); i++) 517 fAccounts.AddItem(new BMailAccountSettings(*accounts.AccountAt(i))); 518 519 for (int i = 0; i < fAccounts.CountItems(); i++) { 520 BMailAccountSettings* account = fAccounts.ItemAt(i); 521 _AddAccountToView(account); 522 } 523 } 524 525 526 void 527 ConfigWindow::_SaveSettings() 528 { 529 // remove config views (trigger view archive) 530 fConfigView->DeleteChildren(); 531 532 // collect changed accounts 533 BMessage changedAccounts(kMsgAccountsChanged); 534 for (int32 i = 0; i < fAccounts.CountItems(); i++) { 535 BMailAccountSettings* account = fAccounts.ItemAt(i); 536 if (account && account->HasBeenModified()) 537 changedAccounts.AddInt32("account", account->AccountID()); 538 } 539 for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) { 540 BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i); 541 changedAccounts.AddInt32("account", account->AccountID()); 542 } 543 544 // cleanup account directory 545 for (int32 i = 0; i < fToDeleteAccounts.CountItems(); i++) { 546 BMailAccountSettings* account = fToDeleteAccounts.ItemAt(i); 547 BEntry entry(account->AccountFile()); 548 entry.Remove(); 549 delete account; 550 } 551 fToDeleteAccounts.MakeEmpty(); 552 553 /*** save general settings ***/ 554 555 // figure out time interval 556 float interval; 557 sscanf(fIntervalControl->Text(),"%f",&interval); 558 float multiplier = 0; 559 switch (fIntervalUnitField->Menu()->IndexOf( 560 fIntervalUnitField->Menu()->FindMarked())) { 561 case 1: // minutes 562 multiplier = 60; 563 break; 564 case 2: // hours 565 multiplier = 60 * 60; 566 break; 567 case 3: // days 568 multiplier = 24 * 60 * 60; 569 break; 570 } 571 time_t time = (time_t)(multiplier * interval); 572 573 // apply and save general settings 574 BMailSettings settings; 575 if (fSaveSettings) { 576 settings.SetAutoCheckInterval(time * 1e6); 577 settings.SetCheckOnlyIfPPPUp(fPPPActiveCheckBox->Value() 578 == B_CONTROL_ON); 579 settings.SetSendOnlyIfPPPUp(fPPPActiveSendCheckBox->Value() 580 == B_CONTROL_ON); 581 settings.SetDaemonAutoStarts(fAutoStartCheckBox->Value() 582 == B_CONTROL_ON); 583 584 // status mode (alway, fetching/retrieving, ...) 585 int32 index = fStatusModeField->Menu()->IndexOf( 586 fStatusModeField->Menu()->FindMarked()); 587 settings.SetShowStatusWindow(index); 588 589 } else { 590 // restore status window look 591 settings.SetStatusWindowLook(settings.StatusWindowLook()); 592 } 593 594 settings.SetConfigWindowFrame(Frame()); 595 settings.Save(); 596 597 /*** save accounts ***/ 598 599 if (fSaveSettings) { 600 for (int i = 0; i < fAccounts.CountItems(); i++) 601 fAccounts.ItemAt(i)->Save(); 602 } 603 604 BMessenger messenger("application/x-vnd.Be-POST"); 605 if (messenger.IsValid()) { 606 // server should reload general settings 607 messenger.SendMessage(kMsgSettingsUpdated); 608 // notify server about changed accounts 609 messenger.SendMessage(&changedAccounts); 610 } 611 612 // start the mail_daemon if auto start was selected 613 if (fSaveSettings && fAutoStartCheckBox->Value() == B_CONTROL_ON 614 && !be_roster->IsRunning("application/x-vnd.Be-POST")) 615 { 616 be_roster->Launch("application/x-vnd.Be-POST"); 617 } 618 } 619 620 621 bool 622 ConfigWindow::QuitRequested() 623 { 624 _SaveSettings(); 625 626 be_app->PostMessage(B_QUIT_REQUESTED); 627 return true; 628 } 629 630 631 void 632 ConfigWindow::MessageReceived(BMessage *msg) 633 { 634 BRect autoConfigRect(0, 0, 400, 300); 635 BRect frame; 636 637 AutoConfigWindow *autoConfigWindow = NULL; 638 switch (msg->what) { 639 case kMsgAccountsRightClicked: 640 { 641 BPoint point; 642 msg->FindPoint("point", &point); 643 int32 index = msg->FindInt32("index"); 644 AccountItem* clickedItem = dynamic_cast<AccountItem*>( 645 fAccountsListView->ItemAt(index)); 646 if (clickedItem == NULL || clickedItem->GetType() != ACCOUNT_ITEM) 647 break; 648 649 BPopUpMenu rightClickMenu("accounts", false, false); 650 651 BMenuItem* inMenuItem = new BMenuItem("Incoming", NULL); 652 BMenuItem* outMenuItem = new BMenuItem("Outgoing", NULL); 653 rightClickMenu.AddItem(inMenuItem); 654 rightClickMenu.AddItem(outMenuItem); 655 656 BMailAccountSettings* settings = clickedItem->GetAccount(); 657 if (settings->IsInboundEnabled()) 658 inMenuItem->SetMarked(true); 659 if (settings->IsOutboundEnabled()) 660 outMenuItem->SetMarked(true); 661 662 BMenuItem* selectedItem = rightClickMenu.Go(point); 663 if (selectedItem == NULL) 664 break; 665 if (selectedItem == inMenuItem) { 666 AccountItem* item = dynamic_cast<AccountItem*>( 667 fAccountsListView->ItemAt(index + 1)); 668 if (item == NULL) 669 break; 670 if (settings->IsInboundEnabled()) { 671 settings->SetInboundEnabled(false); 672 item->SetEnabled(false); 673 } else { 674 settings->SetInboundEnabled(true); 675 item->SetEnabled(true); 676 } 677 } else { 678 AccountItem* item = dynamic_cast<AccountItem*>( 679 fAccountsListView->ItemAt(index + 2)); 680 if (item == NULL) 681 break; 682 if (settings->IsOutboundEnabled()) { 683 settings->SetOutboundEnabled(false); 684 item->SetEnabled(false); 685 } else { 686 settings->SetOutboundEnabled(true); 687 item->SetEnabled(true); 688 } 689 } 690 } 691 692 case kMsgAccountSelected: 693 { 694 int32 index; 695 if (msg->FindInt32("index", &index) != B_OK || index < 0) { 696 // deselect current item 697 fConfigView->DeleteChildren(); 698 _MakeHowToView(); 699 break; 700 } 701 AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(index); 702 if (item) 703 _AccountSelected(item); 704 break; 705 } 706 707 case kMsgAddAccount: 708 { 709 frame = Frame(); 710 autoConfigRect.OffsetTo( 711 frame.left + (frame.Width() - autoConfigRect.Width()) / 2, 712 frame.top + (frame.Width() - autoConfigRect.Height()) / 2); 713 autoConfigWindow = new AutoConfigWindow(autoConfigRect, this); 714 autoConfigWindow->Show(); 715 break; 716 } 717 718 case kMsgRemoveAccount: 719 { 720 int32 index = fAccountsListView->CurrentSelection(); 721 if (index >= 0) { 722 AccountItem *item = (AccountItem *)fAccountsListView->ItemAt( 723 index); 724 if (item != NULL) { 725 _RemoveAccount(item->GetAccount()); 726 _MakeHowToView(); 727 } 728 } 729 break; 730 } 731 732 case kMsgIntervalUnitChanged: 733 { 734 int32 index; 735 if (msg->FindInt32("index",&index) == B_OK) 736 fIntervalControl->SetEnabled(index != 0); 737 break; 738 } 739 740 case kMsgShowStatusWindowChanged: 741 { 742 // the status window stuff is the only "live" setting 743 BMessenger messenger("application/x-vnd.Be-POST"); 744 if (messenger.IsValid()) 745 messenger.SendMessage(msg); 746 break; 747 } 748 749 case kMsgRevertSettings: 750 _RevertToLastSettings(); 751 break; 752 753 case kMsgSaveSettings: 754 fSaveSettings = true; 755 _SaveSettings(); 756 AccountUpdated(fLastSelectedAccount); 757 _MakeHowToView(); 758 fAccountsListView->DeselectAll(); 759 break; 760 761 default: 762 BWindow::MessageReceived(msg); 763 break; 764 } 765 } 766 767 768 BMailAccountSettings* 769 ConfigWindow::AddAccount() 770 { 771 BMailAccountSettings* account = new BMailAccountSettings; 772 if (!account) 773 return NULL; 774 fAccounts.AddItem(account); 775 _AddAccountToView(account); 776 return account; 777 } 778 779 780 void 781 ConfigWindow::AccountUpdated(BMailAccountSettings* account) 782 { 783 if (account == NULL) 784 return; 785 786 for (int i = 0; i < fAccountsListView->CountItems(); i++) { 787 AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i); 788 if (item->GetAccount() == account) { 789 if (item->GetType() == ACCOUNT_ITEM) { 790 item->SetText(account->Name()); 791 fAccountsListView->Invalidate(); 792 } 793 } 794 } 795 } 796 797 798 status_t 799 ConfigWindow::_SetToGeneralSettings(BMailSettings *settings) 800 { 801 if (!settings) 802 return B_BAD_VALUE; 803 804 status_t status = settings->InitCheck(); 805 if (status != B_OK) 806 return status; 807 808 // retrieval frequency 809 810 time_t interval = time_t(settings->AutoCheckInterval() / 1e6L); 811 char text[25]; 812 text[0] = 0; 813 int timeIndex = 0; 814 if (interval >= 60) { 815 timeIndex = 1; 816 sprintf(text, "%ld", interval / (60)); 817 } 818 if (interval >= (60*60)) { 819 timeIndex = 2; 820 sprintf(text, "%ld", interval / (60*60)); 821 } 822 if (interval >= (60*60*24)) { 823 timeIndex = 3; 824 sprintf(text, "%ld", interval / (60*60*24)); 825 } 826 fIntervalControl->SetText(text); 827 828 if (BMenuItem *item = fIntervalUnitField->Menu()->ItemAt(timeIndex)) 829 item->SetMarked(true); 830 fIntervalControl->SetEnabled(timeIndex != 0); 831 832 fPPPActiveCheckBox->SetValue(settings->CheckOnlyIfPPPUp()); 833 fPPPActiveSendCheckBox->SetValue(settings->SendOnlyIfPPPUp()); 834 835 fAutoStartCheckBox->SetValue(settings->DaemonAutoStarts()); 836 837 int32 showStatusIndex = settings->ShowStatusWindow(); 838 BMenuItem *item = fStatusModeField->Menu()->ItemAt(showStatusIndex); 839 if (item) { 840 item->SetMarked(true); 841 // send live update to the server by simulating a menu click 842 BMessage msg(kMsgShowStatusWindowChanged); 843 msg.AddInt32("ShowStatusWindow", showStatusIndex); 844 PostMessage(&msg); 845 } 846 847 return B_OK; 848 } 849 850 851 void 852 ConfigWindow::_RevertToLastSettings() 853 { 854 // revert general settings 855 BMailSettings settings; 856 857 // restore status window look 858 settings.SetStatusWindowLook(settings.StatusWindowLook()); 859 860 status_t status = _SetToGeneralSettings(&settings); 861 if (status != B_OK) { 862 char text[256]; 863 sprintf(text, B_TRANSLATE( 864 "\nThe general settings couldn't be reverted.\n\n" 865 "Error retrieving general settings:\n%s\n"), 866 strerror(status)); 867 (new BAlert(B_TRANSLATE("Error"), text, B_TRANSLATE("OK"), NULL, NULL, 868 B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 869 } 870 871 // revert account data 872 873 if (fAccountsListView->CurrentSelection() != -1) 874 fConfigView->DeleteChildren(); 875 876 for (int32 i = 0; i < fAccounts.CountItems(); i++) { 877 BMailAccountSettings* account = fAccounts.ItemAt(i); 878 _RemoveAccountFromListView(account); 879 delete account; 880 } 881 fAccounts.MakeEmpty(); 882 _LoadAccounts(); 883 884 if (fConfigView->CountChildren() == 0) 885 _MakeHowToView(); 886 } 887 888 889 void 890 ConfigWindow::_AddAccountToView(BMailAccountSettings* account) 891 { 892 BString label; 893 label << account->Name(); 894 895 AccountItem* item; 896 item = new AccountItem(label, account, ACCOUNT_ITEM); 897 fAccountsListView->AddItem(item); 898 899 item = new AccountItem(B_TRANSLATE(" · Incoming"), account, INBOUND_ITEM); 900 fAccountsListView->AddItem(item); 901 if (!account->IsInboundEnabled()) 902 item->SetEnabled(false); 903 904 item = new AccountItem(B_TRANSLATE(" · Outgoing"), account, 905 OUTBOUND_ITEM); 906 fAccountsListView->AddItem(item); 907 if (!account->IsOutboundEnabled()) 908 item->SetEnabled(false); 909 910 item = new AccountItem(B_TRANSLATE(" · E-mail filters"), account, 911 FILTER_ITEM); 912 fAccountsListView->AddItem(item); 913 } 914 915 916 void 917 ConfigWindow::_RemoveAccount(BMailAccountSettings* account) 918 { 919 _RemoveAccountFromListView(account); 920 fAccounts.RemoveItem(account); 921 fToDeleteAccounts.AddItem(account); 922 } 923 924 925 void 926 ConfigWindow::_RemoveAccountFromListView(BMailAccountSettings* account) 927 { 928 for (int i = 0; i < fAccountsListView->CountItems(); i++) { 929 AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i); 930 if (item->GetAccount() == account) { 931 fAccountsListView->RemoveItem(i); 932 fConfigView->RemoveChild(item->ConfigPanel()); 933 delete item; 934 i--; 935 } 936 } 937 } 938 939 940 void 941 ConfigWindow::_AccountSelected(AccountItem* item) 942 { 943 AccountUpdated(fLastSelectedAccount); 944 945 BMailAccountSettings* account = item->GetAccount(); 946 fLastSelectedAccount = account; 947 948 fConfigView->Hide(); 949 fConfigView->DeleteChildren(); 950 951 BView* view = NULL; 952 switch (item->GetType()) { 953 case ACCOUNT_ITEM: 954 view = new AccountConfigView(fConfigView->Bounds(), account); 955 break; 956 957 case INBOUND_ITEM: 958 { 959 view = new InProtocolsConfigView(account); 960 break; 961 } 962 963 case OUTBOUND_ITEM: 964 { 965 view = new OutProtocolsConfigView(account); 966 break; 967 } 968 969 case FILTER_ITEM: 970 { 971 view = new FiltersConfigView(fConfigView->Bounds(), *account); 972 break; 973 } 974 } 975 if (view) { 976 item->SetConfigPanel(view); 977 fConfigView->AddChild(view); 978 } 979 980 fConfigView->Layout(); 981 fConfigView->Show(); 982 } 983