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_COMMENT("never", "mail checking frequency"), 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_COMMENT("Never", "show status window"), 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(B_TRANSLATE("Incoming"), 652 NULL); 653 BMenuItem* outMenuItem = new BMenuItem(B_TRANSLATE("Outgoing"), 654 NULL); 655 rightClickMenu.AddItem(inMenuItem); 656 rightClickMenu.AddItem(outMenuItem); 657 658 BMailAccountSettings* settings = clickedItem->GetAccount(); 659 if (settings->IsInboundEnabled()) 660 inMenuItem->SetMarked(true); 661 if (settings->IsOutboundEnabled()) 662 outMenuItem->SetMarked(true); 663 664 BMenuItem* selectedItem = rightClickMenu.Go(point); 665 if (selectedItem == NULL) 666 break; 667 if (selectedItem == inMenuItem) { 668 AccountItem* item = dynamic_cast<AccountItem*>( 669 fAccountsListView->ItemAt(index + 1)); 670 if (item == NULL) 671 break; 672 if (settings->IsInboundEnabled()) { 673 settings->SetInboundEnabled(false); 674 item->SetEnabled(false); 675 } else { 676 settings->SetInboundEnabled(true); 677 item->SetEnabled(true); 678 } 679 } else { 680 AccountItem* item = dynamic_cast<AccountItem*>( 681 fAccountsListView->ItemAt(index + 2)); 682 if (item == NULL) 683 break; 684 if (settings->IsOutboundEnabled()) { 685 settings->SetOutboundEnabled(false); 686 item->SetEnabled(false); 687 } else { 688 settings->SetOutboundEnabled(true); 689 item->SetEnabled(true); 690 } 691 } 692 } 693 694 case kMsgAccountSelected: 695 { 696 int32 index; 697 if (msg->FindInt32("index", &index) != B_OK || index < 0) { 698 // deselect current item 699 fConfigView->DeleteChildren(); 700 _MakeHowToView(); 701 break; 702 } 703 AccountItem *item = (AccountItem *)fAccountsListView->ItemAt(index); 704 if (item) 705 _AccountSelected(item); 706 break; 707 } 708 709 case kMsgAddAccount: 710 { 711 frame = Frame(); 712 autoConfigRect.OffsetTo( 713 frame.left + (frame.Width() - autoConfigRect.Width()) / 2, 714 frame.top + (frame.Width() - autoConfigRect.Height()) / 2); 715 autoConfigWindow = new AutoConfigWindow(autoConfigRect, this); 716 autoConfigWindow->Show(); 717 break; 718 } 719 720 case kMsgRemoveAccount: 721 { 722 int32 index = fAccountsListView->CurrentSelection(); 723 if (index >= 0) { 724 AccountItem *item = (AccountItem *)fAccountsListView->ItemAt( 725 index); 726 if (item != NULL) { 727 _RemoveAccount(item->GetAccount()); 728 _MakeHowToView(); 729 } 730 } 731 break; 732 } 733 734 case kMsgIntervalUnitChanged: 735 { 736 int32 index; 737 if (msg->FindInt32("index",&index) == B_OK) 738 fIntervalControl->SetEnabled(index != 0); 739 break; 740 } 741 742 case kMsgShowStatusWindowChanged: 743 { 744 // the status window stuff is the only "live" setting 745 BMessenger messenger("application/x-vnd.Be-POST"); 746 if (messenger.IsValid()) 747 messenger.SendMessage(msg); 748 break; 749 } 750 751 case kMsgRevertSettings: 752 _RevertToLastSettings(); 753 break; 754 755 case kMsgSaveSettings: 756 fSaveSettings = true; 757 _SaveSettings(); 758 AccountUpdated(fLastSelectedAccount); 759 _MakeHowToView(); 760 fAccountsListView->DeselectAll(); 761 break; 762 763 default: 764 BWindow::MessageReceived(msg); 765 break; 766 } 767 } 768 769 770 BMailAccountSettings* 771 ConfigWindow::AddAccount() 772 { 773 BMailAccountSettings* account = new BMailAccountSettings; 774 if (!account) 775 return NULL; 776 fAccounts.AddItem(account); 777 _AddAccountToView(account); 778 return account; 779 } 780 781 782 void 783 ConfigWindow::AccountUpdated(BMailAccountSettings* account) 784 { 785 if (account == NULL) 786 return; 787 788 for (int i = 0; i < fAccountsListView->CountItems(); i++) { 789 AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i); 790 if (item->GetAccount() == account) { 791 if (item->GetType() == ACCOUNT_ITEM) { 792 item->SetText(account->Name()); 793 fAccountsListView->Invalidate(); 794 } 795 } 796 } 797 } 798 799 800 status_t 801 ConfigWindow::_SetToGeneralSettings(BMailSettings *settings) 802 { 803 if (!settings) 804 return B_BAD_VALUE; 805 806 status_t status = settings->InitCheck(); 807 if (status != B_OK) 808 return status; 809 810 // retrieval frequency 811 812 time_t interval = time_t(settings->AutoCheckInterval() / 1e6L); 813 char text[25]; 814 text[0] = 0; 815 int timeIndex = 0; 816 if (interval >= 60) { 817 timeIndex = 1; 818 sprintf(text, "%ld", interval / (60)); 819 } 820 if (interval >= (60*60)) { 821 timeIndex = 2; 822 sprintf(text, "%ld", interval / (60*60)); 823 } 824 if (interval >= (60*60*24)) { 825 timeIndex = 3; 826 sprintf(text, "%ld", interval / (60*60*24)); 827 } 828 fIntervalControl->SetText(text); 829 830 if (BMenuItem *item = fIntervalUnitField->Menu()->ItemAt(timeIndex)) 831 item->SetMarked(true); 832 fIntervalControl->SetEnabled(timeIndex != 0); 833 834 fPPPActiveCheckBox->SetValue(settings->CheckOnlyIfPPPUp()); 835 fPPPActiveSendCheckBox->SetValue(settings->SendOnlyIfPPPUp()); 836 837 fAutoStartCheckBox->SetValue(settings->DaemonAutoStarts()); 838 839 int32 showStatusIndex = settings->ShowStatusWindow(); 840 BMenuItem *item = fStatusModeField->Menu()->ItemAt(showStatusIndex); 841 if (item) { 842 item->SetMarked(true); 843 // send live update to the server by simulating a menu click 844 BMessage msg(kMsgShowStatusWindowChanged); 845 msg.AddInt32("ShowStatusWindow", showStatusIndex); 846 PostMessage(&msg); 847 } 848 849 return B_OK; 850 } 851 852 853 void 854 ConfigWindow::_RevertToLastSettings() 855 { 856 // revert general settings 857 BMailSettings settings; 858 859 // restore status window look 860 settings.SetStatusWindowLook(settings.StatusWindowLook()); 861 862 status_t status = _SetToGeneralSettings(&settings); 863 if (status != B_OK) { 864 char text[256]; 865 sprintf(text, B_TRANSLATE( 866 "\nThe general settings couldn't be reverted.\n\n" 867 "Error retrieving general settings:\n%s\n"), 868 strerror(status)); 869 (new BAlert(B_TRANSLATE("Error"), text, B_TRANSLATE("OK"), NULL, NULL, 870 B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 871 } 872 873 // revert account data 874 875 if (fAccountsListView->CurrentSelection() != -1) 876 fConfigView->DeleteChildren(); 877 878 for (int32 i = 0; i < fAccounts.CountItems(); i++) { 879 BMailAccountSettings* account = fAccounts.ItemAt(i); 880 _RemoveAccountFromListView(account); 881 delete account; 882 } 883 fAccounts.MakeEmpty(); 884 _LoadAccounts(); 885 886 if (fConfigView->CountChildren() == 0) 887 _MakeHowToView(); 888 } 889 890 891 void 892 ConfigWindow::_AddAccountToView(BMailAccountSettings* account) 893 { 894 BString label; 895 label << account->Name(); 896 897 AccountItem* item; 898 item = new AccountItem(label, account, ACCOUNT_ITEM); 899 fAccountsListView->AddItem(item); 900 901 item = new AccountItem(B_TRANSLATE("\t\t· Incoming"), account, INBOUND_ITEM); 902 fAccountsListView->AddItem(item); 903 if (!account->IsInboundEnabled()) 904 item->SetEnabled(false); 905 906 item = new AccountItem(B_TRANSLATE("\t\t· Outgoing"), account, 907 OUTBOUND_ITEM); 908 fAccountsListView->AddItem(item); 909 if (!account->IsOutboundEnabled()) 910 item->SetEnabled(false); 911 912 item = new AccountItem(B_TRANSLATE("\t\t· E-mail filters"), account, 913 FILTER_ITEM); 914 fAccountsListView->AddItem(item); 915 } 916 917 918 void 919 ConfigWindow::_RemoveAccount(BMailAccountSettings* account) 920 { 921 _RemoveAccountFromListView(account); 922 fAccounts.RemoveItem(account); 923 fToDeleteAccounts.AddItem(account); 924 } 925 926 927 void 928 ConfigWindow::_RemoveAccountFromListView(BMailAccountSettings* account) 929 { 930 for (int i = 0; i < fAccountsListView->CountItems(); i++) { 931 AccountItem* item = (AccountItem*)fAccountsListView->ItemAt(i); 932 if (item->GetAccount() == account) { 933 fAccountsListView->RemoveItem(i); 934 fConfigView->RemoveChild(item->ConfigPanel()); 935 delete item; 936 i--; 937 } 938 } 939 } 940 941 942 void 943 ConfigWindow::_AccountSelected(AccountItem* item) 944 { 945 AccountUpdated(fLastSelectedAccount); 946 947 BMailAccountSettings* account = item->GetAccount(); 948 fLastSelectedAccount = account; 949 950 fConfigView->Hide(); 951 fConfigView->DeleteChildren(); 952 953 BView* view = NULL; 954 switch (item->GetType()) { 955 case ACCOUNT_ITEM: 956 view = new AccountConfigView(fConfigView->Bounds(), account); 957 break; 958 959 case INBOUND_ITEM: 960 { 961 view = new InProtocolsConfigView(account); 962 break; 963 } 964 965 case OUTBOUND_ITEM: 966 { 967 view = new OutProtocolsConfigView(account); 968 break; 969 } 970 971 case FILTER_ITEM: 972 { 973 view = new FiltersConfigView(fConfigView->Bounds(), *account); 974 break; 975 } 976 } 977 if (view) { 978 item->SetConfigPanel(view); 979 fConfigView->AddChild(view); 980 } 981 982 fConfigView->Layout(); 983 fConfigView->Show(); 984 } 985