2 * Copyright 2007-2016, Haiku, Inc. All rights reserved.
3 * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
4 * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
5 * Distributed under the terms of the MIT License.
9 #include "FilterConfigView.h"
17 #include <LayoutBuilder.h>
20 #include <PopUpMenu.h>
21 #include <ScrollView.h>
24 #undef B_TRANSLATION_CONTEXT
25 #define B_TRANSLATION_CONTEXT "Config Views"
29 const uint32 kMsgFilterMoved
= 'flmv';
30 const uint32 kMsgChainSelected
= 'chsl';
31 const uint32 kMsgAddFilter
= 'addf';
32 const uint32 kMsgRemoveFilter
= 'rmfi';
33 const uint32 kMsgFilterSelected
= 'fsel';
35 const uint32 kMsgItemDragged
= 'itdr';
38 class DragListView
: public BListView
{
40 DragListView(const char* name
,
41 list_view_type type
= B_SINGLE_SELECTION_LIST
,
42 BMessage
* itemMovedMsg
= NULL
)
44 BListView(name
, type
),
46 fItemMovedMessage(itemMovedMsg
)
50 virtual bool InitiateDrag(BPoint point
, int32 index
, bool wasSelected
)
52 BRect
frame(ItemFrame(index
));
53 BBitmap
*bitmap
= new BBitmap(frame
.OffsetToCopy(B_ORIGIN
), B_RGBA32
,
55 BView
*view
= new BView(bitmap
->Bounds(), NULL
, 0, 0);
56 bitmap
->AddChild(view
);
58 if (view
->LockLooper()) {
59 BListItem
*item
= ItemAt(index
);
60 bool selected
= item
->IsSelected();
62 view
->SetLowColor(225, 225, 225, 128);
63 view
->FillRect(view
->Bounds());
67 ItemAt(index
)->DrawItem(view
, view
->Bounds(), true);
77 BMessage
drag(kMsgItemDragged
);
78 drag
.AddInt32("index", index
);
79 DragMessage(&drag
, bitmap
, B_OP_ALPHA
, point
- frame
.LeftTop(), this);
84 void DrawDragTargetIndicator(int32 target
)
87 SetDrawingMode(B_OP_INVERT
);
90 if (target
>= CountItems())
91 target
= CountItems() - 1, last
= true;
93 BRect frame
= ItemFrame(target
);
95 frame
.OffsetBy(0,frame
.Height());
96 frame
.bottom
= frame
.top
+ 1;
103 virtual void MouseMoved(BPoint point
, uint32 transit
, const BMessage
*msg
)
105 BListView::MouseMoved(point
, transit
, msg
);
107 if ((transit
!= B_ENTERED_VIEW
&& transit
!= B_INSIDE_VIEW
)
111 int32 target
= IndexOf(point
);
113 target
= CountItems();
115 // correct the target insertion index
116 if (target
== fDragIndex
|| target
== fDragIndex
+ 1)
119 if (target
== fLastDragTarget
)
122 // remove old target indicator
123 if (fLastDragTarget
!= -1)
124 DrawDragTargetIndicator(fLastDragTarget
);
127 fLastDragTarget
= target
;
129 DrawDragTargetIndicator(target
);
132 virtual void MouseUp(BPoint point
)
136 if (fLastDragTarget
!= -1)
137 DrawDragTargetIndicator(fLastDragTarget
);
139 BListView::MouseUp(point
);
142 virtual void MessageReceived(BMessage
*msg
)
145 case kMsgItemDragged
:
147 int32 source
= msg
->FindInt32("index");
148 BPoint point
= msg
->FindPoint("_drop_point_");
149 ConvertFromScreen(&point
);
150 int32 to
= IndexOf(point
);
154 to
= CountItems() - 1;
159 if (fItemMovedMessage
!= NULL
) {
160 BMessage
msg(fItemMovedMessage
->what
);
161 msg
.AddInt32("from",source
);
162 msg
.AddInt32("to",to
);
163 Messenger().SendMessage(&msg
);
169 BListView::MessageReceived(msg
);
174 int32 fLastDragTarget
,fDragIndex
;
175 BMessage
*fItemMovedMessage
;
182 class FilterSettingsView
: public BBox
{
184 FilterSettingsView(const BString
& label
, BMailSettingsView
* settingsView
)
187 fSettingsView(settingsView
)
191 BView
* contents
= new BView("contents", 0);
194 BLayoutBuilder::Group
<>(contents
, B_VERTICAL
)
195 .SetInsets(B_USE_DEFAULT_SPACING
)
199 status_t
SaveInto(BMailAddOnSettings
& settings
) const
201 return fSettingsView
->SaveInto(settings
);
205 BMailSettingsView
* fSettingsView
;
212 FiltersConfigView::FiltersConfigView(BMailAccountSettings
& account
)
214 BGroupView(B_VERTICAL
),
216 fDirection(kIncoming
),
217 fInboundFilters(kIncoming
),
218 fOutboundFilters(kOutgoing
),
222 BBox
* box
= new BBox("filters");
225 BView
* contents
= new BView(NULL
, 0);
226 box
->AddChild(contents
);
228 BMessage
* msg
= new BMessage(kMsgChainSelected
);
229 msg
->AddInt32("direction", kIncoming
);
230 BMenuItem
* item
= new BMenuItem(B_TRANSLATE("Incoming mail filters"), msg
);
231 item
->SetMarked(true);
232 BPopUpMenu
* menu
= new BPopUpMenu(B_EMPTY_STRING
);
235 msg
= new BMessage(kMsgChainSelected
);
236 msg
->AddInt32("direction", kOutgoing
);
237 item
= new BMenuItem(B_TRANSLATE("Outgoing mail filters"), msg
);
240 fChainsField
= new BMenuField(NULL
, NULL
, menu
);
241 fChainsField
->ResizeToPreferred();
242 box
->SetLabel(fChainsField
);
244 fListView
= new DragListView(NULL
, B_SINGLE_SELECTION_LIST
,
245 new BMessage(kMsgFilterMoved
));
246 fListView
->SetSelectionMessage(new BMessage(kMsgFilterSelected
));
248 menu
= new BPopUpMenu(B_TRANSLATE("Add filter"));
249 menu
->SetRadioMode(false);
251 fAddField
= new BMenuField(NULL
, NULL
, menu
);
253 fRemoveButton
= new BButton(NULL
, B_TRANSLATE("Remove"),
254 new BMessage(kMsgRemoveFilter
));
256 BLayoutBuilder::Group
<>(contents
, B_VERTICAL
)
257 .SetInsets(B_USE_DEFAULT_SPACING
)
258 .Add(new BScrollView(NULL
, fListView
, 0, false, true))
259 .AddGroup(B_HORIZONTAL
)
264 _SetDirection(fDirection
);
268 FiltersConfigView::~FiltersConfigView()
270 // We need to remove the filter manually, as their add-on
271 // is not available anymore in the parent destructor.
272 if (fFilterView
!= NULL
) {
273 RemoveChild(fFilterView
);
280 FiltersConfigView::_SelectFilter(int32 index
)
284 // remove old config view
285 if (fFilterView
!= NULL
) {
286 RemoveChild(fFilterView
);
287 _SaveConfig(fCurrentIndex
);
293 // add new config view
294 BMailAddOnSettings
* filterSettings
295 = _MailSettings()->FilterSettingsAt(index
);
296 if (filterSettings
!= NULL
) {
297 ::FilterList
* filters
= _FilterList();
298 BMailSettingsView
* view
= filters
->CreateSettingsView(fAccount
,
301 fFilterView
= new FilterSettingsView(
302 filters
->DescriptiveName(filterSettings
->AddOnRef(),
303 fAccount
, NULL
), view
);
304 AddChild(fFilterView
);
309 fCurrentIndex
= index
;
315 FiltersConfigView::_SetDirection(direction direction
)
317 // remove the filter config view
320 for (int32 i
= fListView
->CountItems(); i
-- > 0;) {
321 BStringItem
*item
= (BStringItem
*)fListView
->RemoveItem(i
);
325 fDirection
= direction
;
326 BMailProtocolSettings
* protocolSettings
= _MailSettings();
327 ::FilterList
* filters
= _FilterList();
330 for (int32 i
= 0; i
< protocolSettings
->CountFilterSettings(); i
++) {
331 BMailAddOnSettings
* settings
= protocolSettings
->FilterSettingsAt(i
);
332 if (filters
->InfoIndexFor(settings
->AddOnRef()) < 0) {
333 fprintf(stderr
, "Removed missing filter: %s\n",
334 settings
->AddOnRef().name
);
335 protocolSettings
->RemoveFilterSettings(i
);
340 fListView
->AddItem(new BStringItem(filters
->DescriptiveName(
341 settings
->AddOnRef(), fAccount
, settings
)));
344 // remove old filter items
345 BMenu
* menu
= fAddField
->Menu();
346 for (int32 i
= menu
->CountItems(); i
-- > 0;) {
347 BMenuItem
*item
= menu
->RemoveItem(i
);
351 for (int32 i
= 0; i
< filters
->CountInfos(); i
++) {
352 const FilterInfo
& info
= filters
->InfoAt(i
);
354 BMessage
* msg
= new BMessage(kMsgAddFilter
);
355 msg
->AddRef("filter", &info
.ref
);
356 BMenuItem
* item
= new BMenuItem(filters
->SimpleName(i
, fAccount
), msg
);
360 menu
->SetTargetForItems(this);
365 FiltersConfigView::AttachedToWindow()
367 fChainsField
->Menu()->SetTargetForItems(this);
368 fListView
->SetTarget(this);
369 fAddField
->Menu()->SetTargetForItems(this);
370 fRemoveButton
->SetTarget(this);
375 FiltersConfigView::DetachedFromWindow()
377 _SaveConfig(fCurrentIndex
);
382 FiltersConfigView::MessageReceived(BMessage
*msg
)
385 case kMsgChainSelected
:
388 if (msg
->FindInt32("direction", (int32
*)&dir
) != B_OK
)
391 if (fDirection
== dir
)
400 if (msg
->FindRef("filter", &ref
) != B_OK
)
403 int32 index
= _MailSettings()->AddFilterSettings(&ref
);
407 fListView
->AddItem(new BStringItem(_FilterList()->DescriptiveName(
408 ref
, fAccount
, _MailSettings()->FilterSettingsAt(index
))));
411 case kMsgRemoveFilter
:
413 int32 index
= fListView
->CurrentSelection();
416 BStringItem
* item
= (BStringItem
*)fListView
->RemoveItem(index
);
420 _MailSettings()->RemoveFilterSettings(index
);
423 case kMsgFilterSelected
:
426 if (msg
->FindInt32("index",&index
) != B_OK
)
429 _SelectFilter(index
);
432 case kMsgFilterMoved
:
434 int32 from
= msg
->FindInt32("from");
435 int32 to
= msg
->FindInt32("to");
439 if (!_MailSettings()->MoveFilterSettings(from
, to
)) {
440 BAlert
* alert
= new BAlert("E-mail",
441 B_TRANSLATE("The filter could not be moved. Deleting "
442 "filter."), B_TRANSLATE("OK"));
443 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
445 fListView
->RemoveItem(to
);
452 BView::MessageReceived(msg
);
458 BMailProtocolSettings
*
459 FiltersConfigView::_MailSettings()
461 return fDirection
== kIncoming
462 ? &fAccount
.InboundSettings() : &fAccount
.OutboundSettings();
467 FiltersConfigView::_FilterList()
469 return fDirection
== kIncoming
? &fInboundFilters
: &fOutboundFilters
;
474 FiltersConfigView::_SaveConfig(int32 index
)
476 if (fFilterView
!= NULL
) {
477 BMailAddOnSettings
* settings
= _MailSettings()->FilterSettingsAt(index
);
478 if (settings
!= NULL
)
479 fFilterView
->SaveInto(*settings
);