зеркало из https://github.com/mozilla/pjs.git
Bug 342065: wrong order of Tags; r=neil, sr=bienvenu
This commit is contained in:
Родитель
f92a2e42f9
Коммит
2cd6f3b234
|
@ -593,10 +593,10 @@ function ToggleMessageTagKey(index)
|
||||||
var msgHdr = gDBView.hdrForFirstSelectedMessage;
|
var msgHdr = gDBView.hdrForFirstSelectedMessage;
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
while (allKeys.hasMore())
|
for (var i = 0; i < tagArray.length; ++i)
|
||||||
{
|
{
|
||||||
var key = allKeys.getNext();
|
var key = tagArray[i].key;
|
||||||
if (!--index)
|
if (!--index)
|
||||||
{
|
{
|
||||||
// found the key, now toggle its state
|
// found the key, now toggle its state
|
||||||
|
@ -671,7 +671,7 @@ function AddTagCallback(name, color)
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
tagService.addTag(name, color);
|
tagService.addTag(name, color, '');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ToggleMessageTag(tagService.getKeyForTag(name), true);
|
ToggleMessageTag(tagService.getKeyForTag(name), true);
|
||||||
|
@ -700,8 +700,8 @@ function InitMessageTags(menuPopup)
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allTags = tagService.tagEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagCount = tagArray.length;
|
||||||
|
|
||||||
// remove any existing non-static entries...
|
// remove any existing non-static entries...
|
||||||
var menuseparator = menuPopup.lastChild.previousSibling;
|
var menuseparator = menuPopup.lastChild.previousSibling;
|
||||||
|
@ -709,7 +709,7 @@ function InitMessageTags(menuPopup)
|
||||||
menuPopup.removeChild(menuseparator.previousSibling);
|
menuPopup.removeChild(menuseparator.previousSibling);
|
||||||
|
|
||||||
// hide double menuseparator
|
// hide double menuseparator
|
||||||
menuseparator.previousSibling.hidden = !allTags.hasMore();
|
menuseparator.previousSibling.hidden = !tagCount;
|
||||||
|
|
||||||
// create label and accesskey for the static remove item
|
// create label and accesskey for the static remove item
|
||||||
var tagRemoveLabel = gMessengerBundle.getString("mailnews.tags.remove");
|
var tagRemoveLabel = gMessengerBundle.getString("mailnews.tags.remove");
|
||||||
|
@ -721,18 +721,16 @@ function InitMessageTags(menuPopup)
|
||||||
if (msgHdr.label)
|
if (msgHdr.label)
|
||||||
curKeys += " $label" + msgHdr.label;
|
curKeys += " $label" + msgHdr.label;
|
||||||
|
|
||||||
var index = 0;
|
for (var i = 0; i < tagCount; ++i)
|
||||||
while (allTags.hasMore())
|
|
||||||
{
|
{
|
||||||
var tag = allTags.getNext();
|
var taginfo = tagArray[i];
|
||||||
var key = allKeys.getNext();
|
|
||||||
// TODO we want to either remove or "check" the tags that already exist
|
// TODO we want to either remove or "check" the tags that already exist
|
||||||
var newMenuItem = document.createElement("menuitem");
|
var newMenuItem = document.createElement("menuitem");
|
||||||
SetMessageTagLabel(newMenuItem, ++index, tag);
|
SetMessageTagLabel(newMenuItem, i + 1, taginfo.tag);
|
||||||
newMenuItem.setAttribute("value", key);
|
newMenuItem.setAttribute("value", taginfo.key);
|
||||||
newMenuItem.setAttribute("type", "checkbox");
|
newMenuItem.setAttribute("type", "checkbox");
|
||||||
newMenuItem.style.color = tagService.getColorForKey(key);
|
newMenuItem.style.color = tagService.getColorForKey(taginfo.key);
|
||||||
var removeKey = (" " + curKeys + " ").indexOf(" " + key + " ") > -1;
|
var removeKey = (" " + curKeys + " ").indexOf(" " + taginfo.key + " ") > -1;
|
||||||
newMenuItem.setAttribute('checked', removeKey);
|
newMenuItem.setAttribute('checked', removeKey);
|
||||||
newMenuItem.setAttribute('oncommand', 'ToggleMessageTagMenu(event.target);');
|
newMenuItem.setAttribute('oncommand', 'ToggleMessageTagMenu(event.target);');
|
||||||
menuPopup.insertBefore(newMenuItem, menuseparator);
|
menuPopup.insertBefore(newMenuItem, menuseparator);
|
||||||
|
|
|
@ -79,13 +79,13 @@ var gDisplayPane = {
|
||||||
|
|
||||||
buildTagList: function()
|
buildTagList: function()
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"].getService(Components.interfaces.nsIMsgTagService);
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
var allTags = tagService.tagEnumerator;
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
while (allTags.hasMore())
|
for (var i = 0; i < tagArray.length; ++i)
|
||||||
{
|
{
|
||||||
var key = allKeys.getNext();
|
var taginfo = tagArray[i];
|
||||||
this.appendTagItem(allTags.getNext(), key, tagService.getColorForKey(key));
|
this.appendTagItem(taginfo.tag, taginfo.key, taginfo.color);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ var gDisplayPane = {
|
||||||
function addTagCallback(aName, aColor)
|
function addTagCallback(aName, aColor)
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"].getService(Components.interfaces.nsIMsgTagService);
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"].getService(Components.interfaces.nsIMsgTagService);
|
||||||
tagService.addTag(aName, aColor);
|
tagService.addTag(aName, aColor, '');
|
||||||
|
|
||||||
var item = gDisplayPane.appendTagItem(aName, tagService.getKeyForTag(aName), aColor);
|
var item = gDisplayPane.appendTagItem(aName, tagService.getKeyForTag(aName), aColor);
|
||||||
var tagListBox = document.getElementById('tagList');
|
var tagListBox = document.getElementById('tagList');
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* David Bienvenu <bienvenu@mozilla.com>
|
* David Bienvenu <bienvenu@mozilla.com>
|
||||||
|
* Karsten Düsterloh <mnyromyr@tprac.de>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -37,14 +38,13 @@
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIStringEnumerator.idl"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keys are the internal representation of tags, and use a limited range of
|
* Keys are the internal representation of tags, and use a limited range of
|
||||||
* characters, basically the characters allowed in imap keywords, which are
|
* characters, basically the characters allowed in imap keywords, which are
|
||||||
* alphanumeric characters, but don't include spaces. Keys are stored on
|
* alphanumeric characters, but don't include spaces. Keys are stored on
|
||||||
* the imap server, in local mail messages, and in summary files.
|
* the imap server, in local mail messages, and in summary files.
|
||||||
*
|
*
|
||||||
* Tags are the user visible representation of keys, and are full unicode
|
* Tags are the user visible representation of keys, and are full unicode
|
||||||
* strings. Tags should allow any unicode character.
|
* strings. Tags should allow any unicode character.
|
||||||
*
|
*
|
||||||
|
@ -55,18 +55,40 @@
|
||||||
* sure that no other keyword has the same value since that algorithm
|
* sure that no other keyword has the same value since that algorithm
|
||||||
* doesn't guarantee a unique mapping.
|
* doesn't guarantee a unique mapping.
|
||||||
*
|
*
|
||||||
|
* Tags are sorted internally by 'importance' by their ordinal strings (which by
|
||||||
|
* default are equal to a tag's key and thus only stored if different).
|
||||||
|
* The alphanumerically 'smallest' string is called the 'most important' one and
|
||||||
|
* comes first in any sorted array. The remainder follows in ascending order.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(ad04db53-cfcc-47eb-b409-b24b3a0b6130)]
|
|
||||||
interface nsIMsgTagService : nsISupports {
|
[scriptable, uuid(84d593a3-5d8a-45e6-96e2-9189acd422e1)]
|
||||||
AString getTagForKey(in ACString key); // look up the tag for a key.
|
interface nsIMsgTag : nsISupports {
|
||||||
void setTagForKey(in ACString key, in AString tag); // this can be used to "rename" a tag
|
readonly attribute ACString key; // distinct tag identifier
|
||||||
ACString getKeyForTag(in AString tag); // get the key representation of a given tag
|
readonly attribute AString tag; // human readable tag name
|
||||||
void addTagForKey(in ACString key, in AString tag, in ACString color);
|
readonly attribute ACString color; // tag color
|
||||||
void addTag(in AString tag, in ACString color);
|
readonly attribute ACString ordinal; // custom sort string (usually empty)
|
||||||
ACString getColorForKey(in ACString key);
|
|
||||||
void deleteKey(in ACString key);
|
|
||||||
// we need some way to enumerate all tags. Or return a list of all tags.
|
|
||||||
readonly attribute nsIStringEnumerator tagEnumerator;
|
|
||||||
readonly attribute nsIUTF8StringEnumerator keyEnumerator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(b897da55-8256-4cf5-892b-32e77bc7c50b)]
|
||||||
|
interface nsIMsgTagService : nsISupports {
|
||||||
|
// create new tag by deriving the key from the tag
|
||||||
|
void addTag(in AString tag, in ACString color, in ACString ordinal);
|
||||||
|
// create/update tag with known key
|
||||||
|
void addTagForKey(in ACString key, in AString tag, in ACString color, in ACString ordinal);
|
||||||
|
// get the key representation of a given tag
|
||||||
|
ACString getKeyForTag(in AString tag);
|
||||||
|
// get the first key by ordinal order
|
||||||
|
ACString getTopKey(in string keyList);
|
||||||
|
// support functions for single tag aspects
|
||||||
|
AString getTagForKey(in ACString key); // look up the tag for a key.
|
||||||
|
void setTagForKey(in ACString key, in AString tag); // this can be used to "rename" a tag
|
||||||
|
ACString getColorForKey(in ACString key);
|
||||||
|
void setColorForKey(in ACString key, in ACString color);
|
||||||
|
ACString getOrdinalForKey(in ACString key);
|
||||||
|
void setOrdinalForKey(in ACString key, in ACString ordinal);
|
||||||
|
// delete a tag from the list of known tags (but not from any messages)
|
||||||
|
void deleteKey(in ACString key);
|
||||||
|
// get all known tags
|
||||||
|
void getAllTags(out unsigned long count,
|
||||||
|
[retval, array, size_is(count)] out nsIMsgTag tagArray);
|
||||||
|
};
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* the Initial Developer. All Rights Reserved.
|
* the Initial Developer. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Karsten Düsterloh <mnyromyr@tprac.de>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -522,9 +523,10 @@
|
||||||
"@mozilla.org/messenger/tagservice;1"
|
"@mozilla.org/messenger/tagservice;1"
|
||||||
|
|
||||||
#define NS_MSGTAGSERVICE_CID \
|
#define NS_MSGTAGSERVICE_CID \
|
||||||
{ /* ad04db53-cfcc-47eb-b409-b24b3a0b6130 */ \
|
{ /* b897da55-8256-4cf5-892b-32e77bc7c50b */ \
|
||||||
0xad04db53, 0xcfcc, 0x47eb, \
|
0xb897da55, 0x8256, 0x4cf5, \
|
||||||
{ 0xb4, 0x09, 0xb2, 0x4b, 0x3a, 0x0b, 0x61, 0x30}}
|
{ 0x89, 0x2b, 0x32, 0xe7, 0x7b, 0xc7, 0xc5, 0x0b}}
|
||||||
|
|
||||||
//
|
//
|
||||||
// nsMessengerOSIntegration
|
// nsMessengerOSIntegration
|
||||||
//
|
//
|
||||||
|
|
|
@ -1493,24 +1493,18 @@
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
var children = document.getAnonymousNodes(this);
|
var children = document.getAnonymousNodes(this);
|
||||||
var popupMenu = children[5].firstChild;
|
var popupMenu = children[5].firstChild;
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"].getService(Components.interfaces.nsIMsgTagService);
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
var allTags = tagService.tagEnumerator;
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
var tagNum = 0;
|
for (var i = 0; i < tagArray.length; ++i)
|
||||||
while (allTags.hasMore())
|
|
||||||
{
|
{
|
||||||
var tag = allTags.getNext();
|
var taginfo = tagArray[i];
|
||||||
var key = allKeys.getNext();
|
|
||||||
var newMenuItem = document.createElement('menuitem');
|
var newMenuItem = document.createElement('menuitem');
|
||||||
newMenuItem.setAttribute('label', tag);
|
newMenuItem.setAttribute('label', taginfo.tag);
|
||||||
newMenuItem.setAttribute('value', key);
|
newMenuItem.setAttribute('value', taginfo.key);
|
||||||
popupMenu.appendChild(newMenuItem);
|
popupMenu.appendChild(newMenuItem);
|
||||||
if (tagNum == 0)
|
if (!i)
|
||||||
{
|
|
||||||
children[5].selectedItem = newMenuItem;
|
children[5].selectedItem = newMenuItem;
|
||||||
children[5].value = key;
|
|
||||||
tagNum++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -551,10 +551,10 @@ function ToggleMessageTagKey(index)
|
||||||
var msgHdr = gDBView.hdrForFirstSelectedMessage;
|
var msgHdr = gDBView.hdrForFirstSelectedMessage;
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
while (allKeys.hasMore())
|
for (var i = 0; i < tagArray.length; ++i)
|
||||||
{
|
{
|
||||||
var key = allKeys.getNext();
|
var key = tagArray[i].key;
|
||||||
if (!--index)
|
if (!--index)
|
||||||
{
|
{
|
||||||
// found the key, now toggle its state
|
// found the key, now toggle its state
|
||||||
|
@ -628,7 +628,7 @@ function AddTagCallback(name, color)
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
tagService.addTag(name, color);
|
tagService.addTag(name, color, '');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ToggleMessageTag(tagService.getKeyForTag(name), true);
|
ToggleMessageTag(tagService.getKeyForTag(name), true);
|
||||||
|
@ -657,8 +657,8 @@ function InitMessageTags(menuPopup)
|
||||||
{
|
{
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
.getService(Components.interfaces.nsIMsgTagService);
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allTags = tagService.tagEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagCount = tagArray.length;
|
||||||
|
|
||||||
// remove any existing non-static entries...
|
// remove any existing non-static entries...
|
||||||
var menuseparator = menuPopup.lastChild.previousSibling;
|
var menuseparator = menuPopup.lastChild.previousSibling;
|
||||||
|
@ -666,7 +666,7 @@ function InitMessageTags(menuPopup)
|
||||||
menuPopup.removeChild(menuseparator.previousSibling);
|
menuPopup.removeChild(menuseparator.previousSibling);
|
||||||
|
|
||||||
// hide double menuseparator
|
// hide double menuseparator
|
||||||
menuseparator.previousSibling.hidden = !allTags.hasMore();
|
menuseparator.previousSibling.hidden = !tagCount;
|
||||||
|
|
||||||
// create label and accesskey for the static remove item
|
// create label and accesskey for the static remove item
|
||||||
var tagRemoveLabel = gMessengerBundle.getString("mailnews.tags.remove");
|
var tagRemoveLabel = gMessengerBundle.getString("mailnews.tags.remove");
|
||||||
|
@ -677,17 +677,15 @@ function InitMessageTags(menuPopup)
|
||||||
var curKeys = msgHdr.getStringProperty("keywords");
|
var curKeys = msgHdr.getStringProperty("keywords");
|
||||||
if (msgHdr.label)
|
if (msgHdr.label)
|
||||||
curKeys += " $label" + msgHdr.label;
|
curKeys += " $label" + msgHdr.label;
|
||||||
var index = 0;
|
for (var i = 0; i < tagCount; ++i)
|
||||||
while (allTags.hasMore())
|
|
||||||
{
|
{
|
||||||
var tag = allTags.getNext();
|
var taginfo = tagArray[i];
|
||||||
var key = allKeys.getNext();
|
|
||||||
// TODO we want to either remove or "check" the tags that already exist
|
// TODO we want to either remove or "check" the tags that already exist
|
||||||
var newMenuItem = document.createElement("menuitem");
|
var newMenuItem = document.createElement("menuitem");
|
||||||
SetMessageTagLabel(newMenuItem, ++index, tag);
|
SetMessageTagLabel(newMenuItem, i + 1, taginfo.tag);
|
||||||
newMenuItem.setAttribute("value", key);
|
newMenuItem.setAttribute("value", taginfo.key);
|
||||||
newMenuItem.setAttribute("type", "checkbox");
|
newMenuItem.setAttribute("type", "checkbox");
|
||||||
var removeKey = (" " + curKeys + " ").indexOf(" " + key + " ") > -1;
|
var removeKey = (" " + curKeys + " ").indexOf(" " + taginfo.key + " ") > -1;
|
||||||
newMenuItem.setAttribute('checked', removeKey);
|
newMenuItem.setAttribute('checked', removeKey);
|
||||||
newMenuItem.setAttribute('oncommand', 'ToggleMessageTagMenu(event.target);');
|
newMenuItem.setAttribute('oncommand', 'ToggleMessageTagMenu(event.target);');
|
||||||
menuPopup.insertBefore(newMenuItem, menuseparator);
|
menuPopup.insertBefore(newMenuItem, menuseparator);
|
||||||
|
|
|
@ -401,16 +401,15 @@
|
||||||
<constructor>
|
<constructor>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
var menuPopup = document.getAnonymousNodes(this)[0].menupopup;
|
var menuPopup = document.getAnonymousNodes(this)[0].menupopup;
|
||||||
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"].getService(Components.interfaces.nsIMsgTagService);
|
var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
|
||||||
var allTags = tagService.tagEnumerator;
|
.getService(Components.interfaces.nsIMsgTagService);
|
||||||
var allKeys = tagService.keyEnumerator;
|
var tagArray = tagService.getAllTags({});
|
||||||
while (allTags.hasMore())
|
for (var i = 0; i < tagArray.length; ++i)
|
||||||
{
|
{
|
||||||
var tag = allTags.getNext();
|
var taginfo = tagArray[i];
|
||||||
var key = allKeys.getNext();
|
|
||||||
var newMenuItem = document.createElement('menuitem');
|
var newMenuItem = document.createElement('menuitem');
|
||||||
newMenuItem.setAttribute('label', tag);
|
newMenuItem.setAttribute('label', taginfo.tag);
|
||||||
newMenuItem.setAttribute('value', key);
|
newMenuItem.setAttribute('value', taginfo.key);
|
||||||
menuPopup.appendChild(newMenuItem);
|
menuPopup.appendChild(newMenuItem);
|
||||||
}
|
}
|
||||||
// propagating a pre-existing hack to make the tag get displayed correctly in the menulist
|
// propagating a pre-existing hack to make the tag get displayed correctly in the menulist
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Jan Varga (varga@ku.sk)
|
* Jan Varga (varga@ku.sk)
|
||||||
* Håkan Waara (hwaara@chello.se)
|
* Håkan Waara (hwaara@chello.se)
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -360,23 +360,22 @@ nsresult nsMsgDBView::GetPrefLocalizedString(const char *aPrefName, nsString& aR
|
||||||
|
|
||||||
nsresult nsMsgDBView::AppendKeywordProperties(const char *keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty)
|
nsresult nsMsgDBView::AppendKeywordProperties(const char *keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty)
|
||||||
{
|
{
|
||||||
// get last keyword, get its color, turn that into an atom, and and
|
// get the top most keyword's color and append that as a property.
|
||||||
// append that as a property.
|
|
||||||
nsCStringArray keywordsArray;
|
|
||||||
nsCAutoString color;
|
|
||||||
// skip leading spaces
|
|
||||||
while (*keywords == ' ')
|
|
||||||
keywords++;
|
|
||||||
if (!*keywords)
|
|
||||||
return NS_OK;
|
|
||||||
keywordsArray.ParseString(keywords, " ");
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if (!mTagService)
|
if (!mTagService)
|
||||||
{
|
{
|
||||||
mTagService = do_GetService(NS_MSGTAGSERVICE_CONTRACTID, &rv);
|
mTagService = do_GetService(NS_MSGTAGSERVICE_CONTRACTID, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
rv = mTagService->GetColorForKey(*(keywordsArray[keywordsArray.Count() - 1]), color);
|
|
||||||
|
nsCString topKey;
|
||||||
|
rv = mTagService->GetTopKey(keywords, topKey);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (topKey.IsEmpty())
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsCString color;
|
||||||
|
rv = mTagService->GetColorForKey(topKey, color);
|
||||||
if (NS_SUCCEEDED(rv) && !color.IsEmpty())
|
if (NS_SUCCEEDED(rv) && !color.IsEmpty())
|
||||||
{
|
{
|
||||||
if (addSelectedTextProperty)
|
if (addSelectedTextProperty)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* David Bienvenu <bienvenu@mozilla.org>
|
* David Bienvenu <bienvenu@mozilla.org>
|
||||||
|
* Karsten Düsterloh <mnyromyr@tprac.de>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -38,18 +39,123 @@
|
||||||
|
|
||||||
#include "msgCore.h"
|
#include "msgCore.h"
|
||||||
#include "nsMsgTagService.h"
|
#include "nsMsgTagService.h"
|
||||||
|
#include "nsMsgBaseCID.h"
|
||||||
#include "nsIPrefService.h"
|
#include "nsIPrefService.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsMsgI18N.h"
|
#include "nsMsgI18N.h"
|
||||||
#include "nsIPrefLocalizedString.h"
|
#include "nsIPrefLocalizedString.h"
|
||||||
#include "nsMsgDBView.h" // for labels migration
|
#include "nsMsgDBView.h" // for labels migration
|
||||||
#include "nsStringEnumerator.h"
|
#include "nsQuickSort.h"
|
||||||
|
|
||||||
|
#define STRLEN(s) (sizeof(s) - 1)
|
||||||
|
|
||||||
|
#define TAG_PREF_VERSION "version"
|
||||||
|
#define TAG_PREF_SUFFIX_TAG ".tag"
|
||||||
|
#define TAG_PREF_SUFFIX_COLOR ".color"
|
||||||
|
#define TAG_PREF_SUFFIX_ORDINAL ".ordinal"
|
||||||
|
#define TAG_CMP_LESSER -1
|
||||||
|
#define TAG_CMP_EQUAL 0
|
||||||
|
#define TAG_CMP_GREATER 1
|
||||||
|
|
||||||
|
|
||||||
|
// comparison functions for nsQuickSort
|
||||||
|
PR_STATIC_CALLBACK(int)
|
||||||
|
CompareMsgTagKeys(const void* aTagPref1, const void* aTagPref2, void* aData)
|
||||||
|
{
|
||||||
|
return strcmp(*NS_STATIC_CAST(const char* const*, aTagPref1),
|
||||||
|
*NS_STATIC_CAST(const char* const*, aTagPref2));
|
||||||
|
}
|
||||||
|
|
||||||
|
PR_STATIC_CALLBACK(int)
|
||||||
|
CompareMsgTags(const void* aTagPref1, const void* aTagPref2, void* aData)
|
||||||
|
{
|
||||||
|
// Sort nsMsgTag objects by ascending order, using their ordinal or key.
|
||||||
|
// The "smallest" value will be first in the sorted array,
|
||||||
|
// thus being the most important element.
|
||||||
|
nsMsgTag *element1 = *(nsMsgTag**) aTagPref1;
|
||||||
|
nsMsgTag *element2 = *(nsMsgTag**) aTagPref2;
|
||||||
|
|
||||||
|
// if we have only one element, it wins
|
||||||
|
if (!element1 && !element2)
|
||||||
|
return TAG_CMP_EQUAL;
|
||||||
|
if (!element2)
|
||||||
|
return TAG_CMP_LESSER;
|
||||||
|
if (!element1)
|
||||||
|
return TAG_CMP_GREATER;
|
||||||
|
|
||||||
|
// only use the key if the ordinal is not defined or empty
|
||||||
|
nsCAutoString value1, value2;
|
||||||
|
element1->GetOrdinal(value1);
|
||||||
|
if (value1.IsEmpty())
|
||||||
|
element1->GetKey(value1);
|
||||||
|
element2->GetOrdinal(value2);
|
||||||
|
if (value2.IsEmpty())
|
||||||
|
element2->GetKey(value2);
|
||||||
|
|
||||||
|
return strcmp(value1.get(), value2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// nsMsgTag
|
||||||
|
//
|
||||||
|
NS_IMPL_ISUPPORTS1(nsMsgTag, nsIMsgTag)
|
||||||
|
|
||||||
|
nsMsgTag::nsMsgTag(const nsACString &aKey,
|
||||||
|
const nsAString &aTag,
|
||||||
|
const nsACString &aColor,
|
||||||
|
const nsACString &aOrdinal)
|
||||||
|
: mTag(aTag),
|
||||||
|
mKey(aKey),
|
||||||
|
mColor(aColor),
|
||||||
|
mOrdinal(aOrdinal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsMsgTag::~nsMsgTag()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* readonly attribute ACString key; */
|
||||||
|
NS_IMETHODIMP nsMsgTag::GetKey(nsACString & aKey)
|
||||||
|
{
|
||||||
|
aKey = mKey;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* readonly attribute AString tag; */
|
||||||
|
NS_IMETHODIMP nsMsgTag::GetTag(nsAString & aTag)
|
||||||
|
{
|
||||||
|
aTag = mTag;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* readonly attribute ACString color; */
|
||||||
|
NS_IMETHODIMP nsMsgTag::GetColor(nsACString & aColor)
|
||||||
|
{
|
||||||
|
aColor = mColor;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* readonly attribute ACString ordinal; */
|
||||||
|
NS_IMETHODIMP nsMsgTag::GetOrdinal(nsACString & aOrdinal)
|
||||||
|
{
|
||||||
|
aOrdinal = mOrdinal;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// nsMsgTagService
|
||||||
|
//
|
||||||
NS_IMPL_ISUPPORTS1(nsMsgTagService, nsIMsgTagService)
|
NS_IMPL_ISUPPORTS1(nsMsgTagService, nsIMsgTagService)
|
||||||
|
|
||||||
nsMsgTagService::nsMsgTagService()
|
nsMsgTagService::nsMsgTagService()
|
||||||
{
|
{
|
||||||
m_prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
m_prefBranch = nsnull;
|
||||||
|
nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||||
|
if (prefService)
|
||||||
|
prefService->GetBranch("mailnews.tags.", getter_AddRefs(m_prefBranch));
|
||||||
// need to figure out how to migrate the tags only once.
|
// need to figure out how to migrate the tags only once.
|
||||||
MigrateLabelsToTags();
|
MigrateLabelsToTags();
|
||||||
}
|
}
|
||||||
|
@ -62,18 +168,16 @@ nsMsgTagService::~nsMsgTagService()
|
||||||
/* wstring getTagForKey (in string key); */
|
/* wstring getTagForKey (in string key); */
|
||||||
NS_IMETHODIMP nsMsgTagService::GetTagForKey(const nsACString &key, nsAString &_retval)
|
NS_IMETHODIMP nsMsgTagService::GetTagForKey(const nsACString &key, nsAString &_retval)
|
||||||
{
|
{
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
nsCAutoString prefName(key);
|
||||||
prefName.Append(key);
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_TAG);
|
||||||
prefName.AppendLiteral(".tag");
|
|
||||||
return GetUnicharPref(prefName.get(), _retval);
|
return GetUnicharPref(prefName.get(), _retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void setTagForKey (in string key); */
|
/* void setTagForKey (in string key); */
|
||||||
NS_IMETHODIMP nsMsgTagService::SetTagForKey(const nsACString &key, const nsAString &tag )
|
NS_IMETHODIMP nsMsgTagService::SetTagForKey(const nsACString &key, const nsAString &tag )
|
||||||
{
|
{
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
nsCAutoString prefName(key);
|
||||||
prefName.Append(key);
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_TAG);
|
||||||
prefName.AppendLiteral(".tag");
|
|
||||||
return SetUnicharPref(prefName.get(), tag);
|
return SetUnicharPref(prefName.get(), tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,23 +186,21 @@ NS_IMETHODIMP nsMsgTagService::GetKeyForTag(const nsAString &aTag, nsACString &a
|
||||||
{
|
{
|
||||||
PRUint32 count;
|
PRUint32 count;
|
||||||
char **prefList;
|
char **prefList;
|
||||||
nsresult rv = m_prefBranch->GetChildList("mailnews.tags.", &count, &prefList);
|
nsresult rv = m_prefBranch->GetChildList("", &count, &prefList);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
// traverse the list, and look for a pref with the desired tag value.
|
// traverse the list, and look for a pref with the desired tag value.
|
||||||
for (PRUint32 i = count; i--; )
|
for (PRUint32 i = count; i--;)
|
||||||
{
|
{
|
||||||
// The prefname we passed to GetChildList was of the form
|
// We are returned the tag prefs in the form "<key>.<tag_data_type>", but
|
||||||
// "mailnews.tags." and we are returned the descendants
|
// since we only want the tags, just check that the string ends with "tag".
|
||||||
// in the form of ""mailnews.tags.<key>.tag"
|
nsDependentCString prefName(prefList[i]);
|
||||||
// But we only want the tags, so check that the string
|
if (StringEndsWith(prefName, NS_LITERAL_CSTRING(TAG_PREF_SUFFIX_TAG)))
|
||||||
// ends with tag.
|
|
||||||
if (StringEndsWith(nsDependentCString(prefList[i]), NS_LITERAL_CSTRING(".tag")))
|
|
||||||
{
|
{
|
||||||
nsAutoString curTag;
|
nsAutoString curTag;
|
||||||
GetUnicharPref(prefList[i], curTag);
|
GetUnicharPref(prefList[i], curTag);
|
||||||
if (aTag.Equals(curTag))
|
if (aTag.Equals(curTag))
|
||||||
{
|
{
|
||||||
aKey = Substring(nsDependentCString(prefList[i]), 14, strlen(prefList[i]) - 18);
|
aKey = Substring(prefName, 0, prefName.Length() - STRLEN(TAG_PREF_SUFFIX_TAG));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,22 +209,62 @@ NS_IMETHODIMP nsMsgTagService::GetKeyForTag(const nsAString &aTag, nsACString &a
|
||||||
return aKey.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
|
return aKey.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void addTagForKey (in string key, in wstring tag, in long color); */
|
/* ACString getTopKey (in string keylist); */
|
||||||
NS_IMETHODIMP nsMsgTagService::AddTagForKey(const nsACString &key, const nsAString &tag, const nsACString &color)
|
NS_IMETHODIMP nsMsgTagService::GetTopKey(const char * keyList, nsACString & _retval)
|
||||||
{
|
{
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
_retval = EmptyCString();
|
||||||
prefName.Append(key);
|
// find the most important key
|
||||||
prefName.AppendLiteral(".tag");
|
nsCStringArray keyArray;
|
||||||
SetUnicharPref(prefName.get(), tag);
|
keyArray.ParseString(keyList, " ");
|
||||||
prefName.Replace(prefName.Length() - 3, 3, NS_LITERAL_CSTRING("color"));
|
PRUint32 keyCount = keyArray.Count();
|
||||||
m_prefBranch->SetCharPref(prefName.get(), PromiseFlatCString(color).get());
|
nsCString *topKey = nsnull, *key, topOrdinal, ordinal;
|
||||||
|
for (PRUint32 i = 0; i < keyCount; ++i)
|
||||||
|
{
|
||||||
|
key = keyArray[i];
|
||||||
|
if (key->IsEmpty())
|
||||||
|
continue;
|
||||||
|
// new top key, judged by ordinal order?
|
||||||
|
nsresult rv = GetOrdinalForKey(*key, ordinal);
|
||||||
|
if (NS_FAILED(rv) || ordinal.IsEmpty())
|
||||||
|
ordinal = *key;
|
||||||
|
if ((ordinal < topOrdinal) || topOrdinal.IsEmpty())
|
||||||
|
{
|
||||||
|
topOrdinal = ordinal;
|
||||||
|
topKey = key; // copy actual result key only once - later
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return the most important key - if any
|
||||||
|
if (topKey)
|
||||||
|
_retval = *topKey;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void addTag (in wstring tag, in long color); */
|
/* void addTagForKey (in string key, in wstring tag, in string color, in string ordinal); */
|
||||||
NS_IMETHODIMP nsMsgTagService::AddTag(const nsAString &tag, const nsACString &color)
|
NS_IMETHODIMP nsMsgTagService::AddTagForKey(const nsACString &key,
|
||||||
|
const nsAString &tag,
|
||||||
|
const nsACString &color,
|
||||||
|
const nsACString &ordinal)
|
||||||
|
{
|
||||||
|
nsCAutoString prefName(key);
|
||||||
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_TAG);
|
||||||
|
SetUnicharPref(prefName.get(), tag);
|
||||||
|
prefName.Replace(prefName.Length() - STRLEN(TAG_PREF_SUFFIX_TAG),
|
||||||
|
STRLEN(TAG_PREF_SUFFIX_TAG),
|
||||||
|
NS_LITERAL_CSTRING(TAG_PREF_SUFFIX_COLOR));
|
||||||
|
m_prefBranch->SetCharPref(prefName.get(), PromiseFlatCString(color).get());
|
||||||
|
prefName.Replace(prefName.Length() - STRLEN(TAG_PREF_SUFFIX_COLOR),
|
||||||
|
STRLEN(TAG_PREF_SUFFIX_COLOR),
|
||||||
|
NS_LITERAL_CSTRING(TAG_PREF_SUFFIX_ORDINAL));
|
||||||
|
if (prefName.IsEmpty())
|
||||||
|
return m_prefBranch->ClearUserPref(prefName.get());
|
||||||
|
return m_prefBranch->SetCharPref(prefName.get(), PromiseFlatCString(ordinal).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void addTag (in wstring tag, in long color); */
|
||||||
|
NS_IMETHODIMP nsMsgTagService::AddTag(const nsAString &tag,
|
||||||
|
const nsACString &color,
|
||||||
|
const nsACString &ordinal)
|
||||||
{
|
{
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
|
||||||
// figure out key from tag. Apply transformation stripping out
|
// figure out key from tag. Apply transformation stripping out
|
||||||
// illegal characters like <SP> and then convert to imap mod utf7.
|
// illegal characters like <SP> and then convert to imap mod utf7.
|
||||||
// Then, check if we have a tag with that key yet, and if so,
|
// Then, check if we have a tag with that key yet, and if so,
|
||||||
|
@ -132,13 +274,13 @@ NS_IMETHODIMP nsMsgTagService::AddTag(const nsAString &tag, const nsACString &c
|
||||||
transformedTag.ReplaceChar(" ()/{%*<>\\\"", '_');
|
transformedTag.ReplaceChar(" ()/{%*<>\\\"", '_');
|
||||||
nsCAutoString key;
|
nsCAutoString key;
|
||||||
CopyUTF16toMUTF7(transformedTag, key);
|
CopyUTF16toMUTF7(transformedTag, key);
|
||||||
prefName.Append(key);
|
nsCAutoString prefName(key);
|
||||||
while (PR_TRUE)
|
while (PR_TRUE)
|
||||||
{
|
{
|
||||||
nsAutoString tagValue;
|
nsAutoString tagValue;
|
||||||
GetUnicharPref(prefName.get(), tagValue);
|
GetUnicharPref(prefName.get(), tagValue);
|
||||||
if (tagValue.IsEmpty() || tagValue.Equals(tag))
|
if (tagValue.IsEmpty() || tagValue.Equals(tag))
|
||||||
return AddTagForKey(key, tag, color);
|
return AddTagForKey(key, tag, color, ordinal);
|
||||||
prefName.Append('A');
|
prefName.Append('A');
|
||||||
}
|
}
|
||||||
NS_ASSERTION(PR_FALSE, "can't get here");
|
NS_ASSERTION(PR_FALSE, "can't get here");
|
||||||
|
@ -148,99 +290,128 @@ NS_IMETHODIMP nsMsgTagService::AddTag(const nsAString &tag, const nsACString &c
|
||||||
/* long getColorForKey (in string key); */
|
/* long getColorForKey (in string key); */
|
||||||
NS_IMETHODIMP nsMsgTagService::GetColorForKey(const nsACString &key, nsACString &_retval)
|
NS_IMETHODIMP nsMsgTagService::GetColorForKey(const nsACString &key, nsACString &_retval)
|
||||||
{
|
{
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
nsCAutoString prefName(key);
|
||||||
prefName.Append(key);
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_COLOR);
|
||||||
prefName.AppendLiteral(".color");
|
|
||||||
nsXPIDLCString color;
|
nsXPIDLCString color;
|
||||||
nsresult rv = m_prefBranch->GetCharPref(prefName.get(), getter_Copies(color));
|
nsresult rv = m_prefBranch->GetCharPref(prefName.get(), getter_Copies(color));
|
||||||
_retval = color;
|
_retval = color;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* void setColorForKey (in ACString key, in ACString color); */
|
||||||
|
NS_IMETHODIMP nsMsgTagService::SetColorForKey(const nsACString & key, const nsACString & color)
|
||||||
|
{
|
||||||
|
if (color.IsEmpty())
|
||||||
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
|
nsCAutoString prefName(key);
|
||||||
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_COLOR);
|
||||||
|
return m_prefBranch->SetCharPref(prefName.get(), PromiseFlatCString(color).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACString getOrdinalForKey (in ACString key); */
|
||||||
|
NS_IMETHODIMP nsMsgTagService::GetOrdinalForKey(const nsACString & key, nsACString & _retval)
|
||||||
|
{
|
||||||
|
nsCAutoString prefName(key);
|
||||||
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_ORDINAL);
|
||||||
|
nsXPIDLCString ordinal;
|
||||||
|
nsresult rv = m_prefBranch->GetCharPref(prefName.get(), getter_Copies(ordinal));
|
||||||
|
_retval = ordinal;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void setOrdinalForKey (in ACString key, in ACString ordinal); */
|
||||||
|
NS_IMETHODIMP nsMsgTagService::SetOrdinalForKey(const nsACString & key, const nsACString & ordinal)
|
||||||
|
{
|
||||||
|
nsCAutoString prefName(key);
|
||||||
|
prefName.AppendLiteral(TAG_PREF_SUFFIX_ORDINAL);
|
||||||
|
if (ordinal.IsEmpty())
|
||||||
|
return m_prefBranch->ClearUserPref(prefName.get());
|
||||||
|
return m_prefBranch->SetCharPref(prefName.get(), PromiseFlatCString(ordinal).get());
|
||||||
|
}
|
||||||
|
|
||||||
/* void deleteTag (in wstring tag); */
|
/* void deleteTag (in wstring tag); */
|
||||||
NS_IMETHODIMP nsMsgTagService::DeleteKey(const nsACString &key)
|
NS_IMETHODIMP nsMsgTagService::DeleteKey(const nsACString &key)
|
||||||
{
|
{
|
||||||
// clear the associated prefs
|
// clear the associated prefs
|
||||||
nsCAutoString prefName("mailnews.tags.");
|
return m_prefBranch->DeleteBranch(PromiseFlatCString(key).get());
|
||||||
prefName.Append(key);
|
|
||||||
return m_prefBranch->DeleteBranch(prefName.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* readonly attribute nsIStringEnumerator tagEnumerator; */
|
/* void getAllTags (out unsigned long count, [array, size_is (count), retval] out nsIMsgTag tagArray); */
|
||||||
NS_IMETHODIMP nsMsgTagService::GetTagEnumerator(nsIStringEnumerator * *aTagEnumerator)
|
NS_IMETHODIMP nsMsgTagService::GetAllTags(PRUint32 *aCount, nsIMsgTag ***aTagArray)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
// preset harmless default values
|
||||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
*aCount = 0;
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
*aTagArray = nsnull;
|
||||||
|
|
||||||
PRUint32 count;
|
// get the actual tag definitions
|
||||||
|
nsresult rv;
|
||||||
|
PRUint32 prefCount;
|
||||||
char **prefList;
|
char **prefList;
|
||||||
rv = prefBranch->GetChildList("mailnews.tags.", &count, &prefList);
|
rv = m_prefBranch->GetChildList("", &prefCount, &prefList);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
nsStringArray *stringArray = new nsStringArray(count); // or should it be count / 2?
|
// sort them by key for ease of processing
|
||||||
if (!stringArray)
|
NS_QuickSort(prefList, prefCount, sizeof(char*), CompareMsgTagKeys, nsnull);
|
||||||
|
|
||||||
|
// build an array of nsIMsgTag elements from the orderered list
|
||||||
|
// it's at max the same size as the preflist, but usually only about half
|
||||||
|
*aTagArray = (nsIMsgTag**) NS_Alloc(sizeof(nsIMsgTag*) * prefCount);
|
||||||
|
if (!*aTagArray)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
// traverse the list, and truncate all the descendant strings to just
|
PRUint32 currentTagIndex = 0;
|
||||||
// one branch level below the root branch.
|
nsMsgTag *newMsgTag;
|
||||||
for (PRUint32 i = count; i--; )
|
nsString tag;
|
||||||
|
nsCString lastKey, color, ordinal;
|
||||||
|
for (PRUint32 i = prefCount; i--;)
|
||||||
{
|
{
|
||||||
// The prefname we passed to GetChildList was of the form
|
// extract just the key from <key>.<info=tag|color|ordinal>
|
||||||
// "mailnews.tags." and we are returned the descendants
|
char *info = strrchr(prefList[i], '.');
|
||||||
// in the form of ""mailnews.tags.<key>.tag"
|
if (info)
|
||||||
// But we only want the tags, so check that the string
|
|
||||||
// ends with tag.
|
|
||||||
if (StringEndsWith(nsDependentCString(prefList[i]), NS_LITERAL_CSTRING(".tag")))
|
|
||||||
{
|
{
|
||||||
nsAutoString tag;
|
nsCAutoString key(Substring(prefList[i], info));
|
||||||
GetUnicharPref(prefList[i], tag);
|
if (key != lastKey)
|
||||||
stringArray->AppendString(tag);
|
{
|
||||||
|
if (!key.IsEmpty())
|
||||||
|
{
|
||||||
|
// .tag MUST exist (but may be empty)
|
||||||
|
rv = GetTagForKey(key, tag);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
{
|
||||||
|
// .color MAY exist
|
||||||
|
rv = GetColorForKey(key, color);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
color = EmptyCString();
|
||||||
|
// .ordinal MAY exist
|
||||||
|
rv = GetOrdinalForKey(key, ordinal);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
ordinal = EmptyCString();
|
||||||
|
// store the tag info in our array
|
||||||
|
newMsgTag = new nsMsgTag(key, tag, color, ordinal);
|
||||||
|
if (!newMsgTag)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
(*aTagArray)[currentTagIndex++] = newMsgTag;
|
||||||
|
NS_ADDREF(newMsgTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastKey = key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, prefList);
|
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefList);
|
||||||
return NS_NewAdoptingStringEnumerator(aTagEnumerator, stringArray);;
|
|
||||||
|
// return the number of tags
|
||||||
|
// (the idl's size_is(count) parameter ensures that the array is cut accordingly)
|
||||||
|
*aCount = currentTagIndex;
|
||||||
|
|
||||||
|
// sort the non-null entries by ordinal
|
||||||
|
NS_QuickSort(*aTagArray, *aCount, sizeof(nsMsgTag*), CompareMsgTags, nsnull);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsMsgTagService::GetKeyEnumerator(nsIUTF8StringEnumerator * *aKeyEnumerator)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
PRUint32 count;
|
|
||||||
char **prefList;
|
|
||||||
rv = prefBranch->GetChildList("mailnews.tags.", &count, &prefList);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
nsCStringArray *stringArray = new nsCStringArray; // or should it be count / 2?
|
|
||||||
if (!stringArray)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
// traverse the list, and truncate all the descendant strings to just
|
|
||||||
// one branch level below the root branch.
|
|
||||||
for (PRUint32 i = count; i--; )
|
|
||||||
{
|
|
||||||
// The prefname we passed to GetChildList was of the form
|
|
||||||
// "mailnews.tags." and we are returned the descendants
|
|
||||||
// in the form of ""mailnews.tags.<key>.tag"
|
|
||||||
// But we only want the keys, so check that the string
|
|
||||||
// ends with tag.
|
|
||||||
if (StringEndsWith(nsDependentCString(prefList[i]), NS_LITERAL_CSTRING(".tag")))
|
|
||||||
{
|
|
||||||
nsCAutoString key;
|
|
||||||
nsDependentCString prefStr(prefList[i]);
|
|
||||||
|
|
||||||
prefStr.Mid(key, 14, strlen(prefList[i]) - 18);
|
|
||||||
stringArray->AppendCString(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, prefList);
|
|
||||||
return NS_NewAdoptingUTF8StringEnumerator(aKeyEnumerator, stringArray);;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End of implementation class template. */
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsMsgTagService::getPrefService()
|
nsMsgTagService::getPrefService()
|
||||||
{
|
{
|
||||||
if (m_prefBranch)
|
if (m_prefBranch)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
@ -256,12 +427,12 @@ nsresult nsMsgTagService::SetUnicharPref(const char *prefName,
|
||||||
{
|
{
|
||||||
nsresult rv = getPrefService();
|
nsresult rv = getPrefService();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!val.IsEmpty())
|
if (!val.IsEmpty())
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupportsString> supportsString =
|
nsCOMPtr<nsISupportsString> supportsString =
|
||||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||||
if (supportsString)
|
if (supportsString)
|
||||||
{
|
{
|
||||||
supportsString->SetData(val);
|
supportsString->SetData(val);
|
||||||
rv = m_prefBranch->SetComplexValue(prefName,
|
rv = m_prefBranch->SetComplexValue(prefName,
|
||||||
|
@ -269,7 +440,7 @@ nsresult nsMsgTagService::SetUnicharPref(const char *prefName,
|
||||||
supportsString);
|
supportsString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_prefBranch->ClearUserPref(prefName);
|
m_prefBranch->ClearUserPref(prefName);
|
||||||
}
|
}
|
||||||
|
@ -281,10 +452,10 @@ nsresult nsMsgTagService::GetUnicharPref(const char *prefName,
|
||||||
{
|
{
|
||||||
nsresult rv = getPrefService();
|
nsresult rv = getPrefService();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsISupportsString> supportsString =
|
nsCOMPtr<nsISupportsString> supportsString =
|
||||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||||
if (supportsString)
|
if (supportsString)
|
||||||
{
|
{
|
||||||
rv = m_prefBranch->GetComplexValue(prefName,
|
rv = m_prefBranch->GetComplexValue(prefName,
|
||||||
NS_GET_IID(nsISupportsString),
|
NS_GET_IID(nsISupportsString),
|
||||||
|
@ -303,7 +474,7 @@ nsresult nsMsgTagService::MigrateLabelsToTags()
|
||||||
nsCString prefString;
|
nsCString prefString;
|
||||||
|
|
||||||
PRInt32 prefVersion = 0;
|
PRInt32 prefVersion = 0;
|
||||||
nsresult rv = m_prefBranch->GetIntPref("mailnews.tags.version", &prefVersion);
|
nsresult rv = m_prefBranch->GetIntPref(TAG_PREF_VERSION, &prefVersion);
|
||||||
if (NS_SUCCEEDED(rv) && prefVersion == 1)
|
if (NS_SUCCEEDED(rv) && prefVersion == 1)
|
||||||
return rv;
|
return rv;
|
||||||
nsCOMPtr<nsIPrefLocalizedString> pls;
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
||||||
|
@ -325,10 +496,9 @@ nsresult nsMsgTagService::MigrateLabelsToTags()
|
||||||
|
|
||||||
rv = m_prefBranch->GetCharPref(prefString.get(), getter_Copies(csval));
|
rv = m_prefBranch->GetCharPref(prefString.get(), getter_Copies(csval));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
rv = AddTagForKey(labelKey, ucsval, csval);
|
rv = AddTagForKey(labelKey, ucsval, csval, EmptyCString());
|
||||||
labelKey.SetCharAt(++i + '1', 6);
|
labelKey.SetCharAt(++i + '1', 6);
|
||||||
}
|
}
|
||||||
m_prefBranch->SetIntPref("mailnews.tags.version", 1);
|
m_prefBranch->SetIntPref(TAG_PREF_VERSION, 1);
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* David Bienvenu <bienvenu@mozilla.org>
|
* David Bienvenu <bienvenu@mozilla.org>
|
||||||
|
* Karsten Düsterloh <mnyromyr@tprac.de>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -42,15 +43,25 @@
|
||||||
#include "nsIMsgTagService.h"
|
#include "nsIMsgTagService.h"
|
||||||
#include "nsIPrefBranch.h"
|
#include "nsIPrefBranch.h"
|
||||||
|
|
||||||
class nsMsgTagEntry
|
|
||||||
|
class nsMsgTag : public nsIMsgTag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsMsgTagEntry(const char *key, const PRUnichar *tag, PRUint32 color);
|
NS_DECL_ISUPPORTS
|
||||||
nsString m_tag;
|
NS_DECL_NSIMSGTAG
|
||||||
nsCString m_key;
|
|
||||||
PRUint32 m_color;
|
nsMsgTag(const nsACString &aKey,
|
||||||
|
const nsAString &aTag,
|
||||||
|
const nsACString &aColor,
|
||||||
|
const nsACString &aOrdinal);
|
||||||
|
~nsMsgTag();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsString mTag;
|
||||||
|
nsCString mKey, mColor, mOrdinal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class nsMsgTagService : public nsIMsgTagService
|
class nsMsgTagService : public nsIMsgTagService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -65,9 +76,9 @@ private:
|
||||||
protected:
|
protected:
|
||||||
nsresult getPrefService() ;
|
nsresult getPrefService() ;
|
||||||
nsresult SetUnicharPref(const char *prefName,
|
nsresult SetUnicharPref(const char *prefName,
|
||||||
const nsAString &prefValue);
|
const nsAString &prefValue);
|
||||||
nsresult GetUnicharPref(const char *prefName,
|
nsresult GetUnicharPref(const char *prefName,
|
||||||
nsAString &prefValue);
|
nsAString &prefValue);
|
||||||
nsresult MigrateLabelsToTags();
|
nsresult MigrateLabelsToTags();
|
||||||
|
|
||||||
nsCOMPtr<nsIPrefBranch> m_prefBranch;
|
nsCOMPtr<nsIPrefBranch> m_prefBranch;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче