Major mail protocol/filter settings rework.

* Instead of abusing BArchive::Archive() we now use a BMailSettingsView as
  a base view for all filter/protocol settings that works with
  BMailAddOnSettings.
* Cleanups in E-mail which is now completely layout friendly. But also still
  crashes when changing the views.
This commit is contained in:
Axel Dörfler
2015-01-06 15:22:56 +01:00
parent a6943acbe0
commit ca3341c7b4
26 changed files with 495 additions and 348 deletions
+9 -8
View File
@@ -11,17 +11,15 @@
class BMailProtocol; class BMailProtocol;
class BView; class BMailSettingsView;
class BMailFilter { class BMailFilter {
public: public:
BMailFilter(BMailProtocol& protocol, BMailFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings* settings);
virtual ~BMailFilter(); virtual ~BMailFilter();
virtual BString DescriptiveName() const = 0;
// Message hooks if filter is installed to an inbound protocol // Message hooks if filter is installed to an inbound protocol
virtual void HeaderFetched(const entry_ref& ref, virtual void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
@@ -36,15 +34,18 @@ public:
protected: protected:
BMailProtocol& fMailProtocol; BMailProtocol& fMailProtocol;
BMailAddOnSettings* fSettings; const BMailAddOnSettings* fSettings;
}; };
// Your filter needs to export these hooks in order to be picked up // Your filter needs to export these hooks in order to be picked up
extern "C" BView* instantiate_filter_config_panel(BMailAddOnSettings& settings); extern "C" BMailSettingsView* instantiate_filter_settings_view(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings);
extern "C" BString filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* settings);
extern "C" BMailFilter* instantiate_filter(BMailProtocol& protocol, extern "C" BMailFilter* instantiate_filter(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings& settings);
extern "C" BString filter_name();
#endif // _MAIL_FILTER_H #endif // _MAIL_FILTER_H
@@ -22,6 +22,7 @@
class BMailFilter; class BMailFilter;
class BMailSettingsView;
class BView; class BView;
@@ -103,7 +104,7 @@ protected:
const BMailProtocolSettings& settings); const BMailProtocolSettings& settings);
private: private:
BMailFilter* _LoadFilter(BMailAddOnSettings* filterSettings); BMailFilter* _LoadFilter(const BMailAddOnSettings& settings);
protected: protected:
const BMailAccountSettings fAccountSettings; const BMailAccountSettings fAccountSettings;
@@ -149,12 +150,14 @@ public:
// Your protocol needs to export these hooks in order to be picked up // Your protocol needs to export these hooks in order to be picked up
extern "C" _EXPORT BInboundMailProtocol* instantiate_inbound_protocol( extern "C" BInboundMailProtocol* instantiate_inbound_protocol(
const BMailAccountSettings& settings); const BMailAccountSettings& settings);
extern "C" _EXPORT BOutboundMailProtocol* instantiate_outbound_protocol( extern "C" BOutboundMailProtocol* instantiate_outbound_protocol(
const BMailAccountSettings& settings); const BMailAccountSettings& settings);
extern "C" _EXPORT BView* instantiate_protocol_config_panel(
BMailAccountSettings& settings); extern "C" BMailSettingsView* instantiate_protocol_settings_view(
const BMailAccountSettings& accountSettings,
const BMailProtocolSettings& settings);
#endif // _MAIL_PROTOCOL_H #endif // _MAIL_PROTOCOL_H
@@ -0,0 +1,25 @@
/*
* Copyright 2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _MAIL_SETTINGS_VIEW_H
#define _MAIL_SETTINGS_VIEW_H
#include <MailSettings.h>
#include <View.h>
class BMailSettingsView : public BView {
public:
BMailSettingsView(const char* name);
virtual ~BMailSettingsView();
// virtual BString DescriptiveName() const = 0;
virtual status_t SaveInto(
BMailAddOnSettings& settings) const = 0;
};
#endif // _MAIL_SETTINGS_VIEW_H
@@ -12,6 +12,7 @@
#include <LayoutBuilder.h> #include <LayoutBuilder.h>
#include <MailFilter.h> #include <MailFilter.h>
#include <MailSettings.h> #include <MailSettings.h>
#include <MailSettingsView.h>
#include <MenuField.h> #include <MenuField.h>
#include <MenuItem.h> #include <MenuItem.h>
#include <Message.h> #include <Message.h>
@@ -20,7 +21,7 @@
#include <FileConfigView.h> #include <FileConfigView.h>
#include "RuleFilter.h" #include "MatchHeaderSettings.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
@@ -33,13 +34,15 @@ using namespace BPrivate;
static const uint32 kMsgActionChanged = 'actC'; static const uint32 kMsgActionChanged = 'actC';
class RuleFilterConfig : public BView { class RuleFilterConfig : public BMailSettingsView {
public: public:
RuleFilterConfig(const BMessage& settings); RuleFilterConfig(
const BMailAddOnSettings& settings);
virtual status_t SaveInto(BMailAddOnSettings& settings) const;
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual status_t Archive(BMessage* into, bool deep = true) const;
private: private:
void _SetVisible(BView* view, bool visible); void _SetVisible(BView* view, bool visible);
@@ -57,48 +60,38 @@ private:
}; };
RuleFilterConfig::RuleFilterConfig(const BMessage& settings) RuleFilterConfig::RuleFilterConfig(const BMailAddOnSettings& addOnSettings)
: :
BView("rulefilter_config", 0), BMailSettingsView("rulefilter_config"),
fActionMenu(NULL) fActionMenu(NULL)
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
if (settings.HasInt32("do_what")) MatchHeaderSettings settings(addOnSettings);
fAction = settings.FindInt32("do_what"); fAction = settings.Action();
else
fAction = -1;
fAttributeControl = new BTextControl("attr", B_TRANSLATE("If"), fAttributeControl = new BTextControl("attr", B_TRANSLATE("If"),
B_TRANSLATE("header (e.g. Subject)"), NULL); B_TRANSLATE("header (e.g. Subject)"), NULL);
if (settings.HasString("attribute")) fAttributeControl->SetText(settings.Attribute());
fAttributeControl->SetText(settings.FindString("attribute"));
fRegexControl = new BTextControl("regex", B_TRANSLATE("has"), fRegexControl = new BTextControl("regex", B_TRANSLATE("has"),
B_TRANSLATE("value (use REGEX: in from of regular expressions like " B_TRANSLATE("value (use REGEX: in front of regular expressions like "
"*spam*)"), NULL); "*spam*)"), NULL);
if (settings.HasString("regex")) fRegexControl->SetText(settings.Expression());
fRegexControl->SetText(settings.FindString("regex"));
fFileControl = new FileControl("arg", NULL, fFileControl = new FileControl("arg", NULL,
B_TRANSLATE("this field is based on the action")); B_TRANSLATE("this field is based on the action"));
if (BControl* control = (BControl*)fFileControl->FindView("select_file")) if (BControl* control = (BControl*)fFileControl->FindView("select_file"))
control->SetEnabled(false); control->SetEnabled(false);
if (fAction == ACTION_MOVE_TO && settings.HasString("argument")) fFileControl->SetText(settings.MoveTarget());
fFileControl->SetText(settings.FindString("argument"));
fFlagsControl = new BTextControl("flags", NULL, NULL); fFlagsControl = new BTextControl("flags", NULL, NULL);
if (fAction == ACTION_SET_FLAGS_TO && settings.HasString("argument")) fFlagsControl->SetText(settings.SetFlagsTo());
fFlagsControl->SetText(settings.FindString("argument"));
// Populate account menu // Populate account menu
fAccountMenu = new BPopUpMenu(B_TRANSLATE("<Choose account>")); fAccountMenu = new BPopUpMenu(B_TRANSLATE("<Choose account>"));
fAccountID = settings.ReplyAccount();
if (fAction == ACTION_REPLY_WITH)
fAccountID = settings.FindInt32("argument");
else
fAccountID = -1;
BMailAccounts accounts; BMailAccounts accounts;
for (int32 i = 0; i < accounts.CountAccounts(); i++) { for (int32 i = 0; i < accounts.CountAccounts(); i++) {
@@ -145,7 +138,7 @@ RuleFilterConfig::RuleFilterConfig(const BMessage& settings)
fActionMenu->AddItem(new BMenuItem(kActions[i].label, message)); fActionMenu->AddItem(new BMenuItem(kActions[i].label, message));
} }
BMenuField* actionField = new BMenuField("do_what", B_TRANSLATE("Then"), BMenuField* actionField = new BMenuField("action", B_TRANSLATE("Then"),
fActionMenu); fActionMenu);
// Build layout // Build layout
@@ -166,6 +159,38 @@ RuleFilterConfig::RuleFilterConfig(const BMessage& settings)
} }
status_t
RuleFilterConfig::SaveInto(BMailAddOnSettings& settings) const
{
int32 action = fActionMenu->IndexOf(fActionMenu->FindMarked());
settings.SetInt32("action", action);
settings.SetString("attribute", fAttributeControl->Text());
settings.SetString("regex", fRegexControl->Text());
switch (action) {
case ACTION_MOVE_TO:
settings.SetString("move target", fFileControl->Text());
break;
case ACTION_SET_FLAGS_TO:
settings.SetString("set flags", fFlagsControl->Text());
break;
case ACTION_REPLY_WITH:
{
BMenuItem* item = fAccountMenu->FindMarked();
if (item != NULL) {
settings.SetInt32("account",
item->Message()->FindInt32("account id"));
}
break;
}
}
return B_OK;
}
void void
RuleFilterConfig::AttachedToWindow() RuleFilterConfig::AttachedToWindow()
{ {
@@ -173,26 +198,6 @@ RuleFilterConfig::AttachedToWindow()
} }
status_t
RuleFilterConfig::Archive(BMessage *into, bool deep) const
{
into->MakeEmpty();
into->AddInt32("do_what", fActionMenu->IndexOf(fActionMenu->FindMarked()));
into->AddString("attribute", fAttributeControl->Text());
into->AddString("regex", fRegexControl->Text());
if (into->FindInt32("do_what") == ACTION_REPLY_WITH) {
BMenuItem* item = fAccountMenu->FindMarked();
if (item != NULL) {
into->AddInt32("argument",
item->Message()->FindInt32("account id"));
}
} else
into->AddString("argument", fFileControl->Text());
return B_OK;
}
void void
RuleFilterConfig::MessageReceived(BMessage* message) RuleFilterConfig::MessageReceived(BMessage* message)
{ {
@@ -224,8 +229,9 @@ RuleFilterConfig::_SetVisible(BView* view, bool visible)
// #pragma mark - // #pragma mark -
BView* BMailSettingsView*
instantiate_filter_config_panel(BMailAddOnSettings& settings) instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{ {
return new RuleFilterConfig(settings); return new RuleFilterConfig(settings);
} }
@@ -0,0 +1,64 @@
/*
* Copyright 2012, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef MATCH_HEADER_SETTINGS_H
#define MATCH_HEADER_SETTINGS_H
#include <MailSettings.h>
enum rule_action {
ACTION_MOVE_TO,
ACTION_SET_FLAGS_TO,
ACTION_DELETE_MESSAGE,
ACTION_REPLY_WITH,
ACTION_SET_AS_READ
};
class MatchHeaderSettings {
public:
MatchHeaderSettings(const BMailAddOnSettings& settings)
:
fSettings(settings)
{
}
rule_action Action() const
{
return (rule_action)fSettings.GetInt32("action", -1);
}
const char* Attribute() const
{
return fSettings.FindString("attribute");
}
const char* Expression() const
{
return fSettings.FindString("regex");
}
const char* MoveTarget() const
{
return fSettings.FindString("regex");
}
const char* SetFlagsTo() const
{
return fSettings.FindString("set flags");
}
const int32 ReplyAccount() const
{
return fSettings.GetInt32("account", -1);
}
private:
const BMailAddOnSettings& fSettings;
};
#endif // MATCH_HEADER_SETTINGS_H
@@ -22,20 +22,25 @@
#include <MailProtocol.h> #include <MailProtocol.h>
#include "MatchHeaderSettings.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "RuleFilter" #define B_TRANSLATION_CONTEXT "RuleFilter"
RuleFilter::RuleFilter(BMailProtocol& protocol, BMailAddOnSettings* settings) RuleFilter::RuleFilter(BMailProtocol& protocol,
const BMailAddOnSettings& addOnSettings)
: :
BMailFilter(protocol, settings) BMailFilter(protocol, &addOnSettings)
{ {
MatchHeaderSettings settings(addOnSettings);
// attribute is adapted to our "capitalize-each-word-in-the-header" policy // attribute is adapted to our "capitalize-each-word-in-the-header" policy
settings->FindString("attribute", &fAttribute); fAttribute = settings.Attribute();
fAttribute.CapitalizeEachWord(); fAttribute.CapitalizeEachWord();
settings->FindString("regex", &fExpression); fExpression = settings.Expression();
int32 index = fExpression.FindFirst("REGEX:"); int32 index = fExpression.FindFirst("REGEX:");
if (index == B_ERROR || index > 0) if (index == B_ERROR || index > 0)
EscapeRegexTokens(fExpression); EscapeRegexTokens(fExpression);
@@ -44,20 +49,10 @@ RuleFilter::RuleFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
fMatcher.SetPattern(fExpression, false); fMatcher.SetPattern(fExpression, false);
settings->FindString("argument", &fArg); fAction = settings.Action();
settings->FindInt32("do_what", (int32*)&fAction); fMoveTarget = settings.MoveTarget();
if (fAction == ACTION_REPLY_WITH) fSetFlags = settings.SetFlagsTo();
settings->FindInt32("argument", &fReplyAccount); fReplyAccount = settings.ReplyAccount();
}
BString
RuleFilter::DescriptiveName() const
{
BString name(B_TRANSLATE("Match \"%attribute\" against \"%regex\""));
name.ReplaceAll("%attribute", fAttribute);
name.ReplaceAll("%regex", fExpression);
return name;
} }
@@ -89,7 +84,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
switch (fAction) { switch (fAction) {
case ACTION_MOVE_TO: case ACTION_MOVE_TO:
{ {
BDirectory dir(fArg); BDirectory dir(fMoveTarget);
// TODO: move is currently broken! // TODO: move is currently broken!
// fMailProtocol.Looper()->TriggerFileMove(ref, dir); // fMailProtocol.Looper()->TriggerFileMove(ref, dir);
break; break;
@@ -100,7 +95,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
break; break;
case ACTION_SET_FLAGS_TO: case ACTION_SET_FLAGS_TO:
file->WriteAttrString("MAIL:filter_flags", &fArg); file->WriteAttrString("MAIL:filter_flags", &fSetFlags);
break; break;
case ACTION_REPLY_WITH: case ACTION_REPLY_WITH:
@@ -126,14 +121,25 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
BString BString
filter_name() filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* addOnSettings)
{ {
return B_TRANSLATE("Rule filter"); if (addOnSettings != NULL) {
MatchHeaderSettings settings(*addOnSettings);
if (settings.Attribute() != NULL && settings.Expression() != NULL) {
BString name(
B_TRANSLATE("Match \"%attribute\" against \"%regex\""));
name.ReplaceAll("%attribute", settings.Attribute());
name.ReplaceAll("%regex", settings.Expression());
return name;
}
}
return B_TRANSLATE("Match header");
} }
BMailFilter* BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings) instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings)
{ {
return new RuleFilter(protocol, settings); return new RuleFilter(protocol, settings);
} }
@@ -12,24 +12,14 @@
#include <List.h> #include <List.h>
#include <MailFilter.h> #include <MailFilter.h>
#include "MatchHeaderSettings.h"
#include "StringMatcher.h" #include "StringMatcher.h"
enum rule_action {
ACTION_MOVE_TO,
ACTION_SET_FLAGS_TO,
ACTION_DELETE_MESSAGE,
ACTION_REPLY_WITH,
ACTION_SET_AS_READ
};
class RuleFilter : public BMailFilter { class RuleFilter : public BMailFilter {
public: public:
RuleFilter(BMailProtocol& protocol, RuleFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings& settings);
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref, virtual void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
@@ -38,7 +28,8 @@ private:
BString fAttribute; BString fAttribute;
BString fExpression; BString fExpression;
StringMatcher fMatcher; StringMatcher fMatcher;
BString fArg; BString fMoveTarget;
BString fSetFlags;
int32 fReplyAccount; int32 fReplyAccount;
rule_action fAction; rule_action fAction;
}; };
@@ -30,7 +30,7 @@ const uint32 kMsgNotifyMethod = 'nomt';
NotifierConfigView::NotifierConfigView() NotifierConfigView::NotifierConfigView()
: :
BView("notifier_config", 0) BMailSettingsView("notifier_config")
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
@@ -54,14 +54,6 @@ NotifierConfigView::NotifierConfigView()
} }
void
NotifierConfigView::AttachedToWindow()
{
if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify")))
field->Menu()->SetTargetForItems(this);
}
void void
NotifierConfigView::SetTo(const BMessage *archive) NotifierConfigView::SetTo(const BMessage *archive)
{ {
@@ -77,12 +69,38 @@ NotifierConfigView::SetTo(const BMessage *archive)
BMenuItem *item = field->Menu()->ItemAt(i); BMenuItem *item = field->Menu()->ItemAt(i);
item->SetMarked((method & (1L << i)) != 0); item->SetMarked((method & (1L << i)) != 0);
} }
UpdateNotifyText(); _UpdateNotifyText();
}
status_t
NotifierConfigView::SaveInto(BMailAddOnSettings& settings) const
{
int32 method = 0;
BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL) {
for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
BMenuItem *item = field->Menu()->ItemAt(i);
if (item->IsMarked())
method |= 1L << i;
}
}
return settings.SetInt32("notification_method", method);
} }
void void
NotifierConfigView::UpdateNotifyText() NotifierConfigView::AttachedToWindow()
{
if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify")))
field->Menu()->SetTargetForItems(this);
}
void
NotifierConfigView::_UpdateNotifyText()
{ {
BMenuField *field; BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL) if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
@@ -115,7 +133,7 @@ NotifierConfigView::MessageReceived(BMessage *msg)
break; break;
item->SetMarked(!item->IsMarked()); item->SetMarked(!item->IsMarked());
UpdateNotifyText(); _UpdateNotifyText();
break; break;
} }
default: default:
@@ -124,34 +142,14 @@ NotifierConfigView::MessageReceived(BMessage *msg)
} }
status_t
NotifierConfigView::Archive(BMessage *into, bool /*deep*/) const
{
int32 method = 0;
BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL) {
for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
BMenuItem *item = field->Menu()->ItemAt(i);
if (item->IsMarked())
method |= 1L << i;
}
}
if (into->ReplaceInt32("notification_method", method) != B_OK)
into->AddInt32("notification_method", method);
return B_OK;
}
// #pragma mark - // #pragma mark -
BView* BMailSettingsView*
instantiate_filter_config_panel(BMailAddOnSettings& settings) instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{ {
NotifierConfigView *view = new NotifierConfigView(); NotifierConfigView* view = new NotifierConfigView();
view->SetTo(&settings); view->SetTo(&settings);
return view; return view;
} }
@@ -8,7 +8,7 @@
#define NOTIFIER_CONFIG_VIEW_H #define NOTIFIER_CONFIG_VIEW_H
#include <View.h> #include <MailSettingsView.h>
enum { enum {
@@ -21,18 +21,19 @@ enum {
}; };
class NotifierConfigView : public BView { class NotifierConfigView : public BMailSettingsView {
public: public:
NotifierConfigView(); NotifierConfigView();
void SetTo(const BMessage *archive); void SetTo(const BMessage *archive);
virtual status_t Archive(BMessage *into, bool deep = true) const; virtual status_t SaveInto(BMailAddOnSettings& settings) const;
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage *msg); virtual void MessageReceived(BMessage *msg);
void UpdateNotifyText(); private:
void _UpdateNotifyText();
}; };
@@ -31,9 +31,7 @@
class NotifyFilter : public BMailFilter { class NotifyFilter : public BMailFilter {
public: public:
NotifyFilter(BMailProtocol& protocol, NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings& settings);
virtual BString DescriptiveName() const;
void HeaderFetched(const entry_ref& ref, void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
@@ -46,19 +44,12 @@ private:
NotifyFilter::NotifyFilter(BMailProtocol& protocol, NotifyFilter::NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings) const BMailAddOnSettings& settings)
: :
BMailFilter(protocol, settings), BMailFilter(protocol, &settings),
fNNewMessages(0) fNNewMessages(0)
{ {
fStrategy = settings->FindInt32("notification_method"); fStrategy = settings.FindInt32("notification_method");
}
BString
NotifyFilter::DescriptiveName() const
{
return filter_name();
} }
@@ -130,14 +121,15 @@ NotifyFilter::MailboxSynchronized(status_t status)
BString BString
filter_name() filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* addOnSettings)
{ {
return B_TRANSLATE("New mails notification"); return B_TRANSLATE("New mails notification");
} }
BMailFilter* BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings) instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings)
{ {
return new NotifyFilter(protocol, settings); return new NotifyFilter(protocol, settings);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011, Haiku, Inc. All rights reserved. * Copyright 2002-2012, Haiku, Inc. All rights reserved.
* Copyright 2002 Alexander G. M. Smith. * Copyright 2002 Alexander G. M. Smith.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
@@ -45,23 +45,17 @@ static const char* kAGMSBayesBeepUncertainName = "SpamFilter-Uncertain";
static const char* kServerSignature = "application/x-vnd.agmsmith.spamdbm"; static const char* kServerSignature = "application/x-vnd.agmsmith.spamdbm";
SpamFilter::SpamFilter(BMailProtocol& protocol, BMailAddOnSettings* settings) SpamFilter::SpamFilter(BMailProtocol& protocol,
const BMailAddOnSettings& settings)
: :
BMailFilter(protocol, settings) BMailFilter(protocol, &settings)
{ {
if (settings->FindBool("AddMarkerToSubject", &fAddSpamToSubject) != B_OK) fAddSpamToSubject = settings.GetBool("AddMarkerToSubject", false);
fAddSpamToSubject = false; fAutoTraining = settings.GetBool("AutoTraining", true);
if (settings->FindBool("AutoTraining", &fAutoTraining) != B_OK) fGenuineCutoffRatio = settings.GetFloat("GenuineCutoffRatio", 0.01f);
fAutoTraining = true; fNoWordsMeansSpam = settings.GetBool("NoWordsMeansSpam", true);
if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK) fQuitServerWhenFinished = settings.GetBool("QuitServerWhenFinished", false);
fGenuineCutoffRatio = 0.01f; fSpamCutoffRatio = settings.GetFloat("SpamCutoffRatio", 0.99f);
if (settings->FindBool("NoWordsMeansSpam", &fNoWordsMeansSpam) != B_OK)
fNoWordsMeansSpam = true;
if (settings->FindBool("QuitServerWhenFinished",
&fQuitServerWhenFinished) != B_OK)
fQuitServerWhenFinished = false;
if (settings->FindFloat("SpamCutoffRatio", &fSpamCutoffRatio) != B_OK)
fSpamCutoffRatio = 0.99f;
} }
@@ -72,13 +66,6 @@ SpamFilter::~SpamFilter()
} }
BString
SpamFilter::DescriptiveName() const
{
return filter_name();
}
void void
SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file) SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{ {
@@ -327,14 +314,15 @@ SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
BString BString
filter_name() filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* addOnSettings)
{ {
return B_TRANSLATE("Bayesian Spam Filter"); return B_TRANSLATE("Bayesian Spam Filter");
} }
BMailFilter* BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings) instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings)
{ {
return new SpamFilter(protocol, settings); return new SpamFilter(protocol, settings);
} }
@@ -15,11 +15,9 @@
class SpamFilter : public BMailFilter { class SpamFilter : public BMailFilter {
public: public:
SpamFilter(BMailProtocol& protocol, SpamFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings& settings);
virtual ~SpamFilter(); virtual ~SpamFilter();
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref, virtual void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file); virtual void BodyFetched(const entry_ref& ref, BFile* file);
@@ -18,6 +18,8 @@
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <LayoutBuilder.h> #include <LayoutBuilder.h>
#include <MailFilter.h>
#include <MailSettingsView.h>
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <Roster.h> #include <Roster.h>
@@ -27,7 +29,6 @@
#include <Entry.h> #include <Entry.h>
#include <Path.h> #include <Path.h>
#include <MailFilter.h>
#include <FileConfigView.h> #include <FileConfigView.h>
@@ -35,11 +36,11 @@
#define B_TRANSLATION_CONTEXT "SpamFilterConfig" #define B_TRANSLATION_CONTEXT "SpamFilterConfig"
class SpamFilterConfig : public BView { class SpamFilterConfig : public BMailSettingsView {
public: public:
SpamFilterConfig(const BMessage* settings); SpamFilterConfig(const BMessage* settings);
virtual status_t Archive(BMessage* into, bool deep = true) const; virtual status_t SaveInto(BMailAddOnSettings& settings) const;
private: private:
BCheckBox* fSubjectHintCheckBox; BCheckBox* fSubjectHintCheckBox;
@@ -54,7 +55,7 @@ private:
SpamFilterConfig::SpamFilterConfig(const BMessage* settings) SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
: :
BView("spamfilter_config", 0), BMailSettingsView("spamfilter_config"),
fSubjectHintCheckBox(NULL), fSubjectHintCheckBox(NULL),
fAutoTrainingCheckBox(NULL), fAutoTrainingCheckBox(NULL),
fGenuineCutoffRatioTextControl(NULL), fGenuineCutoffRatioTextControl(NULL),
@@ -116,27 +117,27 @@ SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
status_t status_t
SpamFilterConfig::Archive(BMessage* into, bool /*deep*/) const SpamFilterConfig::SaveInto(BMailAddOnSettings& settings) const
{ {
into->MakeEmpty(); settings.MakeEmpty();
status_t status = into->AddBool("AddMarkerToSubject", status_t status = settings.AddBool("AddMarkerToSubject",
fSubjectHintCheckBox->Value() == B_CONTROL_ON); fSubjectHintCheckBox->Value() == B_CONTROL_ON);
if (status == B_OK) { if (status == B_OK) {
status = into->AddBool("AutoTraining", status = settings.AddBool("AutoTraining",
fAutoTrainingCheckBox->Value() == B_CONTROL_ON); fAutoTrainingCheckBox->Value() == B_CONTROL_ON);
} }
if (status == B_OK) { if (status == B_OK) {
status = into->AddBool("NoWordsMeansSpam", status = settings.AddBool("NoWordsMeansSpam",
fNoWordsMeansSpamCheckBox->Value() == B_CONTROL_ON); fNoWordsMeansSpamCheckBox->Value() == B_CONTROL_ON);
} }
if (status == B_OK) { if (status == B_OK) {
status = into->AddFloat("GenuineCutoffRatio", status = settings.AddFloat("GenuineCutoffRatio",
atof(fGenuineCutoffRatioTextControl->Text())); atof(fGenuineCutoffRatioTextControl->Text()));
} }
if (status == B_OK) { if (status == B_OK) {
status = into->AddFloat("SpamCutoffRatio", status = settings.AddFloat("SpamCutoffRatio",
atof(fSpamCutoffRatioTextControl->Text())); atof(fSpamCutoffRatioTextControl->Text()));
} }
@@ -147,8 +148,9 @@ SpamFilterConfig::Archive(BMessage* into, bool /*deep*/) const
// #pragma mark - // #pragma mark -
BView* BMailSettingsView*
instantiate_filter_config_panel(BMailAddOnSettings& settings) instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{ {
return new SpamFilterConfig(&settings); return new SpamFilterConfig(&settings);
} }
+1
View File
@@ -29,6 +29,7 @@ local sources =
MailMessage.cpp MailMessage.cpp
MailProtocol.cpp MailProtocol.cpp
MailSettings.cpp MailSettings.cpp
MailSettingsView.cpp
NodeMessage.cpp NodeMessage.cpp
numailkit.cpp numailkit.cpp
ProtocolConfigView.cpp ProtocolConfigView.cpp
+2 -1
View File
@@ -6,7 +6,8 @@
#include <MailFilter.h> #include <MailFilter.h>
BMailFilter::BMailFilter(BMailProtocol& protocol, BMailAddOnSettings* settings) BMailFilter::BMailFilter(BMailProtocol& protocol,
const BMailAddOnSettings* settings)
: :
fMailProtocol(protocol), fMailProtocol(protocol),
fSettings(settings) fSettings(settings)
+7 -7
View File
@@ -305,7 +305,7 @@ BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
{ {
for (int i = 0; i < settings.CountFilterSettings(); i++) { for (int i = 0; i < settings.CountFilterSettings(); i++) {
BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i); BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
BMailFilter* filter = _LoadFilter(filterSettings); BMailFilter* filter = _LoadFilter(*filterSettings);
if (filter != NULL) if (filter != NULL)
AddFilter(filter); AddFilter(filter);
} }
@@ -313,9 +313,9 @@ BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
BMailFilter* BMailFilter*
BMailProtocol::_LoadFilter(BMailAddOnSettings* filterSettings) BMailProtocol::_LoadFilter(const BMailAddOnSettings& settings)
{ {
const entry_ref& ref = filterSettings->AddOnRef(); const entry_ref& ref = settings.AddOnRef();
std::map<entry_ref, image_id>::iterator it = fFilterImages.find(ref); std::map<entry_ref, image_id>::iterator it = fFilterImages.find(ref);
image_id image; image_id image;
if (it != fFilterImages.end()) if (it != fFilterImages.end())
@@ -328,16 +328,16 @@ BMailProtocol::_LoadFilter(BMailAddOnSettings* filterSettings)
if (image < 0) if (image < 0)
return NULL; return NULL;
BMailFilter* (*instantiate_filter)(BMailProtocol& protocol, BMailFilter* (*instantiateFilter)(BMailProtocol& protocol,
BMailAddOnSettings* settings); const BMailAddOnSettings& settings);
if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT, if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT,
(void**)&instantiate_filter) != B_OK) { (void**)&instantiateFilter) != B_OK) {
unload_add_on(image); unload_add_on(image);
return NULL; return NULL;
} }
fFilterImages[ref] = image; fFilterImages[ref] = image;
return (*instantiate_filter)(*this, filterSettings); return instantiateFilter(*this, settings);
} }
+2
View File
@@ -460,6 +460,8 @@ BMailAddOnSettings::Load(const BMessage& message)
MakeEmpty(); MakeEmpty();
Append(settings); Append(settings);
puts("settings:");
settings.PrintToStream();
fOriginalSettings = *this; fOriginalSettings = *this;
fOriginalRef = fRef; fOriginalRef = fRef;
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2012, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <MailSettingsView.h>
BMailSettingsView::BMailSettingsView(const char* name)
:
BView(name, 0)
{
}
BMailSettingsView::~BMailSettingsView()
{
}
+1 -1
View File
@@ -394,7 +394,7 @@ MailProtocolConfigView::_StoreIndexOfMarked(BMessage& message, const char* name,
BMenuField* field) const BMenuField* field) const
{ {
int32 index = -1; int32 index = -1;
if (field != NULL) { if (field != NULL && field->Menu() != NULL) {
BMenuItem* item = field->Menu()->FindMarked(); BMenuItem* item = field->Menu()->FindMarked();
if (item != NULL) if (item != NULL)
index = field->Menu()->IndexOf(item); index = field->Menu()->IndexOf(item);
+21 -17
View File
@@ -120,17 +120,18 @@ AccountConfigView::UpdateViews()
// #pragma mark - // #pragma mark -
ProtocolConfigView::ProtocolConfigView(BMailAccountSettings& accountSettings, ProtocolSettingsView::ProtocolSettingsView(const entry_ref& ref,
const entry_ref& ref, BMailProtocolSettings& settings) const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings)
: :
BBox("protocol"), BBox("protocol"),
fSettings(settings), fSettings(settings),
fConfigView(NULL) fSettingsView(NULL)
{ {
status_t status = _CreateConfigView(ref, settings, accountSettings); status_t status = _CreateSettingsView(ref, accountSettings, settings);
BView* view = fConfigView; BView* view = fSettingsView;
if (fConfigView != NULL) { if (status == B_OK) {
SetLabel(ref.name); SetLabel(ref.name);
} else { } else {
BString text(B_TRANSLATE("An error occurred while creating the " BString text(B_TRANSLATE("An error occurred while creating the "
@@ -151,30 +152,33 @@ ProtocolConfigView::ProtocolConfigView(BMailAccountSettings& accountSettings,
void void
ProtocolConfigView::DetachedFromWindow() ProtocolSettingsView::DetachedFromWindow()
{ {
if (fConfigView == NULL) if (fSettingsView == NULL)
return; return;
BMessage settings; BMessage settings;
if (fConfigView->Archive(&settings) != B_OK) if (fSettingsView->Archive(&settings) != B_OK)
return; return;
fSettings.MakeEmpty(); fSettings.MakeEmpty();
fSettings.Append(settings); fSettings.Append(settings);
RemoveChild(fConfigView); RemoveChild(fSettingsView);
delete fConfigView; delete fSettingsView;
fConfigView = NULL; fSettingsView = NULL;
unload_add_on(fImage); unload_add_on(fImage);
} }
status_t status_t
ProtocolConfigView::_CreateConfigView(const entry_ref& ref, ProtocolSettingsView::_CreateSettingsView(const entry_ref& ref,
BMailProtocolSettings& settings, BMailAccountSettings& accountSettings) const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings)
{ {
BView* (*instantiateConfig)(BMailProtocolSettings& settings, BMailSettingsView* (*instantiateConfig)(
BMailAccountSettings& accountSettings); const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings);
BPath path(&ref); BPath path(&ref);
image_id image = load_add_on(path.Path()); image_id image = load_add_on(path.Path());
if (image < 0) if (image < 0)
@@ -187,6 +191,6 @@ ProtocolConfigView::_CreateConfigView(const entry_ref& ref,
} }
fImage = image; fImage = image;
fConfigView = instantiateConfig(settings, accountSettings); fSettingsView = instantiateConfig(accountSettings, settings);
return B_OK; return B_OK;
} }
+11 -9
View File
@@ -12,8 +12,11 @@
#include <Box.h> #include <Box.h>
#include <image.h> #include <image.h>
#include "MailSettings.h" #include <MailSettingsView.h>
#include <MailSettings.h>
#include <ProtocolConfigView.h> #include <ProtocolConfigView.h>
#include "FilterConfigView.h" #include "FilterConfigView.h"
@@ -43,23 +46,22 @@ private:
}; };
class ProtocolConfigView : public BBox { class ProtocolSettingsView : public BBox {
public: public:
ProtocolConfigView( ProtocolSettingsView(const entry_ref& ref,
BMailAccountSettings& accountSettings, const BMailAccountSettings& accountSettings,
const entry_ref& ref,
BMailProtocolSettings& settings); BMailProtocolSettings& settings);
void DetachedFromWindow(); void DetachedFromWindow();
private: private:
status_t _CreateConfigView(const entry_ref& ref, status_t _CreateSettingsView(const entry_ref& ref,
BMailProtocolSettings& settings, const BMailAccountSettings& accountSettings,
BMailAccountSettings& accountSettings); BMailProtocolSettings& settings);
private: private:
BMailProtocolSettings& fSettings; BMailProtocolSettings& fSettings;
BView* fConfigView; BMailSettingsView* fSettingsView;
image_id fImage; image_id fImage;
}; };
+4 -4
View File
@@ -831,13 +831,13 @@ ConfigWindow::_AccountSelected(AccountItem* item)
break; break;
case INBOUND_ITEM: case INBOUND_ITEM:
view = new ProtocolConfigView(*account, account->InboundAddOnRef(), view = new ProtocolSettingsView(account->InboundAddOnRef(),
account->InboundSettings()); *account, account->InboundSettings());
break; break;
case OUTBOUND_ITEM: case OUTBOUND_ITEM:
view = new ProtocolConfigView(*account, account->OutboundAddOnRef(), view = new ProtocolSettingsView(account->OutboundAddOnRef(),
account->OutboundSettings()); *account, account->OutboundSettings());
break; break;
case FILTER_ITEM: case FILTER_ITEM:
+33 -35
View File
@@ -177,29 +177,30 @@ private:
// #pragma mark - // #pragma mark -
class FilterConfigBox : public BBox { class FilterSettingsView : public BBox {
public: public:
FilterConfigBox(const BString& label, BView* child) FilterSettingsView(const BString& label, BMailSettingsView* settingsView)
: :
BBox(BRect(0,0,100,100)), BBox("filter"),
fChild(child) fSettingsView(settingsView)
{ {
SetLabel(label); SetLabel(label);
float w = child->Bounds().Width();
float h = child->Bounds().Height(); BView* contents = new BView("contents", 0);
child->MoveTo(3, 13); AddChild(contents);
ResizeTo(w + 6, h + 16);
AddChild(child); BLayoutBuilder::Group<>(contents, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fSettingsView);
} }
status_t status_t SaveInto(BMailAddOnSettings& settings) const
ArchiveAddOn(BMessage* into) const
{ {
return fChild->Archive(into); return fSettingsView->SaveInto(settings);
} }
private: private:
BView* fChild; BMailSettingsView* fSettingsView;
}; };
@@ -211,8 +212,8 @@ FiltersConfigView::FiltersConfigView(BMailAccountSettings& account)
BBox("filters"), BBox("filters"),
fAccount(account), fAccount(account),
fDirection(kIncoming), fDirection(kIncoming),
fInboundFilters(kIncoming, false), fInboundFilters(kIncoming),
fOutboundFilters(kOutgoing, false), fOutboundFilters(kOutgoing),
fFilterView(NULL), fFilterView(NULL),
fCurrentIndex(-1) fCurrentIndex(-1)
{ {
@@ -284,11 +285,12 @@ FiltersConfigView::_SelectFilter(int32 index)
= _MailSettings()->FilterSettingsAt(index); = _MailSettings()->FilterSettingsAt(index);
if (filterSettings != NULL) { if (filterSettings != NULL) {
::FilterList* filters = _FilterList(); ::FilterList* filters = _FilterList();
BView* view = filters->CreateConfigView(*filterSettings); BMailSettingsView* view = filters->CreateSettingsView(fAccount,
*filterSettings);
if (view != NULL) { if (view != NULL) {
BString name; fFilterView = new FilterSettingsView(
filters->GetDescriptiveName(filterSettings->AddOnRef(), name); filters->DescriptiveName(filterSettings->AddOnRef(),
fFilterView = new FilterConfigBox(name, view); fAccount, NULL), view);
Parent()->AddChild(fFilterView); Parent()->AddChild(fFilterView);
} }
} }
@@ -320,31 +322,30 @@ FiltersConfigView::_SetDirection(direction direction)
for (int32 i = 0; i < protocolSettings->CountFilterSettings(); i++) { for (int32 i = 0; i < protocolSettings->CountFilterSettings(); i++) {
BMailAddOnSettings* settings = protocolSettings->FilterSettingsAt(i); BMailAddOnSettings* settings = protocolSettings->FilterSettingsAt(i);
if (filters->InfoIndexFor(settings->AddOnRef()) < 0) { if (filters->InfoIndexFor(settings->AddOnRef()) < 0) {
fprintf(stderr, "Removed missing filter: %s\n",
settings->AddOnRef().name);
protocolSettings->RemoveFilterSettings(i); protocolSettings->RemoveFilterSettings(i);
i--; i--;
continue; continue;
} }
BString name = "Unnamed Filter";
filters->GetDescriptiveName(settings->AddOnRef(), name); fListView->AddItem(new BStringItem(filters->DescriptiveName(
fListView->AddItem(new BStringItem(name)); settings->AddOnRef(), fAccount, settings)));
} }
// remove old filter items // remove old filter items
BMenu *menu = fAddField->Menu(); BMenu* menu = fAddField->Menu();
for (int32 i = menu->CountItems(); i-- > 0;) { for (int32 i = menu->CountItems(); i-- > 0;) {
BMenuItem *item = menu->RemoveItem(i); BMenuItem *item = menu->RemoveItem(i);
delete item; delete item;
} }
filters->Reload();
for (int32 i = 0; i < filters->CountInfos(); i++) { for (int32 i = 0; i < filters->CountInfos(); i++) {
FilterInfo& info = filters->InfoAt(i); const FilterInfo& info = filters->InfoAt(i);
BString name;
filters->GetDescriptiveName(i, name);
BMessage* msg = new BMessage(kMsgAddFilter); BMessage* msg = new BMessage(kMsgAddFilter);
msg->AddRef("filter", &info.ref); msg->AddRef("filter", &info.ref);
BMenuItem *item = new BMenuItem(name, msg); BMenuItem* item = new BMenuItem(filters->SimpleName(i, fAccount), msg);
menu->AddItem(item); menu->AddItem(item);
} }
@@ -391,15 +392,12 @@ FiltersConfigView::MessageReceived(BMessage *msg)
if (msg->FindRef("filter", &ref) != B_OK) if (msg->FindRef("filter", &ref) != B_OK)
break; break;
::FilterList* filters = _FilterList(); int32 index = _MailSettings()->AddFilterSettings(&ref);
int32 index = filters->InfoIndexFor(ref);
if (index < 0) if (index < 0)
break; break;
_MailSettings()->AddFilterSettings(&ref);
BString name; fListView->AddItem(new BStringItem(_FilterList()->DescriptiveName(
filters->GetDescriptiveName(index, name); ref, fAccount, _MailSettings()->FilterSettingsAt(index))));
fListView->AddItem(new BStringItem(name));
break; break;
} }
case kMsgRemoveFilter: case kMsgRemoveFilter:
@@ -470,6 +468,6 @@ FiltersConfigView::_SaveConfig(int32 index)
if (fFilterView != NULL) { if (fFilterView != NULL) {
BMailAddOnSettings* settings = _MailSettings()->FilterSettingsAt(index); BMailAddOnSettings* settings = _MailSettings()->FilterSettingsAt(index);
if (settings != NULL) if (settings != NULL)
fFilterView->ArchiveAddOn(settings); fFilterView->SaveInto(*settings);
} }
} }
+4 -3
View File
@@ -20,7 +20,7 @@
#include "FilterList.h" #include "FilterList.h"
class FilterConfigBox; class FilterSettingsView;
class FiltersConfigView : public BBox { class FiltersConfigView : public BBox {
@@ -52,9 +52,10 @@ private:
BListView* fListView; BListView* fListView;
BMenuField* fAddField; BMenuField* fAddField;
BButton* fRemoveButton; BButton* fRemoveButton;
FilterConfigBox* fFilterView; FilterSettingsView* fFilterView;
int32 fCurrentIndex; int32 fCurrentIndex;
}; };
#endif //FILTER_CONFIG_VIEW_H
#endif // FILTER_CONFIG_VIEW_H
+97 -67
View File
@@ -7,17 +7,17 @@
#include "FilterList.h" #include "FilterList.h"
#include <set>
#include <Directory.h> #include <Directory.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Path.h> #include <Path.h>
FilterList::FilterList(direction dir, bool loadOnStart) FilterList::FilterList(direction dir)
: :
fDirection(dir) fDirection(dir)
{ {
if (loadOnStart)
Reload();
} }
@@ -32,91 +32,116 @@ FilterList::Reload()
{ {
_MakeEmpty(); _MakeEmpty();
BPath path; std::set<BString> knownNames;
status_t status = find_directory(B_SYSTEM_ADDONS_DIRECTORY, &path);
if (status != B_OK)
return;
path.Append("mail_daemon");
if (fDirection == kIncoming)
path.Append("inbound_filters");
else
path.Append("outbound_filters");
BDirectory dir(path.Path()); directory_which which[] = {B_USER_ADDONS_DIRECTORY,
if (dir.InitCheck() != B_OK) B_COMMON_ADDONS_DIRECTORY,
return; B_SYSTEM_ADDONS_DIRECTORY};
BEntry entry; for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
while (dir.GetNextEntry(&entry) == B_OK) BPath path;
_LoadAddOn(entry); status_t status = find_directory(which[i], &path);
if (status != B_OK)
continue;
path.Append("mail_daemon");
if (fDirection == kIncoming)
path.Append("inbound_filters");
else
path.Append("outbound_filters");
BDirectory dir(path.Path());
if (dir.InitCheck() != B_OK)
continue;
BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK) {
// Ignore entries we already had before (ie., user add-ons are
// overriding system add-ons)
if (knownNames.find(entry.Name()) != knownNames.end())
continue;
if (_LoadAddOn(entry) == B_OK)
knownNames.insert(entry.Name());
}
}
} }
int32 int32
FilterList::CountInfos() FilterList::CountInfos() const
{ {
return fList.size(); return fList.size();
} }
FilterInfo& const FilterInfo&
FilterList::InfoAt(int32 index) FilterList::InfoAt(int32 index) const
{ {
return fList[index]; return fList[index];
} }
bool int32
FilterList::GetDescriptiveName(int32 index, BString& name) FilterList::InfoIndexFor(const entry_ref& ref) const
{ {
if (index < 0) for (size_t i = 0; i < fList.size(); i++) {
return false; const FilterInfo& info = fList[i];
if (info.ref == ref)
FilterInfo& info = InfoAt(index); return i;
}
BString (*descriptive_name)(); return -1;
if (get_image_symbol(info.image, "descriptive_name", B_SYMBOL_TYPE_TEXT,
(void **)&descriptive_name) == B_OK) {
name = (*descriptive_name)();
} else
name = info.ref.name;
return true;
} }
bool BString
FilterList::GetDescriptiveName(const entry_ref& ref, BString& name) FilterList::SimpleName(int32 index,
const BMailAccountSettings& accountSettings) const
{ {
int32 index = InfoIndexFor(ref); return DescriptiveName(index, accountSettings, NULL);
return GetDescriptiveName(index, name);
} }
BView* BString
FilterList::CreateConfigView(BMailAddOnSettings& settings) FilterList::SimpleName(const entry_ref& ref,
const BMailAccountSettings& accountSettings) const
{
return DescriptiveName(InfoIndexFor(ref), accountSettings, NULL);
}
BString
FilterList::DescriptiveName(int32 index,
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* settings) const
{
if (index < 0 || index >= CountInfos())
return "-";
const FilterInfo& info = InfoAt(index);
return info.name(accountSettings, settings);
}
BString
FilterList::DescriptiveName(const entry_ref& ref,
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* settings) const
{
return DescriptiveName(InfoIndexFor(ref), accountSettings, settings);
}
BMailSettingsView*
FilterList::CreateSettingsView(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{ {
const entry_ref& ref = settings.AddOnRef(); const entry_ref& ref = settings.AddOnRef();
int32 index = InfoIndexFor(ref); int32 index = InfoIndexFor(ref);
if (index < 0) if (index < 0)
return NULL; return NULL;
FilterInfo& info = InfoAt(index);
BView* (*instantiateFilterConfigPanel)(BMailAddOnSettings&); const FilterInfo& info = InfoAt(index);
if (get_image_symbol(info.image, "instantiate_filter_config_panel", return info.instantiateSettingsView(accountSettings, settings);
B_SYMBOL_TYPE_TEXT, (void **)&instantiateFilterConfigPanel) != B_OK)
return NULL;
return (*instantiateFilterConfigPanel)(settings);
}
int32
FilterList::InfoIndexFor(const entry_ref& ref)
{
for (size_t i = 0; i < fList.size(); i++) {
FilterInfo& info = fList[i];
if (info.ref == ref)
return i;
}
return -1;
} }
@@ -131,7 +156,7 @@ FilterList::_MakeEmpty()
} }
void status_t
FilterList::_LoadAddOn(BEntry& entry) FilterList::_LoadAddOn(BEntry& entry)
{ {
FilterInfo info; FilterInfo info;
@@ -139,17 +164,22 @@ FilterList::_LoadAddOn(BEntry& entry)
BPath path(&entry); BPath path(&entry);
info.image = load_add_on(path.Path()); info.image = load_add_on(path.Path());
if (info.image < 0) if (info.image < 0)
return; return info.image;
BView* (*instantiateFilterConfigPanel)(BMailProtocolSettings&); status_t status = get_image_symbol(info.image,
if (get_image_symbol(info.image, "instantiate_filter_config_panel", "instantiate_filter_settings_view", B_SYMBOL_TYPE_TEXT,
B_SYMBOL_TYPE_TEXT, (void **)&instantiateFilterConfigPanel) (void**)&info.instantiateSettingsView);
!= B_OK) { if (status == B_OK) {
status = get_image_symbol(info.image, "filter_name", B_SYMBOL_TYPE_TEXT,
(void**)&info.name);
}
if (status != B_OK) {
fprintf(stderr, "Filter \"%s\" misses required hooks!\n", path.Path());
unload_add_on(info.image); unload_add_on(info.image);
return; return B_NAME_NOT_FOUND;
} }
entry.GetRef(&info.ref); entry.GetRef(&info.ref);
fList.push_back(info); fList.push_back(info);
return B_OK;
} }
+26 -12
View File
@@ -8,7 +8,7 @@
#include <MailSettings.h> #include <MailSettings.h>
#include <View.h> #include <MailSettingsView.h>
enum direction { enum direction {
@@ -20,32 +20,46 @@ enum direction {
struct FilterInfo { struct FilterInfo {
image_id image; image_id image;
entry_ref ref; entry_ref ref;
BMailSettingsView* (*instantiateSettingsView)(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings);
BString (*name)(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* settings);
}; };
class FilterList { class FilterList {
public: public:
FilterList(direction dir, FilterList(direction dir);
bool loadOnStart = true);
~FilterList(); ~FilterList();
void Reload(); void Reload();
int32 CountInfos(); int32 CountInfos() const;
FilterInfo& InfoAt(int32 index); const FilterInfo& InfoAt(int32 index) const;
int32 InfoIndexFor(const entry_ref& ref) const;
bool GetDescriptiveName(int32 index, BString& name); BString SimpleName(int32 index,
bool GetDescriptiveName(const entry_ref& ref, const BMailAccountSettings& settings) const;
BString& name); BString SimpleName(const entry_ref& ref,
const BMailAccountSettings& settings) const;
BString DescriptiveName(int32 index,
const BMailAccountSettings& settings,
const BMailAddOnSettings* settings) const;
BString DescriptiveName(const entry_ref& ref,
const BMailAccountSettings& settings,
const BMailAddOnSettings* settings) const;
BView* CreateConfigView(BMailAddOnSettings& settings); BMailSettingsView* CreateSettingsView(
const BMailAccountSettings& accountSettings,
int32 InfoIndexFor(const entry_ref& ref); const BMailAddOnSettings& settings);
private: private:
void _MakeEmpty(); void _MakeEmpty();
void _LoadAddOn(BEntry& entry); status_t _LoadAddOn(BEntry& entry);
private:
direction fDirection; direction fDirection;
std::vector<FilterInfo> fList; std::vector<FilterInfo> fList;
}; };