fix 66771 add match all search term for filters and virtual folders, sr=mscott
This commit is contained in:
Родитель
ee7d824917
Коммит
28402a3247
|
@ -1016,6 +1016,11 @@ function getSearchTermString(searchTerms)
|
|||
if (condition.length > 1)
|
||||
condition += ' ';
|
||||
|
||||
if (term.matchAll)
|
||||
{
|
||||
condition = "ALL";
|
||||
break;
|
||||
}
|
||||
condition += (term.booleanAnd) ? "AND (" : "OR (";
|
||||
condition += term.termAsString + ')';
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<!ENTITY matchAll.accesskey "a">
|
||||
<!ENTITY matchAny.label "Match any of the following">
|
||||
<!ENTITY matchAny.accesskey "o">
|
||||
<!ENTITY matchAllMsgs.label "Match all messages">
|
||||
<!ENTITY matchAllMsgs.accesskey "m">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
The values below are used to control the widths of the search widgets.
|
||||
|
|
|
@ -1040,6 +1040,11 @@ function getSearchTermString(searchTerms)
|
|||
if (condition.length > 1)
|
||||
condition += ' ';
|
||||
|
||||
if (term.matchAll)
|
||||
{
|
||||
condition = "ALL";
|
||||
break;
|
||||
}
|
||||
condition += (term.booleanAnd) ? "AND (" : "OR (";
|
||||
condition += term.termAsString + ')';
|
||||
}
|
||||
|
|
|
@ -55,8 +55,8 @@ interface nsIMsgSearchTerm : nsISupports {
|
|||
attribute boolean booleanAnd;
|
||||
attribute string arbitraryHeader;
|
||||
|
||||
attribute boolean beginsGrouping;
|
||||
attribute boolean endsGrouping;
|
||||
attribute boolean beginsGrouping;
|
||||
attribute boolean endsGrouping;
|
||||
|
||||
boolean matchRfc822String(in string aString, in string charset, in boolean charsetOverride);
|
||||
boolean matchRfc2047String(in string aString, in string charset, in boolean charsetOverride);
|
||||
|
@ -65,8 +65,8 @@ interface nsIMsgSearchTerm : nsISupports {
|
|||
boolean matchPriority(in nsMsgPriorityValue priority);
|
||||
boolean matchAge(in PRTime days);
|
||||
boolean matchSize(in unsigned long size);
|
||||
boolean matchLabel(in nsMsgLabelValue aLabelValue);
|
||||
boolean matchJunkStatus(in string aJunkScore);
|
||||
boolean matchLabel(in nsMsgLabelValue aLabelValue);
|
||||
boolean matchJunkStatus(in string aJunkScore);
|
||||
|
||||
boolean matchBody(in nsIMsgSearchScopeTerm scopeTerm,
|
||||
in unsigned long offset,
|
||||
|
@ -93,5 +93,6 @@ interface nsIMsgSearchTerm : nsISupports {
|
|||
readonly attribute boolean matchAllBeforeDeciding;
|
||||
|
||||
readonly attribute ACString termAsString;
|
||||
attribute boolean matchAll;
|
||||
};
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
nsMsgSearchBooleanOperator m_booleanOp; // boolean operator to be applied to this search term and the search term which precedes it.
|
||||
nsCString m_arbitraryHeader; // user specified string for the name of the arbitrary header to be used in the search
|
||||
// only has a value when m_attribute = attribOtherHeader!!!!
|
||||
PRBool m_matchAll; // does this term match all headers?
|
||||
|
||||
protected:
|
||||
nsresult MatchString (const char *stringToMatch, const char *charset,
|
||||
|
|
|
@ -314,7 +314,8 @@ function initializeSearchWindowWidgets()
|
|||
gFolderPicker = document.getElementById("searchableFolders");
|
||||
gSearchStopButton = document.getElementById("search-button");
|
||||
gStatusBar = document.getElementById('statusbar-icon');
|
||||
|
||||
hideMatchAllItem();
|
||||
|
||||
msgWindow = Components.classes[msgWindowContractID].createInstance(nsIMsgWindow);
|
||||
msgWindow.statusFeedback = gStatusFeedback;
|
||||
msgWindow.SetDOMWindow(window);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Alec Flett <alecf@netscape.com>
|
||||
* Seth Spitzer <sspitzer@netscape.com>
|
||||
* David Bienvenu <bienvenu@nventure.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -142,6 +143,7 @@ searchTermContainer.prototype = {
|
|||
this.searchvalue.saveTo(searchTerm.value);
|
||||
searchTerm.value = this.searchvalue.value;
|
||||
searchTerm.booleanAnd = this.booleanAnd;
|
||||
searchTerm.matchAll = this.matchAll;
|
||||
},
|
||||
// if you have a search term element with no search term
|
||||
saveTo: function(searchTerm) {
|
||||
|
@ -166,13 +168,21 @@ function initializeSearchWidgets()
|
|||
function initializeBooleanWidgets()
|
||||
{
|
||||
var booleanAnd = true;
|
||||
var matchAll = false;
|
||||
// get the boolean value from the first term
|
||||
var firstTerm = gSearchTerms[0].searchTerm;
|
||||
if (firstTerm)
|
||||
{
|
||||
booleanAnd = firstTerm.booleanAnd;
|
||||
|
||||
// target radio items have value="and" or value="or"
|
||||
gSearchBooleanRadiogroup.value = booleanAnd ? "and" : "or";
|
||||
matchAll = firstTerm.matchAll;
|
||||
}
|
||||
// target radio items have value="and" or value="or" or "all"
|
||||
gSearchBooleanRadiogroup.value = matchAll
|
||||
? "matchAll"
|
||||
: (booleanAnd ? "and" : "or")
|
||||
var searchTerms = document.getElementById("searchTermList");
|
||||
if (searchTerms)
|
||||
searchTerms.hidden = matchAll;
|
||||
}
|
||||
|
||||
function initializeSearchRows(scope, searchTerms)
|
||||
|
@ -257,6 +267,7 @@ function updateSearchAttributes()
|
|||
function booleanChanged(event) {
|
||||
// when boolean changes, we have to update all the attributes on the search terms
|
||||
var newBoolValue = (event.target.getAttribute("value") == "and") ? true : false;
|
||||
var matchAllValue = (event.target.getAttribute("value") == "matchAll") ? true : false;
|
||||
if (document.getElementById("abPopup")) {
|
||||
var selectedAB = document.getElementById("abPopup").selectedItem.id;
|
||||
setSearchScope(GetScopeForDirectoryURI(selectedAB));
|
||||
|
@ -264,6 +275,14 @@ function booleanChanged(event) {
|
|||
for (var i=0; i<gSearchTerms.length; i++) {
|
||||
var searchTerm = gSearchTerms[i].obj;
|
||||
searchTerm.booleanAnd = newBoolValue;
|
||||
searchTerm.matchAll = matchAllValue;
|
||||
}
|
||||
var searchTerms = document.getElementById("searchTermList");
|
||||
if (searchTerms)
|
||||
{
|
||||
if (!matchAllValue && searchTerms.hidden)
|
||||
onMore(null); // fake to get empty row.
|
||||
searchTerms.hidden = matchAllValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,6 +471,7 @@ function removeSearchRow(index)
|
|||
// via XPCOM)
|
||||
function saveSearchTerms(searchTerms, termOwner)
|
||||
{
|
||||
var matchAll = gSearchBooleanRadiogroup.value == 'matchAll';
|
||||
var i;
|
||||
for (i = 0; i<gSearchTerms.length; i++) {
|
||||
try {
|
||||
|
@ -463,7 +483,7 @@ function saveSearchTerms(searchTerms, termOwner)
|
|||
// is an existing term, but not initialize, so skip saving
|
||||
continue;
|
||||
}
|
||||
|
||||
searchTerm.matchAll = matchAll;
|
||||
if (searchTerm)
|
||||
gSearchTerms[i].obj.save();
|
||||
else {
|
||||
|
@ -485,7 +505,6 @@ function saveSearchTerms(searchTerms, termOwner)
|
|||
gSearchRemovedTerms[i].QueryInterface(Components.interfaces.nsISupports);
|
||||
searchTerms.RemoveElement(searchTermSupports);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onReset(event)
|
||||
|
@ -495,6 +514,13 @@ function onReset(event)
|
|||
onMore(null);
|
||||
}
|
||||
|
||||
function hideMatchAllItem()
|
||||
{
|
||||
var allItems = document.getElementById('matchAllItem');
|
||||
if (allItems)
|
||||
allItems.hidden = true;
|
||||
}
|
||||
|
||||
// this is a helper routine used by our search term xbl widget
|
||||
var gLabelStrings = new Array;
|
||||
function GetLabelStrings()
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
selectedItem="or" oncommand="booleanChanged(event);">
|
||||
<radio value="and" label="&matchAll.label;" accesskey="&matchAll.accesskey;"/>
|
||||
<radio selected="true" value="or" label="&matchAny.label;" accesskey="&matchAny.accesskey;"/>
|
||||
<radio value="matchAll" id="matchAllItem" label="&matchAllMsgs.label;" accesskey="&matchAllMsgs.accesskey;"/>
|
||||
</radiogroup>
|
||||
|
||||
<hbox flex="1">
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!ENTITY matchAll.label "Match all of the following">
|
||||
<!ENTITY matchAll.accesskey "a">
|
||||
<!ENTITY matchAny.label "Match any of the following">
|
||||
<!ENTITY matchAny.accesskey "o">
|
||||
<!-- LOCALIZATION NOTE
|
||||
The values below are used to control the widths of the search widgets.
|
||||
Change the values only when the localized strings in the popup menus
|
||||
are truncated in the widgets.
|
||||
-->
|
||||
<!ENTITY searchTermListAttributesFlexValue "5">
|
||||
<!ENTITY searchTermListOperatorsFlexValue "5">
|
||||
<!ENTITY searchTermListValueFlexValue "5">
|
||||
<!ENTITY searchTermListButtonsFlexValue "2">
|
|
@ -749,33 +749,40 @@ nsresult nsMsgFilter::SaveRule(nsIOFileStream *aStream)
|
|||
PRUint32 count;
|
||||
m_termList->Count(&count);
|
||||
for (searchIndex = 0; searchIndex < count && NS_SUCCEEDED(err);
|
||||
searchIndex++)
|
||||
searchIndex++)
|
||||
{
|
||||
nsCAutoString stream;
|
||||
|
||||
|
||||
nsCOMPtr<nsIMsgSearchTerm> term;
|
||||
m_termList->QueryElementAt(searchIndex, NS_GET_IID(nsIMsgSearchTerm),
|
||||
(void **)getter_AddRefs(term));
|
||||
if (!term)
|
||||
continue;
|
||||
|
||||
|
||||
if (condition.Length() > 1)
|
||||
condition += ' ';
|
||||
|
||||
|
||||
PRBool booleanAnd;
|
||||
PRBool matchAll;
|
||||
term->GetBooleanAnd(&booleanAnd);
|
||||
if (booleanAnd)
|
||||
term->GetMatchAll(&matchAll);
|
||||
if (matchAll)
|
||||
{
|
||||
condition += "ALL";
|
||||
break;
|
||||
}
|
||||
else if (booleanAnd)
|
||||
condition += "AND (";
|
||||
else
|
||||
condition += "OR (";
|
||||
|
||||
|
||||
nsresult searchError = term->GetTermAsString(stream);
|
||||
if (NS_FAILED(searchError))
|
||||
{
|
||||
err = searchError;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
condition += stream;
|
||||
condition += ')';
|
||||
}
|
||||
|
|
|
@ -115,7 +115,6 @@ protected:
|
|||
PRPackedBool m_enabled;
|
||||
PRPackedBool m_temporary;
|
||||
PRPackedBool m_unparseable;
|
||||
|
||||
nsIMsgFilterList *m_filterList; /* owning filter list */
|
||||
nsCOMPtr<nsISupportsArray> m_termList; /* linked list of criteria terms */
|
||||
nsCOMPtr<nsIMsgSearchScopeTerm> m_scope; /* default for mail rules is inbox, but news rules could
|
||||
|
|
|
@ -719,11 +719,24 @@ nsresult nsMsgFilterList::LoadTextFilters(nsIOFileStream *aStream)
|
|||
// what about values with close parens and quotes? e.g., (body, isn't, "foo")")
|
||||
// I guess interior quotes will need to be escaped - ("foo\")")
|
||||
// which will get written out as (\"foo\\")\") and read in as ("foo\")"
|
||||
// ALL means match all messages.
|
||||
NS_IMETHODIMP nsMsgFilterList::ParseCondition(nsIMsgFilter *aFilter, const char *aCondition)
|
||||
{
|
||||
PRBool done = PR_FALSE;
|
||||
nsresult err = NS_OK;
|
||||
const char *curPtr = aCondition;
|
||||
if (!strcmp(aCondition, "ALL"))
|
||||
{
|
||||
nsMsgSearchTerm *newTerm = new nsMsgSearchTerm;
|
||||
|
||||
if (newTerm)
|
||||
{
|
||||
newTerm->m_matchAll = PR_TRUE;
|
||||
aFilter->AppendTerm(newTerm);
|
||||
}
|
||||
return (newTerm) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
while (!done)
|
||||
{
|
||||
// insert code to save the boolean operator if there is one for this search term....
|
||||
|
|
|
@ -441,9 +441,16 @@ nsresult nsMsgSearchOfflineMail::ProcessSearchTerm(nsIMsgDBHdr *msgToMatch,
|
|||
PRBool charsetOverride = PR_FALSE; /* XXX BUG 68706 */
|
||||
PRUint32 msgFlags;
|
||||
PRBool result;
|
||||
PRBool matchAll;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(pResult);
|
||||
|
||||
aTerm->GetMatchAll(&matchAll);
|
||||
if (matchAll)
|
||||
{
|
||||
*pResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
*pResult = PR_FALSE;
|
||||
|
||||
nsMsgSearchAttribValue attrib;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Seth Spitzer <sspitzer@netscape.com>
|
||||
* Jungshik Shin <jshin@mailaps.org>
|
||||
* David Bienvenu <bienvenu@nventure.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -342,6 +343,7 @@ nsMsgSearchTerm::nsMsgSearchTerm()
|
|||
m_attribute = nsMsgSearchAttrib::Default;
|
||||
mBeginsGrouping = PR_FALSE;
|
||||
mEndsGrouping = PR_FALSE;
|
||||
m_matchAll = PR_FALSE;
|
||||
}
|
||||
|
||||
nsMsgSearchTerm::nsMsgSearchTerm (
|
||||
|
@ -357,6 +359,7 @@ nsMsgSearchTerm::nsMsgSearchTerm (
|
|||
if (attrib > nsMsgSearchAttrib::OtherHeader && attrib < nsMsgSearchAttrib::kNumMsgSearchAttributes && arbitraryHeader)
|
||||
m_arbitraryHeader = arbitraryHeader;
|
||||
nsMsgResultElement::AssignValues (val, &m_value);
|
||||
m_matchAll = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -495,6 +498,11 @@ NS_IMETHODIMP nsMsgSearchTerm::GetTermAsString (nsACString &outStream)
|
|||
nsCAutoString outputStr;
|
||||
nsresult ret;
|
||||
|
||||
if (m_matchAll)
|
||||
{
|
||||
outStream = "ALL";
|
||||
return NS_OK;
|
||||
}
|
||||
ret = NS_MsgGetStringForAttribute(m_attribute, &attrib);
|
||||
if (ret != NS_OK)
|
||||
return ret;
|
||||
|
@ -641,18 +649,23 @@ nsMsgSearchTerm::ParseAttribute(char *inStream, nsMsgSearchAttribValue *attrib)
|
|||
|
||||
nsresult nsMsgSearchTerm::DeStreamNew (char *inStream, PRInt16 /*length*/)
|
||||
{
|
||||
char *commaSep = PL_strchr(inStream, ',');
|
||||
nsresult rv = ParseAttribute(inStream, &m_attribute); // will allocate space for arbitrary header if necessary
|
||||
if (!strcmp(inStream, "ALL"))
|
||||
{
|
||||
m_matchAll = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
char *commaSep = PL_strchr(inStream, ',');
|
||||
nsresult rv = ParseAttribute(inStream, &m_attribute); // will allocate space for arbitrary header if necessary
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!commaSep)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
char *secondCommaSep = PL_strchr(commaSep + 1, ',');
|
||||
if (commaSep)
|
||||
rv = ParseOperator(commaSep + 1, &m_operator);
|
||||
if (!commaSep)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
char *secondCommaSep = PL_strchr(commaSep + 1, ',');
|
||||
if (commaSep)
|
||||
rv = ParseOperator(commaSep + 1, &m_operator);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (secondCommaSep)
|
||||
ParseValue(secondCommaSep + 1);
|
||||
return NS_OK;
|
||||
if (secondCommaSep)
|
||||
ParseValue(secondCommaSep + 1);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1369,7 +1382,7 @@ nsresult nsMsgSearchTerm::InitHeaderAddressParser()
|
|||
|
||||
NS_IMPL_GETSET(nsMsgSearchTerm, Attrib, nsMsgSearchAttribValue, m_attribute)
|
||||
NS_IMPL_GETSET(nsMsgSearchTerm, Op, nsMsgSearchOpValue, m_operator)
|
||||
|
||||
NS_IMPL_GETSET(nsMsgSearchTerm, MatchAll, PRBool, m_matchAll)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgSearchTerm::GetValue(nsIMsgSearchValue **aResult)
|
||||
|
|
|
@ -118,6 +118,9 @@ function initializeMailViewOverrides()
|
|||
//orButton.setAttribute('label', 'Any of the following');
|
||||
//var andButton = document.getElementById('and');
|
||||
//andButton.setAttribute('label', 'All of the following');
|
||||
// matchAll doesn't make sense for views, since views are a single folder
|
||||
hideMatchAllItem();
|
||||
|
||||
}
|
||||
|
||||
function UpdateAfterCustomHeaderChange()
|
||||
|
|
Загрузка…
Ссылка в новой задаче