1 /* ConfigViews - config views for the account, protocols, and filters 2 ** 3 ** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. 4 */ 5 6 7 #include "ConfigViews.h" 8 #include "Account.h" 9 #include "CenterContainer.h" 10 11 #include <TextControl.h> 12 #include <ListView.h> 13 #include <ScrollView.h> 14 #include <PopUpMenu.h> 15 #include <MenuField.h> 16 #include <MenuItem.h> 17 #include <Button.h> 18 #include <Bitmap.h> 19 #include <Looper.h> 20 #include <Path.h> 21 #include <Alert.h> 22 #include <Entry.h> 23 #include <FindDirectory.h> 24 #include <Directory.h> 25 26 #include <Catalog.h> 27 #include <Locale.h> 28 29 #include <string.h> 30 31 #include <MailSettings.h> 32 33 #include <MDRLanguage.h> 34 35 36 #undef TR_CONTEXT 37 #define TR_CONTEXT "Config Views" 38 39 40 // AccountConfigView 41 const uint32 kMsgAccountTypeChanged = 'atch'; 42 const uint32 kMsgAccountNameChanged = 'anmc'; 43 44 // ProtocolsConfigView 45 const uint32 kMsgProtocolChanged = 'prch'; 46 47 // FiltersConfigView 48 const uint32 kMsgItemDragged = 'itdr'; 49 const uint32 kMsgFilterMoved = 'flmv'; 50 const uint32 kMsgChainSelected = 'chsl'; 51 const uint32 kMsgAddFilter = 'addf'; 52 const uint32 kMsgRemoveFilter = 'rmfi'; 53 const uint32 kMsgFilterSelected = 'fsel'; 54 55 56 AccountConfigView::AccountConfigView(BRect rect,Account *account) 57 : BBox(rect), 58 fAccount(account) 59 { 60 SetLabel(TR ("Account settings")); 61 62 rect = Bounds().InsetByCopy(8,8); 63 rect.top += 10; 64 CenterContainer *view = new CenterContainer(rect,false); 65 view->SetSpacing(5); 66 67 // determine font height 68 font_height fontHeight; 69 view->GetFontHeight(&fontHeight); 70 int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 5; 71 72 rect = view->Bounds(); 73 rect.bottom = height + 5; 74 75 float labelWidth = view->StringWidth(TR ("Account name:")) + 6; 76 77 view->AddChild(fNameControl = new BTextControl(rect,NULL,TR ("Account name:"),NULL,new BMessage(kMsgAccountNameChanged))); 78 fNameControl->SetDivider(labelWidth); 79 view->AddChild(fRealNameControl = new BTextControl(rect,NULL,TR ("Real name:"),NULL,NULL)); 80 fRealNameControl->SetDivider(labelWidth); 81 view->AddChild(fReturnAddressControl = new BTextControl(rect,NULL,TR ("Return address:"),NULL,NULL)); 82 fReturnAddressControl->SetDivider(labelWidth); 83 // control->TextView()->HideTyping(true); 84 85 BPopUpMenu *chainsPopUp = new BPopUpMenu(B_EMPTY_STRING); 86 const char *chainModes[] = { 87 TR ("Receive mail only"), 88 TR ("Send mail only"), 89 TR ("Send and receive mail")}; 90 BMenuItem *item; 91 for (int32 i = 0;i < 3;i++) 92 chainsPopUp->AddItem(item = new BMenuItem(chainModes[i],new BMessage(kMsgAccountTypeChanged))); 93 94 fTypeField = new BMenuField(rect,NULL,TR ("Account type:"),chainsPopUp); 95 fTypeField->SetDivider(labelWidth + 3); 96 view->AddChild(fTypeField); 97 98 float w,h; 99 view->GetPreferredSize(&w,&h); 100 ResizeTo(w + 15,h + 22); 101 view->ResizeTo(w,h); 102 103 AddChild(view); 104 } 105 106 107 void AccountConfigView::DetachedFromWindow() 108 { 109 fAccount->SetName(fNameControl->Text()); 110 fAccount->SetRealName(fRealNameControl->Text()); 111 fAccount->SetReturnAddress(fReturnAddressControl->Text()); 112 } 113 114 115 void AccountConfigView::AttachedToWindow() 116 { 117 UpdateViews(); 118 fNameControl->SetTarget(this); 119 fTypeField->Menu()->SetTargetForItems(this); 120 } 121 122 123 void AccountConfigView::MessageReceived(BMessage *msg) 124 { 125 switch (msg->what) 126 { 127 case kMsgAccountTypeChanged: 128 { 129 int32 index; 130 if (msg->FindInt32("index",&index) < B_OK) 131 break; 132 133 if (fAccount->Type() < 0) 134 { 135 fNameControl->SetEnabled(true); 136 fRealNameControl->SetEnabled(true); 137 fReturnAddressControl->SetEnabled(true); 138 } 139 fAccount->SetType(index); 140 UpdateViews(); 141 break; 142 } 143 case kMsgAccountNameChanged: 144 fAccount->SetName(fNameControl->Text()); 145 break; 146 147 default: 148 BView::MessageReceived(msg); 149 } 150 } 151 152 153 void AccountConfigView::UpdateViews() 154 { 155 if (!fAccount->Inbound() && !fAccount->Outbound()) 156 { 157 if (BMenuItem *item = fTypeField->Menu()->FindMarked()) 158 item->SetMarked(false); 159 fTypeField->Menu()->Superitem()->SetLabel(TR ("Select account type")); 160 161 fNameControl->SetEnabled(false); 162 fRealNameControl->SetEnabled(false); 163 fReturnAddressControl->SetEnabled(false); 164 return; 165 } 166 fNameControl->SetText(fAccount->Name()); 167 fRealNameControl->SetText(fAccount->RealName()); 168 fReturnAddressControl->SetText(fAccount->ReturnAddress()); 169 170 if (BMenuItem *item = fTypeField->Menu()->ItemAt(fAccount->Type())) 171 item->SetMarked(true); 172 } 173 174 175 //--------------------------------------------------------------------------------------- 176 // #pragma mark - 177 178 #include <stdio.h> 179 FilterConfigView::FilterConfigView(BMailChain *chain,int32 index,BMessage *msg,entry_ref *ref) 180 : BBox(BRect(0,0,100,100)), 181 fConfigView(NULL), 182 fChain(chain), 183 fIndex(index), 184 fMessage(msg), 185 fEntryRef(ref) 186 { 187 Load(msg,ref); 188 BPath addon(ref); 189 SetLabel(addon.Leaf()); 190 } 191 192 193 FilterConfigView::~FilterConfigView() 194 { 195 Remove(); 196 } 197 198 199 void FilterConfigView::Load(BMessage *msg,entry_ref *ref) 200 { 201 ResizeTo(264,30); 202 203 BView *(* instantiate_config)(BMessage *,BMessage *); 204 BPath addon(ref); 205 fImage = load_add_on(addon.Path()); 206 if (fImage < B_OK) 207 return; 208 209 if (get_image_symbol(fImage,"instantiate_config_panel",B_SYMBOL_TYPE_TEXT,(void **)&instantiate_config) < B_OK) 210 { 211 unload_add_on(fImage); 212 fImage = B_MISSING_SYMBOL; 213 return; 214 } 215 216 fConfigView = (*instantiate_config)(msg,fChain->MetaData()); 217 218 float w = fConfigView->Bounds().Width(); 219 float h = fConfigView->Bounds().Height(); 220 fConfigView->MoveTo(3,13); 221 ResizeTo(w + 6,h + 16); 222 AddChild(fConfigView); 223 } 224 225 226 void FilterConfigView::Remove(bool deleteMessage) 227 { 228 // remove config view here, because they may not be available 229 // anymore, if the add-on is unloaded 230 if (fConfigView && RemoveChild(fConfigView)) 231 { 232 delete fConfigView; 233 fConfigView = NULL; 234 } 235 unload_add_on(fImage); 236 237 if (deleteMessage) 238 { 239 delete fMessage; 240 fMessage = NULL; 241 } 242 delete fEntryRef; 243 fEntryRef = NULL; 244 } 245 246 247 status_t FilterConfigView::InitCheck() 248 { 249 return fImage; 250 } 251 252 253 void FilterConfigView::DetachedFromWindow() 254 { 255 if (fConfigView == NULL) 256 return; 257 258 if (fConfigView->Archive(fMessage) >= B_OK) 259 fChain->SetFilter(fIndex,*fMessage,*fEntryRef); 260 } 261 262 263 void FilterConfigView::AttachedToWindow() 264 { 265 } 266 267 268 //--------------------------------------------------------------------------------------- 269 // #pragma mark - 270 271 272 ProtocolsConfigView::ProtocolsConfigView(BMailChain *chain,int32 index,BMessage *msg,entry_ref *ref) 273 : FilterConfigView(chain,index,msg,ref) 274 { 275 BPopUpMenu *menu = new BPopUpMenu("Choose Protocol"); 276 277 for (int i = 0; i < 2; i++) { 278 BPath path; 279 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : B_BEOS_ADDONS_DIRECTORY,&path); 280 if (status != B_OK) 281 { 282 fImage = status; 283 return; 284 } 285 286 path.Append("mail_daemon"); 287 288 if (chain->ChainDirection() == inbound) 289 path.Append("inbound_protocols"); 290 else 291 path.Append("outbound_protocols"); 292 293 BDirectory dir(path.Path()); 294 entry_ref protocolRef; 295 while (dir.GetNextRef(&protocolRef) == B_OK) 296 { 297 char name[B_FILE_NAME_LENGTH]; 298 BEntry entry(&protocolRef); 299 entry.GetName(name); 300 301 BMenuItem *item; 302 BMessage *msg; 303 menu->AddItem(item = new BMenuItem(name,msg = new BMessage(kMsgProtocolChanged))); 304 msg->AddRef("protocol",&protocolRef); 305 306 if (*ref == protocolRef) 307 item->SetMarked(true); 308 } 309 } 310 311 fProtocolsMenuField = new BMenuField(BRect(0,0,200,40),NULL,NULL,menu); 312 fProtocolsMenuField->ResizeToPreferred(); 313 SetLabel(fProtocolsMenuField); 314 315 if (fConfigView) 316 { 317 fConfigView->MoveTo(3,21); 318 ResizeBy(0,8); 319 } 320 else 321 fImage = B_OK; 322 } 323 324 325 void ProtocolsConfigView::AttachedToWindow() 326 { 327 FilterConfigView::AttachedToWindow(); 328 fProtocolsMenuField->Menu()->SetTargetForItems(this); 329 } 330 331 332 void ProtocolsConfigView::MessageReceived(BMessage *msg) 333 { 334 switch (msg->what) 335 { 336 case kMsgProtocolChanged: 337 { 338 entry_ref ref; 339 if (msg->FindRef("protocol",&ref) < B_OK) 340 break; 341 342 DetachedFromWindow(); 343 Remove(false); 344 345 fEntryRef = new entry_ref(ref); 346 Load(fMessage,fEntryRef); 347 fChain->SetFilter(fIndex,*fMessage,*fEntryRef); 348 349 // resize view 350 if (LockLooperWithTimeout(1000000L) == B_OK) 351 { 352 if (fConfigView) 353 { 354 fConfigView->MoveTo(3,21); 355 ResizeBy(0,8); 356 } 357 UnlockLooper(); 358 359 if (CenterContainer *container = dynamic_cast<CenterContainer *>(Parent())) 360 container->Layout(); 361 } 362 break; 363 } 364 default: 365 BView::MessageReceived(msg); 366 break; 367 } 368 } 369 370 371 //--------------------------------------------------------------------------------------- 372 // #pragma mark - 373 374 #include <stdio.h> 375 class DragListView : public BListView 376 { 377 public: 378 DragListView(BRect frame,const char *name,list_view_type type = B_SINGLE_SELECTION_LIST, 379 uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,BMessage *itemMovedMsg = NULL) 380 : BListView(frame,name,type,resizingMode), 381 fDragging(false), 382 fItemMovedMessage(itemMovedMsg) 383 { 384 } 385 386 virtual bool InitiateDrag(BPoint point,int32 index,bool wasSelected) 387 { 388 BRect frame(ItemFrame(index)); 389 BBitmap *bitmap = new BBitmap(frame.OffsetToCopy(B_ORIGIN),B_RGBA32,true); 390 BView *view = new BView(bitmap->Bounds(),NULL,0,0); 391 bitmap->AddChild(view); 392 393 if (view->LockLooper()) 394 { 395 BListItem *item = ItemAt(index); 396 bool selected = item->IsSelected(); 397 398 view->SetLowColor(225,225,225,128); 399 view->FillRect(view->Bounds()); 400 401 if (selected) 402 item->Deselect(); 403 ItemAt(index)->DrawItem(view,view->Bounds(),true); 404 if (selected) 405 item->Select(); 406 407 view->UnlockLooper(); 408 } 409 fLastDragTarget = -1; 410 fDragIndex = index; 411 fDragging = true; 412 413 BMessage drag(kMsgItemDragged); 414 drag.AddInt32("index",index); 415 DragMessage(&drag,bitmap,B_OP_ALPHA,point - frame.LeftTop(),this); 416 417 return true; 418 } 419 420 void DrawDragTargetIndicator(int32 target) 421 { 422 PushState(); 423 SetDrawingMode(B_OP_INVERT); 424 425 bool last = false; 426 if (target >= CountItems()) 427 target = CountItems() - 1, last = true; 428 429 BRect frame = ItemFrame(target); 430 if (last) 431 frame.OffsetBy(0,frame.Height()); 432 frame.bottom = frame.top + 1; 433 434 FillRect(frame); 435 436 PopState(); 437 } 438 439 virtual void MouseMoved(BPoint point,uint32 transit,const BMessage *msg) 440 { 441 BListView::MouseMoved(point,transit,msg); 442 443 if ((transit != B_ENTERED_VIEW && transit != B_INSIDE_VIEW) || !fDragging) 444 return; 445 446 int32 target = IndexOf(point); 447 if (target == -1) 448 target = CountItems(); 449 450 // correct the target insertion index 451 if (target == fDragIndex || target == fDragIndex + 1) 452 target = -1; 453 454 if (target == fLastDragTarget) 455 return; 456 457 // remove old target indicator 458 if (fLastDragTarget != -1) 459 DrawDragTargetIndicator(fLastDragTarget); 460 461 // draw new one 462 fLastDragTarget = target; 463 if (target != -1) 464 DrawDragTargetIndicator(target); 465 } 466 467 virtual void MouseUp(BPoint point) 468 { 469 if (fDragging) 470 { 471 fDragging = false; 472 if (fLastDragTarget != -1) 473 DrawDragTargetIndicator(fLastDragTarget); 474 } 475 BListView::MouseUp(point); 476 } 477 478 virtual void MessageReceived(BMessage *msg) 479 { 480 switch(msg->what) 481 { 482 case kMsgItemDragged: 483 { 484 int32 source = msg->FindInt32("index"); 485 BPoint point = msg->FindPoint("_drop_point_"); 486 ConvertFromScreen(&point); 487 int32 to = IndexOf(point); 488 if (to > fDragIndex) 489 to--; 490 if (to == -1) 491 to = CountItems() - 1; 492 493 if (source != to) 494 { 495 MoveItem(source,to); 496 497 if (fItemMovedMessage != NULL) 498 { 499 BMessage msg(fItemMovedMessage->what); 500 msg.AddInt32("from",source); 501 msg.AddInt32("to",to); 502 Messenger().SendMessage(&msg); 503 } 504 } 505 break; 506 } 507 } 508 BListView::MessageReceived(msg); 509 } 510 511 private: 512 bool fDragging; 513 int32 fLastDragTarget,fDragIndex; 514 BMessage *fItemMovedMessage; 515 }; 516 517 518 void GetPrettyDescriptiveName(BPath &path, char *name, BMessage *msg = NULL) 519 { 520 strcpy(name, path.Leaf()); 521 522 image_id image = load_add_on(path.Path()); 523 if (image < B_OK) 524 return; 525 526 if (msg) 527 { 528 status_t (* descriptive_name)(BMessage *,char *); 529 if (get_image_symbol(image,"descriptive_name",B_SYMBOL_TYPE_TEXT,(void **)&descriptive_name) == B_OK) 530 (*descriptive_name)(msg,name); 531 } 532 unload_add_on(image); 533 } 534 535 536 // #pragma mark - 537 538 539 FiltersConfigView::FiltersConfigView(BRect rect,Account *account) 540 : BBox(rect), 541 fAccount(account), 542 fFilterView(NULL) 543 { 544 BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING); 545 546 BMenuItem *item; 547 BMessage *msg; 548 if ((fChain = fAccount->Inbound())) 549 { 550 menu->AddItem(item = new BMenuItem(TR ("Incoming mail filters"),msg = new BMessage(kMsgChainSelected))); 551 msg->AddPointer("chain",fChain); 552 item->SetMarked(true); 553 } 554 if (BMailChain *chain = fAccount->Outbound()) 555 { 556 menu->AddItem(item = new BMenuItem(TR ("Outgoing mail filters"),msg = new BMessage(kMsgChainSelected))); 557 msg->AddPointer("chain",chain); 558 if (fChain == NULL) 559 { 560 item->SetMarked(true); 561 fChain = chain; 562 } 563 } 564 565 fChainsField = new BMenuField(BRect(0,0,200,40),NULL,NULL,menu); 566 fChainsField->ResizeToPreferred(); 567 SetLabel(fChainsField); 568 569 // determine font height 570 font_height fontHeight; 571 fChainsField->GetFontHeight(&fontHeight); 572 int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 5; 573 574 rect = Bounds().InsetByCopy(10,10); 575 rect.top += 18; 576 rect.right -= B_V_SCROLL_BAR_WIDTH; 577 rect.bottom = rect.top + 4 * height + 2; 578 fListView = new DragListView(rect,NULL,B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL,new BMessage(kMsgFilterMoved)); 579 AddChild(new BScrollView(NULL,fListView,B_FOLLOW_ALL,0,false,true)); 580 rect.right += B_V_SCROLL_BAR_WIDTH; 581 582 // fListView->Select(gSettings.formats.IndexOf(format)); 583 fListView->SetSelectionMessage(new BMessage(kMsgFilterSelected)); 584 585 rect.top = rect.bottom + 8; rect.bottom = rect.top + height; 586 BRect sizeRect = rect; sizeRect.right = sizeRect.left + 30 + fChainsField->StringWidth(TR ("Add filter")); 587 588 menu = new BPopUpMenu(TR ("Add filter")); 589 menu->SetRadioMode(false); 590 591 fAddField = new BMenuField(rect,NULL,NULL,menu); 592 fAddField->ResizeToPreferred(); 593 AddChild(fAddField); 594 595 sizeRect.left = sizeRect.right + 5; sizeRect.right = sizeRect.left + 30 + fChainsField->StringWidth(TR ("Remove")); 596 sizeRect.top--; 597 AddChild(fRemoveButton = new BButton(sizeRect,NULL,TR ("Remove"),new BMessage(kMsgRemoveFilter),B_FOLLOW_BOTTOM)); 598 599 ResizeTo(Bounds().Width(),sizeRect.bottom + 10); 600 SetTo(fChain); 601 } 602 603 604 FiltersConfigView::~FiltersConfigView() 605 { 606 } 607 608 609 void FiltersConfigView::SelectFilter(int32 index) 610 { 611 if (Parent()) 612 Parent()->Hide(); 613 614 // remove old config view 615 if (fFilterView) 616 { 617 Parent()->RemoveChild(fFilterView); 618 619 // update the name in the list 620 BStringItem *item = (BStringItem *)fListView->ItemAt(fFilterView->fIndex - fFirst); 621 622 char name[B_FILE_NAME_LENGTH]; 623 BPath path(fFilterView->fEntryRef); 624 GetPrettyDescriptiveName(path, name, fFilterView->fMessage); 625 item->SetText(name); 626 627 delete fFilterView; 628 fFilterView = NULL; 629 } 630 631 if (index >= 0) 632 { 633 // add new config view 634 BMessage *msg = new BMessage(); 635 entry_ref *ref = new entry_ref(); 636 if (fChain->GetFilter(index + fFirst,msg,ref) >= B_OK && Parent()) 637 { 638 fFilterView = new FilterConfigView(fChain,index + fFirst,msg,ref); 639 if (fFilterView->InitCheck() >= B_OK) 640 Parent()->AddChild(fFilterView); 641 else 642 { 643 delete fFilterView; 644 fFilterView = NULL; 645 } 646 } 647 else 648 { 649 delete msg; 650 delete ref; 651 } 652 } 653 654 // re-layout the view containing the config view 655 if (CenterContainer *container = dynamic_cast<CenterContainer *>(Parent())) 656 container->Layout(); 657 658 if (Parent()) 659 Parent()->Show(); 660 } 661 662 663 void FiltersConfigView::SetTo(BMailChain *chain) 664 { 665 // remove the filter config view 666 SelectFilter(-1); 667 668 for (int32 i = fListView->CountItems();i-- > 0;) 669 { 670 BStringItem *item = (BStringItem *)fListView->RemoveItem(i); 671 delete item; 672 } 673 674 if (chain->ChainDirection() == inbound) 675 { 676 fFirst = 2; // skip protocol (e.g. POP3), and Parser 677 fLast = 2; // skip Notifier, and Folder 678 } 679 else 680 { 681 fFirst = 1; // skip Producer 682 fLast = 1; // skip protocol (e.g. SMTP) 683 } 684 int32 last = chain->CountFilters() - fLast; 685 for (int32 i = fFirst;i < last;i++) 686 { 687 BMessage msg; 688 entry_ref ref; 689 if (chain->GetFilter(i,&msg,&ref) == B_OK) 690 { 691 char name[B_FILE_NAME_LENGTH]; 692 BPath addon(&ref); 693 GetPrettyDescriptiveName(addon, name, &msg); 694 695 fListView->AddItem(new BStringItem(name)); 696 } 697 } 698 fChain = chain; 699 700 /*** search inbound/outbound filters ***/ 701 702 // remove old filter items 703 BMenu *menu = fAddField->Menu(); 704 for (int32 i = menu->CountItems();i-- > 0;) 705 { 706 BMenuItem *item = menu->RemoveItem(i); 707 delete item; 708 } 709 710 for (int i = 0; i < 2; i++) { 711 BPath path; 712 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : B_BEOS_ADDONS_DIRECTORY,&path); 713 if (status != B_OK) 714 return; 715 716 path.Append("mail_daemon"); 717 718 if (fChain->ChainDirection() == inbound) 719 path.Append("inbound_filters"); 720 else 721 path.Append("outbound_filters"); 722 723 BDirectory dir(path.Path()); 724 entry_ref ref; 725 while (dir.GetNextRef(&ref) == B_OK) 726 { 727 char name[B_FILE_NAME_LENGTH]; 728 BPath path(&ref); 729 GetPrettyDescriptiveName(path, name); 730 731 BMenuItem *item; 732 BMessage *msg; 733 menu->AddItem(item = new BMenuItem(name,msg = new BMessage(kMsgAddFilter))); 734 msg->AddRef("filter",&ref); 735 } 736 } 737 menu->SetTargetForItems(this); 738 } 739 740 741 void FiltersConfigView::AttachedToWindow() 742 { 743 fChainsField->Menu()->SetTargetForItems(this); 744 fListView->SetTarget(this); 745 fAddField->Menu()->SetTargetForItems(this); 746 fRemoveButton->SetTarget(this); 747 } 748 749 750 void FiltersConfigView::MessageReceived(BMessage *msg) 751 { 752 switch (msg->what) 753 { 754 case kMsgChainSelected: 755 { 756 BMailChain *chain; 757 if (msg->FindPointer("chain",(void **)&chain) < B_OK) 758 break; 759 760 SetTo(chain); 761 break; 762 } 763 case kMsgAddFilter: 764 { 765 entry_ref ref; 766 if (msg->FindRef("filter",&ref) < B_OK) 767 break; 768 769 BMessage msg; 770 if (fChain->AddFilter(fChain->CountFilters() - fLast, msg, ref) >= B_OK) 771 { 772 char name[B_FILE_NAME_LENGTH]; 773 BPath path(&ref); 774 GetPrettyDescriptiveName(path, name, &msg); 775 fListView->AddItem(new BStringItem(name)); 776 } 777 break; 778 } 779 case kMsgRemoveFilter: 780 { 781 int32 index = fListView->CurrentSelection(); 782 if (index < 0) 783 break; 784 785 SelectFilter(-1); 786 if (BStringItem *item = (BStringItem *)fListView->RemoveItem(index)) 787 { 788 fChain->RemoveFilter(index + fFirst); 789 delete item; 790 } 791 break; 792 } 793 case kMsgFilterSelected: 794 { 795 int32 index; 796 if (msg->FindInt32("index",&index) < B_OK) 797 break; 798 799 SelectFilter(index); 800 break; 801 } 802 case kMsgFilterMoved: 803 { 804 int32 from = msg->FindInt32("from"); 805 int32 to = msg->FindInt32("to"); 806 if (from == to) 807 break; 808 809 from += fFirst; 810 to += fFirst; 811 812 entry_ref ref; 813 BMessage settings; 814 if (fChain->GetFilter(from,&settings,&ref) == B_OK) 815 { 816 // disable filter view saving 817 if (fFilterView && fFilterView->fIndex == from) 818 fFilterView->fIndex = -1; 819 820 fChain->RemoveFilter(from); 821 822 if (fChain->AddFilter(to,settings,ref) < B_OK) 823 { 824 (new BAlert("E-mail",TR ( 825 "The filter could not be moved. Deleting filter." 826 ),TR("OK")))->Go(); 827 828 // the filter view belongs to the moved filter 829 if (fFilterView && fFilterView->fIndex == -1) 830 SelectFilter(-1); 831 832 fListView->RemoveItem(msg->FindInt32("to")); 833 } 834 else if (fFilterView) 835 { 836 int32 index = fFilterView->fIndex; 837 if (index == -1) 838 // the view belongs to the moved filter 839 fFilterView->fIndex = to; 840 else if (index > from && index < to) 841 // the view belongs to another filter (between the 842 // 'from' & 'to' positions) - all others can keep 843 // their index value 844 fFilterView->fIndex--; 845 } 846 } 847 break; 848 } 849 default: 850 BView::MessageReceived(msg); 851 break; 852 } 853 } 854 855