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 BView;
class BMailSettingsView;
class BMailFilter {
public:
BMailFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
const BMailAddOnSettings* settings);
virtual ~BMailFilter();
virtual BString DescriptiveName() const = 0;
// Message hooks if filter is installed to an inbound protocol
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
@@ -36,15 +34,18 @@ public:
protected:
BMailProtocol& fMailProtocol;
BMailAddOnSettings* fSettings;
const BMailAddOnSettings* fSettings;
};
// 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,
BMailAddOnSettings* settings);
extern "C" BString filter_name();
const BMailAddOnSettings& settings);
#endif // _MAIL_FILTER_H
@@ -22,6 +22,7 @@
class BMailFilter;
class BMailSettingsView;
class BView;
@@ -103,7 +104,7 @@ protected:
const BMailProtocolSettings& settings);
private:
BMailFilter* _LoadFilter(BMailAddOnSettings* filterSettings);
BMailFilter* _LoadFilter(const BMailAddOnSettings& settings);
protected:
const BMailAccountSettings fAccountSettings;
@@ -149,12 +150,14 @@ public:
// 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);
extern "C" _EXPORT BOutboundMailProtocol* instantiate_outbound_protocol(
extern "C" BOutboundMailProtocol* instantiate_outbound_protocol(
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
@@ -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 <MailFilter.h>
#include <MailSettings.h>
#include <MailSettingsView.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
@@ -20,7 +21,7 @@
#include <FileConfigView.h>
#include "RuleFilter.h"
#include "MatchHeaderSettings.h"
#undef B_TRANSLATION_CONTEXT
@@ -33,13 +34,15 @@ using namespace BPrivate;
static const uint32 kMsgActionChanged = 'actC';
class RuleFilterConfig : public BView {
class RuleFilterConfig : public BMailSettingsView {
public:
RuleFilterConfig(const BMessage& settings);
RuleFilterConfig(
const BMailAddOnSettings& settings);
virtual status_t SaveInto(BMailAddOnSettings& settings) const;
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
virtual status_t Archive(BMessage* into, bool deep = true) const;
private:
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)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
if (settings.HasInt32("do_what"))
fAction = settings.FindInt32("do_what");
else
fAction = -1;
MatchHeaderSettings settings(addOnSettings);
fAction = settings.Action();
fAttributeControl = new BTextControl("attr", B_TRANSLATE("If"),
B_TRANSLATE("header (e.g. Subject)"), NULL);
if (settings.HasString("attribute"))
fAttributeControl->SetText(settings.FindString("attribute"));
fAttributeControl->SetText(settings.Attribute());
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);
if (settings.HasString("regex"))
fRegexControl->SetText(settings.FindString("regex"));
fRegexControl->SetText(settings.Expression());
fFileControl = new FileControl("arg", NULL,
B_TRANSLATE("this field is based on the action"));
if (BControl* control = (BControl*)fFileControl->FindView("select_file"))
control->SetEnabled(false);
if (fAction == ACTION_MOVE_TO && settings.HasString("argument"))
fFileControl->SetText(settings.FindString("argument"));
fFileControl->SetText(settings.MoveTarget());
fFlagsControl = new BTextControl("flags", NULL, NULL);
if (fAction == ACTION_SET_FLAGS_TO && settings.HasString("argument"))
fFlagsControl->SetText(settings.FindString("argument"));
fFlagsControl->SetText(settings.SetFlagsTo());
// Populate account menu
fAccountMenu = new BPopUpMenu(B_TRANSLATE("<Choose account>"));
if (fAction == ACTION_REPLY_WITH)
fAccountID = settings.FindInt32("argument");
else
fAccountID = -1;
fAccountID = settings.ReplyAccount();
BMailAccounts accounts;
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));
}
BMenuField* actionField = new BMenuField("do_what", B_TRANSLATE("Then"),
BMenuField* actionField = new BMenuField("action", B_TRANSLATE("Then"),
fActionMenu);
// 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
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
RuleFilterConfig::MessageReceived(BMessage* message)
{
@@ -224,8 +229,9 @@ RuleFilterConfig::_SetVisible(BView* view, bool visible)
// #pragma mark -
BView*
instantiate_filter_config_panel(BMailAddOnSettings& settings)
BMailSettingsView*
instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& 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 "MatchHeaderSettings.h"
#undef B_TRANSLATION_CONTEXT
#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
settings->FindString("attribute", &fAttribute);
fAttribute = settings.Attribute();
fAttribute.CapitalizeEachWord();
settings->FindString("regex", &fExpression);
fExpression = settings.Expression();
int32 index = fExpression.FindFirst("REGEX:");
if (index == B_ERROR || index > 0)
EscapeRegexTokens(fExpression);
@@ -44,20 +49,10 @@ RuleFilter::RuleFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
fMatcher.SetPattern(fExpression, false);
settings->FindString("argument", &fArg);
settings->FindInt32("do_what", (int32*)&fAction);
if (fAction == ACTION_REPLY_WITH)
settings->FindInt32("argument", &fReplyAccount);
}
BString
RuleFilter::DescriptiveName() const
{
BString name(B_TRANSLATE("Match \"%attribute\" against \"%regex\""));
name.ReplaceAll("%attribute", fAttribute);
name.ReplaceAll("%regex", fExpression);
return name;
fAction = settings.Action();
fMoveTarget = settings.MoveTarget();
fSetFlags = settings.SetFlagsTo();
fReplyAccount = settings.ReplyAccount();
}
@@ -89,7 +84,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
switch (fAction) {
case ACTION_MOVE_TO:
{
BDirectory dir(fArg);
BDirectory dir(fMoveTarget);
// TODO: move is currently broken!
// fMailProtocol.Looper()->TriggerFileMove(ref, dir);
break;
@@ -100,7 +95,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
break;
case ACTION_SET_FLAGS_TO:
file->WriteAttrString("MAIL:filter_flags", &fArg);
file->WriteAttrString("MAIL:filter_flags", &fSetFlags);
break;
case ACTION_REPLY_WITH:
@@ -126,14 +121,25 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
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*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings)
{
return new RuleFilter(protocol, settings);
}
@@ -12,24 +12,14 @@
#include <List.h>
#include <MailFilter.h>
#include "MatchHeaderSettings.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 {
public:
RuleFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual BString DescriptiveName() const;
const BMailAddOnSettings& settings);
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
@@ -38,7 +28,8 @@ private:
BString fAttribute;
BString fExpression;
StringMatcher fMatcher;
BString fArg;
BString fMoveTarget;
BString fSetFlags;
int32 fReplyAccount;
rule_action fAction;
};
@@ -30,7 +30,7 @@ const uint32 kMsgNotifyMethod = 'nomt';
NotifierConfigView::NotifierConfigView()
:
BView("notifier_config", 0)
BMailSettingsView("notifier_config")
{
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
NotifierConfigView::SetTo(const BMessage *archive)
{
@@ -77,12 +69,38 @@ NotifierConfigView::SetTo(const BMessage *archive)
BMenuItem *item = field->Menu()->ItemAt(i);
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
NotifierConfigView::UpdateNotifyText()
NotifierConfigView::AttachedToWindow()
{
if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify")))
field->Menu()->SetTargetForItems(this);
}
void
NotifierConfigView::_UpdateNotifyText()
{
BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
@@ -115,7 +133,7 @@ NotifierConfigView::MessageReceived(BMessage *msg)
break;
item->SetMarked(!item->IsMarked());
UpdateNotifyText();
_UpdateNotifyText();
break;
}
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 -
BView*
instantiate_filter_config_panel(BMailAddOnSettings& settings)
BMailSettingsView*
instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{
NotifierConfigView *view = new NotifierConfigView();
NotifierConfigView* view = new NotifierConfigView();
view->SetTo(&settings);
return view;
}
@@ -8,7 +8,7 @@
#define NOTIFIER_CONFIG_VIEW_H
#include <View.h>
#include <MailSettingsView.h>
enum {
@@ -21,18 +21,19 @@ enum {
};
class NotifierConfigView : public BView {
class NotifierConfigView : public BMailSettingsView {
public:
NotifierConfigView();
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 MessageReceived(BMessage *msg);
void UpdateNotifyText();
private:
void _UpdateNotifyText();
};
@@ -31,9 +31,7 @@
class NotifyFilter : public BMailFilter {
public:
NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual BString DescriptiveName() const;
const BMailAddOnSettings& settings);
void HeaderFetched(const entry_ref& ref,
BFile* file);
@@ -46,19 +44,12 @@ private:
NotifyFilter::NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings)
const BMailAddOnSettings& settings)
:
BMailFilter(protocol, settings),
BMailFilter(protocol, &settings),
fNNewMessages(0)
{
fStrategy = settings->FindInt32("notification_method");
}
BString
NotifyFilter::DescriptiveName() const
{
return filter_name();
fStrategy = settings.FindInt32("notification_method");
}
@@ -130,14 +121,15 @@ NotifyFilter::MailboxSynchronized(status_t status)
BString
filter_name()
filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* addOnSettings)
{
return B_TRANSLATE("New mails notification");
}
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& 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 2011, Clemens Zeidler <[email protected]>
* 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";
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 = false;
if (settings->FindBool("AutoTraining", &fAutoTraining) != B_OK)
fAutoTraining = true;
if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK)
fGenuineCutoffRatio = 0.01f;
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;
fAddSpamToSubject = settings.GetBool("AddMarkerToSubject", false);
fAutoTraining = settings.GetBool("AutoTraining", true);
fGenuineCutoffRatio = settings.GetFloat("GenuineCutoffRatio", 0.01f);
fNoWordsMeansSpam = settings.GetBool("NoWordsMeansSpam", true);
fQuitServerWhenFinished = settings.GetBool("QuitServerWhenFinished", false);
fSpamCutoffRatio = settings.GetFloat("SpamCutoffRatio", 0.99f);
}
@@ -72,13 +66,6 @@ SpamFilter::~SpamFilter()
}
BString
SpamFilter::DescriptiveName() const
{
return filter_name();
}
void
SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
@@ -327,14 +314,15 @@ SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
BString
filter_name()
filter_name(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* addOnSettings)
{
return B_TRANSLATE("Bayesian Spam Filter");
}
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
instantiate_filter(BMailProtocol& protocol, const BMailAddOnSettings& settings)
{
return new SpamFilter(protocol, settings);
}
@@ -15,11 +15,9 @@
class SpamFilter : public BMailFilter {
public:
SpamFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
const BMailAddOnSettings& settings);
virtual ~SpamFilter();
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file);
@@ -18,6 +18,8 @@
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <MailFilter.h>
#include <MailSettingsView.h>
#include <Message.h>
#include <Messenger.h>
#include <Roster.h>
@@ -27,7 +29,6 @@
#include <Entry.h>
#include <Path.h>
#include <MailFilter.h>
#include <FileConfigView.h>
@@ -35,11 +36,11 @@
#define B_TRANSLATION_CONTEXT "SpamFilterConfig"
class SpamFilterConfig : public BView {
class SpamFilterConfig : public BMailSettingsView {
public:
SpamFilterConfig(const BMessage* settings);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual status_t SaveInto(BMailAddOnSettings& settings) const;
private:
BCheckBox* fSubjectHintCheckBox;
@@ -54,7 +55,7 @@ private:
SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
:
BView("spamfilter_config", 0),
BMailSettingsView("spamfilter_config"),
fSubjectHintCheckBox(NULL),
fAutoTrainingCheckBox(NULL),
fGenuineCutoffRatioTextControl(NULL),
@@ -116,27 +117,27 @@ SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
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);
if (status == B_OK) {
status = into->AddBool("AutoTraining",
status = settings.AddBool("AutoTraining",
fAutoTrainingCheckBox->Value() == B_CONTROL_ON);
}
if (status == B_OK) {
status = into->AddBool("NoWordsMeansSpam",
status = settings.AddBool("NoWordsMeansSpam",
fNoWordsMeansSpamCheckBox->Value() == B_CONTROL_ON);
}
if (status == B_OK) {
status = into->AddFloat("GenuineCutoffRatio",
status = settings.AddFloat("GenuineCutoffRatio",
atof(fGenuineCutoffRatioTextControl->Text()));
}
if (status == B_OK) {
status = into->AddFloat("SpamCutoffRatio",
status = settings.AddFloat("SpamCutoffRatio",
atof(fSpamCutoffRatioTextControl->Text()));
}
@@ -147,8 +148,9 @@ SpamFilterConfig::Archive(BMessage* into, bool /*deep*/) const
// #pragma mark -
BView*
instantiate_filter_config_panel(BMailAddOnSettings& settings)
BMailSettingsView*
instantiate_filter_settings_view(const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings)
{
return new SpamFilterConfig(&settings);
}
+1
View File
@@ -29,6 +29,7 @@ local sources =
MailMessage.cpp
MailProtocol.cpp
MailSettings.cpp
MailSettingsView.cpp
NodeMessage.cpp
numailkit.cpp
ProtocolConfigView.cpp
+2 -1
View File
@@ -6,7 +6,8 @@
#include <MailFilter.h>
BMailFilter::BMailFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
BMailFilter::BMailFilter(BMailProtocol& protocol,
const BMailAddOnSettings* settings)
:
fMailProtocol(protocol),
fSettings(settings)
+7 -7
View File
@@ -305,7 +305,7 @@ BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
{
for (int i = 0; i < settings.CountFilterSettings(); i++) {
BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
BMailFilter* filter = _LoadFilter(filterSettings);
BMailFilter* filter = _LoadFilter(*filterSettings);
if (filter != NULL)
AddFilter(filter);
}
@@ -313,9 +313,9 @@ BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
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);
image_id image;
if (it != fFilterImages.end())
@@ -328,16 +328,16 @@ BMailProtocol::_LoadFilter(BMailAddOnSettings* filterSettings)
if (image < 0)
return NULL;
BMailFilter* (*instantiate_filter)(BMailProtocol& protocol,
BMailAddOnSettings* settings);
BMailFilter* (*instantiateFilter)(BMailProtocol& protocol,
const BMailAddOnSettings& settings);
if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT,
(void**)&instantiate_filter) != B_OK) {
(void**)&instantiateFilter) != B_OK) {
unload_add_on(image);
return NULL;
}
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();
Append(settings);
puts("settings:");
settings.PrintToStream();
fOriginalSettings = *this;
fOriginalRef = fRef;
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2012, Axel Dörfler, axeld@pinc-software.de.
* 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
{
int32 index = -1;
if (field != NULL) {
if (field != NULL && field->Menu() != NULL) {
BMenuItem* item = field->Menu()->FindMarked();
if (item != NULL)
index = field->Menu()->IndexOf(item);
+21 -17
View File
@@ -120,17 +120,18 @@ AccountConfigView::UpdateViews()
// #pragma mark -
ProtocolConfigView::ProtocolConfigView(BMailAccountSettings& accountSettings,
const entry_ref& ref, BMailProtocolSettings& settings)
ProtocolSettingsView::ProtocolSettingsView(const entry_ref& ref,
const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings)
:
BBox("protocol"),
fSettings(settings),
fConfigView(NULL)
fSettingsView(NULL)
{
status_t status = _CreateConfigView(ref, settings, accountSettings);
BView* view = fConfigView;
status_t status = _CreateSettingsView(ref, accountSettings, settings);
BView* view = fSettingsView;
if (fConfigView != NULL) {
if (status == B_OK) {
SetLabel(ref.name);
} else {
BString text(B_TRANSLATE("An error occurred while creating the "
@@ -151,30 +152,33 @@ ProtocolConfigView::ProtocolConfigView(BMailAccountSettings& accountSettings,
void
ProtocolConfigView::DetachedFromWindow()
ProtocolSettingsView::DetachedFromWindow()
{
if (fConfigView == NULL)
if (fSettingsView == NULL)
return;
BMessage settings;
if (fConfigView->Archive(&settings) != B_OK)
if (fSettingsView->Archive(&settings) != B_OK)
return;
fSettings.MakeEmpty();
fSettings.Append(settings);
RemoveChild(fConfigView);
delete fConfigView;
fConfigView = NULL;
RemoveChild(fSettingsView);
delete fSettingsView;
fSettingsView = NULL;
unload_add_on(fImage);
}
status_t
ProtocolConfigView::_CreateConfigView(const entry_ref& ref,
BMailProtocolSettings& settings, BMailAccountSettings& accountSettings)
ProtocolSettingsView::_CreateSettingsView(const entry_ref& ref,
const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings)
{
BView* (*instantiateConfig)(BMailProtocolSettings& settings,
BMailAccountSettings& accountSettings);
BMailSettingsView* (*instantiateConfig)(
const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings);
BPath path(&ref);
image_id image = load_add_on(path.Path());
if (image < 0)
@@ -187,6 +191,6 @@ ProtocolConfigView::_CreateConfigView(const entry_ref& ref,
}
fImage = image;
fConfigView = instantiateConfig(settings, accountSettings);
fSettingsView = instantiateConfig(accountSettings, settings);
return B_OK;
}
+11 -9
View File
@@ -12,8 +12,11 @@
#include <Box.h>
#include <image.h>
#include "MailSettings.h"
#include <MailSettingsView.h>
#include <MailSettings.h>
#include <ProtocolConfigView.h>
#include "FilterConfigView.h"
@@ -43,23 +46,22 @@ private:
};
class ProtocolConfigView : public BBox {
class ProtocolSettingsView : public BBox {
public:
ProtocolConfigView(
BMailAccountSettings& accountSettings,
const entry_ref& ref,
ProtocolSettingsView(const entry_ref& ref,
const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings);
void DetachedFromWindow();
private:
status_t _CreateConfigView(const entry_ref& ref,
BMailProtocolSettings& settings,
BMailAccountSettings& accountSettings);
status_t _CreateSettingsView(const entry_ref& ref,
const BMailAccountSettings& accountSettings,
BMailProtocolSettings& settings);
private:
BMailProtocolSettings& fSettings;
BView* fConfigView;
BMailSettingsView* fSettingsView;
image_id fImage;
};
+4 -4
View File
@@ -831,13 +831,13 @@ ConfigWindow::_AccountSelected(AccountItem* item)
break;
case INBOUND_ITEM:
view = new ProtocolConfigView(*account, account->InboundAddOnRef(),
account->InboundSettings());
view = new ProtocolSettingsView(account->InboundAddOnRef(),
*account, account->InboundSettings());
break;
case OUTBOUND_ITEM:
view = new ProtocolConfigView(*account, account->OutboundAddOnRef(),
account->OutboundSettings());
view = new ProtocolSettingsView(account->OutboundAddOnRef(),
*account, account->OutboundSettings());
break;
case FILTER_ITEM:
+33 -35
View File
@@ -177,29 +177,30 @@ private:
// #pragma mark -
class FilterConfigBox : public BBox {
class FilterSettingsView : public BBox {
public:
FilterConfigBox(const BString& label, BView* child)
FilterSettingsView(const BString& label, BMailSettingsView* settingsView)
:
BBox(BRect(0,0,100,100)),
fChild(child)
BBox("filter"),
fSettingsView(settingsView)
{
SetLabel(label);
float w = child->Bounds().Width();
float h = child->Bounds().Height();
child->MoveTo(3, 13);
ResizeTo(w + 6, h + 16);
AddChild(child);
BView* contents = new BView("contents", 0);
AddChild(contents);
BLayoutBuilder::Group<>(contents, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fSettingsView);
}
status_t
ArchiveAddOn(BMessage* into) const
status_t SaveInto(BMailAddOnSettings& settings) const
{
return fChild->Archive(into);
return fSettingsView->SaveInto(settings);
}
private:
BView* fChild;
BMailSettingsView* fSettingsView;
};
@@ -211,8 +212,8 @@ FiltersConfigView::FiltersConfigView(BMailAccountSettings& account)
BBox("filters"),
fAccount(account),
fDirection(kIncoming),
fInboundFilters(kIncoming, false),
fOutboundFilters(kOutgoing, false),
fInboundFilters(kIncoming),
fOutboundFilters(kOutgoing),
fFilterView(NULL),
fCurrentIndex(-1)
{
@@ -284,11 +285,12 @@ FiltersConfigView::_SelectFilter(int32 index)
= _MailSettings()->FilterSettingsAt(index);
if (filterSettings != NULL) {
::FilterList* filters = _FilterList();
BView* view = filters->CreateConfigView(*filterSettings);
BMailSettingsView* view = filters->CreateSettingsView(fAccount,
*filterSettings);
if (view != NULL) {
BString name;
filters->GetDescriptiveName(filterSettings->AddOnRef(), name);
fFilterView = new FilterConfigBox(name, view);
fFilterView = new FilterSettingsView(
filters->DescriptiveName(filterSettings->AddOnRef(),
fAccount, NULL), view);
Parent()->AddChild(fFilterView);
}
}
@@ -320,31 +322,30 @@ FiltersConfigView::_SetDirection(direction direction)
for (int32 i = 0; i < protocolSettings->CountFilterSettings(); i++) {
BMailAddOnSettings* settings = protocolSettings->FilterSettingsAt(i);
if (filters->InfoIndexFor(settings->AddOnRef()) < 0) {
fprintf(stderr, "Removed missing filter: %s\n",
settings->AddOnRef().name);
protocolSettings->RemoveFilterSettings(i);
i--;
continue;
}
BString name = "Unnamed Filter";
filters->GetDescriptiveName(settings->AddOnRef(), name);
fListView->AddItem(new BStringItem(name));
fListView->AddItem(new BStringItem(filters->DescriptiveName(
settings->AddOnRef(), fAccount, settings)));
}
// remove old filter items
BMenu *menu = fAddField->Menu();
BMenu* menu = fAddField->Menu();
for (int32 i = menu->CountItems(); i-- > 0;) {
BMenuItem *item = menu->RemoveItem(i);
delete item;
}
filters->Reload();
for (int32 i = 0; i < filters->CountInfos(); i++) {
FilterInfo& info = filters->InfoAt(i);
BString name;
filters->GetDescriptiveName(i, name);
const FilterInfo& info = filters->InfoAt(i);
BMessage* msg = new BMessage(kMsgAddFilter);
msg->AddRef("filter", &info.ref);
BMenuItem *item = new BMenuItem(name, msg);
BMenuItem* item = new BMenuItem(filters->SimpleName(i, fAccount), msg);
menu->AddItem(item);
}
@@ -391,15 +392,12 @@ FiltersConfigView::MessageReceived(BMessage *msg)
if (msg->FindRef("filter", &ref) != B_OK)
break;
::FilterList* filters = _FilterList();
int32 index = filters->InfoIndexFor(ref);
int32 index = _MailSettings()->AddFilterSettings(&ref);
if (index < 0)
break;
_MailSettings()->AddFilterSettings(&ref);
BString name;
filters->GetDescriptiveName(index, name);
fListView->AddItem(new BStringItem(name));
fListView->AddItem(new BStringItem(_FilterList()->DescriptiveName(
ref, fAccount, _MailSettings()->FilterSettingsAt(index))));
break;
}
case kMsgRemoveFilter:
@@ -470,6 +468,6 @@ FiltersConfigView::_SaveConfig(int32 index)
if (fFilterView != NULL) {
BMailAddOnSettings* settings = _MailSettings()->FilterSettingsAt(index);
if (settings != NULL)
fFilterView->ArchiveAddOn(settings);
fFilterView->SaveInto(*settings);
}
}
+4 -3
View File
@@ -20,7 +20,7 @@
#include "FilterList.h"
class FilterConfigBox;
class FilterSettingsView;
class FiltersConfigView : public BBox {
@@ -52,9 +52,10 @@ private:
BListView* fListView;
BMenuField* fAddField;
BButton* fRemoveButton;
FilterConfigBox* fFilterView;
FilterSettingsView* fFilterView;
int32 fCurrentIndex;
};
#endif //FILTER_CONFIG_VIEW_H
#endif // FILTER_CONFIG_VIEW_H
+97 -67
View File
@@ -7,17 +7,17 @@
#include "FilterList.h"
#include <set>
#include <Directory.h>
#include <FindDirectory.h>
#include <Path.h>
FilterList::FilterList(direction dir, bool loadOnStart)
FilterList::FilterList(direction dir)
:
fDirection(dir)
{
if (loadOnStart)
Reload();
}
@@ -32,91 +32,116 @@ FilterList::Reload()
{
_MakeEmpty();
BPath path;
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");
std::set<BString> knownNames;
BDirectory dir(path.Path());
if (dir.InitCheck() != B_OK)
return;
BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK)
_LoadAddOn(entry);
directory_which which[] = {B_USER_ADDONS_DIRECTORY,
B_COMMON_ADDONS_DIRECTORY,
B_SYSTEM_ADDONS_DIRECTORY};
for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
BPath path;
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
FilterList::CountInfos()
FilterList::CountInfos() const
{
return fList.size();
}
FilterInfo&
FilterList::InfoAt(int32 index)
const FilterInfo&
FilterList::InfoAt(int32 index) const
{
return fList[index];
}
bool
FilterList::GetDescriptiveName(int32 index, BString& name)
int32
FilterList::InfoIndexFor(const entry_ref& ref) const
{
if (index < 0)
return false;
FilterInfo& info = InfoAt(index);
BString (*descriptive_name)();
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;
for (size_t i = 0; i < fList.size(); i++) {
const FilterInfo& info = fList[i];
if (info.ref == ref)
return i;
}
return -1;
}
bool
FilterList::GetDescriptiveName(const entry_ref& ref, BString& name)
BString
FilterList::SimpleName(int32 index,
const BMailAccountSettings& accountSettings) const
{
int32 index = InfoIndexFor(ref);
return GetDescriptiveName(index, name);
return DescriptiveName(index, accountSettings, NULL);
}
BView*
FilterList::CreateConfigView(BMailAddOnSettings& settings)
BString
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();
int32 index = InfoIndexFor(ref);
if (index < 0)
return NULL;
FilterInfo& info = InfoAt(index);
BView* (*instantiateFilterConfigPanel)(BMailAddOnSettings&);
if (get_image_symbol(info.image, "instantiate_filter_config_panel",
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;
const FilterInfo& info = InfoAt(index);
return info.instantiateSettingsView(accountSettings, settings);
}
@@ -131,7 +156,7 @@ FilterList::_MakeEmpty()
}
void
status_t
FilterList::_LoadAddOn(BEntry& entry)
{
FilterInfo info;
@@ -139,17 +164,22 @@ FilterList::_LoadAddOn(BEntry& entry)
BPath path(&entry);
info.image = load_add_on(path.Path());
if (info.image < 0)
return;
return info.image;
BView* (*instantiateFilterConfigPanel)(BMailProtocolSettings&);
if (get_image_symbol(info.image, "instantiate_filter_config_panel",
B_SYMBOL_TYPE_TEXT, (void **)&instantiateFilterConfigPanel)
!= B_OK) {
status_t status = get_image_symbol(info.image,
"instantiate_filter_settings_view", B_SYMBOL_TYPE_TEXT,
(void**)&info.instantiateSettingsView);
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);
return;
return B_NAME_NOT_FOUND;
}
entry.GetRef(&info.ref);
fList.push_back(info);
return B_OK;
}
+26 -12
View File
@@ -8,7 +8,7 @@
#include <MailSettings.h>
#include <View.h>
#include <MailSettingsView.h>
enum direction {
@@ -20,32 +20,46 @@ enum direction {
struct FilterInfo {
image_id image;
entry_ref ref;
BMailSettingsView* (*instantiateSettingsView)(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings);
BString (*name)(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings* settings);
};
class FilterList {
public:
FilterList(direction dir,
bool loadOnStart = true);
FilterList(direction dir);
~FilterList();
void Reload();
int32 CountInfos();
FilterInfo& InfoAt(int32 index);
int32 CountInfos() const;
const FilterInfo& InfoAt(int32 index) const;
int32 InfoIndexFor(const entry_ref& ref) const;
bool GetDescriptiveName(int32 index, BString& name);
bool GetDescriptiveName(const entry_ref& ref,
BString& name);
BString SimpleName(int32 index,
const BMailAccountSettings& settings) const;
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);
int32 InfoIndexFor(const entry_ref& ref);
BMailSettingsView* CreateSettingsView(
const BMailAccountSettings& accountSettings,
const BMailAddOnSettings& settings);
private:
void _MakeEmpty();
void _LoadAddOn(BEntry& entry);
status_t _LoadAddOn(BEntry& entry);
private:
direction fDirection;
std::vector<FilterInfo> fList;
};