Bug 1308776 - Add choosing of default addressbook from preferences dialog and a context menu. ui-r=Paenglab, r=mkmelin,jorgk,frgrahl a=jorgk
--HG-- extra : amend_source : 80d5f959ef0a4225025cedeeb4438e4ac8f6e187
This commit is contained in:
Родитель
66aff97b13
Коммит
50102bf1fb
|
@ -45,6 +45,7 @@ var DirPaneController =
|
|||
case "cmd_delete":
|
||||
case "button_delete":
|
||||
case "cmd_properties":
|
||||
case "cmd_abToggleStartupDir":
|
||||
case "cmd_printcard":
|
||||
case "cmd_printcardpreview":
|
||||
case "cmd_newlist":
|
||||
|
@ -136,6 +137,8 @@ var DirPaneController =
|
|||
labelAttr, accKeyAttr);
|
||||
return (selectedDir != null);
|
||||
}
|
||||
case "cmd_abToggleStartupDir":
|
||||
return !!getSelectedDirectoryURI();
|
||||
case "cmd_newlist":
|
||||
case "cmd_newCard":
|
||||
return true;
|
||||
|
@ -160,6 +163,9 @@ var DirPaneController =
|
|||
case "cmd_properties":
|
||||
AbEditSelectedDirectory();
|
||||
break;
|
||||
case "cmd_abToggleStartupDir":
|
||||
abToggleSelectedDirStartup();
|
||||
break;
|
||||
case "cmd_newlist":
|
||||
AbNewList();
|
||||
break;
|
||||
|
@ -218,6 +224,41 @@ function AbEditSelectedDirectory()
|
|||
}
|
||||
}
|
||||
|
||||
function updateDirTreeContext() {
|
||||
let startupItem = document.getElementById("dirTreeContext-startupDir");
|
||||
if (Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault")) {
|
||||
let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
|
||||
let selectedDirURI = getSelectedDirectoryURI();
|
||||
startupItem.setAttribute("checked", (startupURI == selectedDirURI));
|
||||
} else {
|
||||
startupItem.setAttribute("checked", "false");
|
||||
}
|
||||
}
|
||||
|
||||
function abToggleSelectedDirStartup()
|
||||
{
|
||||
let selectedDirURI = getSelectedDirectoryURI();
|
||||
if (!selectedDirURI)
|
||||
return;
|
||||
|
||||
let isDefault = Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault");
|
||||
let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
|
||||
|
||||
if (isDefault && (startupURI == selectedDirURI)) {
|
||||
// The current directory has been the default startup view directory;
|
||||
// toggle that off now. So there's no default startup view directory any more.
|
||||
Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", false);
|
||||
} else {
|
||||
// The current directory will now be the default view
|
||||
// when starting up the main AB window.
|
||||
Services.prefs.setCharPref("mail.addr_book.view.startupURI", selectedDirURI);
|
||||
Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", true);
|
||||
}
|
||||
|
||||
// Update the checkbox in the menuitem.
|
||||
goUpdateCommand("cmd_abToggleStartupDir");
|
||||
}
|
||||
|
||||
function AbDeleteSelectedDirectory()
|
||||
{
|
||||
let selectedDirURI = getSelectedDirectoryURI();
|
||||
|
|
|
@ -292,6 +292,7 @@ function CommandUpdate_AddressBook()
|
|||
goUpdateCommand('cmd_delete');
|
||||
goUpdateCommand('button_delete');
|
||||
goUpdateCommand('cmd_properties');
|
||||
goUpdateCommand("cmd_abToggleStartupDir");
|
||||
goUpdateCommand('cmd_newlist');
|
||||
goUpdateCommand('cmd_newCard');
|
||||
goUpdateCommand('cmd_chatWithCard');
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
|
||||
<keyset id="baseMenuKeyset"/>
|
||||
|
||||
<menupopup id="dirTreeContext">
|
||||
<menupopup id="dirTreeContext" onpopupshowing="updateDirTreeContext();">
|
||||
<menuitem id="dirTreeContext-properties"
|
||||
command="cmd_properties-contextMenu"/>
|
||||
<menuseparator/>
|
||||
|
@ -210,6 +210,12 @@
|
|||
label="&newlistButton.label;"
|
||||
accesskey="&newlistButton.accesskey;"
|
||||
command="cmd_newlist"/>
|
||||
<menuitem id="dirTreeContext-startupDir"
|
||||
label="&showAsDefault.label;"
|
||||
accesskey="&showAsDefault.accesskey;"
|
||||
type="checkbox"
|
||||
checked="false"
|
||||
oncommand="goDoCommand('cmd_abToggleStartupDir');"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="dirTreeContext-delete"
|
||||
label="&deleteButton2.label;"
|
||||
|
|
|
@ -26,6 +26,8 @@ var gComposePane = {
|
|||
|
||||
this.updateEmailCollection();
|
||||
|
||||
this.initAbDefaultStartupDir();
|
||||
|
||||
if (!(("arguments" in window) && window.arguments[1])) {
|
||||
// If no tab was specified, select the last used tab.
|
||||
let preference = document.getElementById("mail.preferences.compose.selectedTabIndex");
|
||||
|
@ -116,6 +118,40 @@ var gComposePane = {
|
|||
}
|
||||
},
|
||||
|
||||
initAbDefaultStartupDir: function() {
|
||||
if (!this.startupDirListener.inited)
|
||||
this.startupDirListener.load();
|
||||
|
||||
let dirList = document.getElementById("defaultStartupDirList");
|
||||
if (Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault")) {
|
||||
// Some directory is the default.
|
||||
let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
|
||||
let dirItem = dirList.menupopup.querySelector('[value="' + startupURI + '"]');
|
||||
// It may happen that the stored URI is not in the list.
|
||||
// In that case select the "none" value and let the AB code clear out
|
||||
// the invalid value, unless the user selects something here.
|
||||
if (dirItem)
|
||||
dirList.selectedItem = dirItem;
|
||||
else
|
||||
dirList.value = "";
|
||||
} else {
|
||||
// Choose item meaning there is no default startup directory any more.
|
||||
dirList.value = "";
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultStartupDir: function(aDirURI) {
|
||||
if (aDirURI) {
|
||||
// Some AB directory was selected. Set prefs to make this directory
|
||||
// the default view when starting up the main AB.
|
||||
Services.prefs.setCharPref("mail.addr_book.view.startupURI", aDirURI);
|
||||
Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", true);
|
||||
} else {
|
||||
// Set pref that there's no default startup view directory any more.
|
||||
Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", false);
|
||||
}
|
||||
},
|
||||
|
||||
initLanguageMenu: function ()
|
||||
{
|
||||
var languageMenuList = document.getElementById("languageMenuList");
|
||||
|
@ -175,7 +211,7 @@ var gComposePane = {
|
|||
// Choose the item after the list is completely generated.
|
||||
var preference = document.getElementById(fontsList.getAttribute("preference"));
|
||||
fontsList.value = preference.value;
|
||||
},
|
||||
},
|
||||
|
||||
restoreHTMLDefaults: function()
|
||||
{
|
||||
|
@ -196,5 +232,30 @@ var gComposePane = {
|
|||
try {
|
||||
document.getElementById('msgcompose.background_color').reset();
|
||||
} catch (ex) {}
|
||||
}
|
||||
},
|
||||
|
||||
startupDirListener: {
|
||||
inited: false,
|
||||
domain: "mail.addr_book.view.startupURI",
|
||||
observe: function(subject, topic, prefName) {
|
||||
if (topic != "nsPref:changed")
|
||||
return;
|
||||
|
||||
// If the default startup directory prefs have changed,
|
||||
// reinitialize the default startup dir picker to show the new value.
|
||||
gComposePane.initAbDefaultStartupDir();
|
||||
},
|
||||
load: function() {
|
||||
// Observe changes of our prefs.
|
||||
Services.prefs.addObserver(this.domain, this, false);
|
||||
// Unload the pref observer when preferences window is closed.
|
||||
window.addEventListener("unload", this.unload, true);
|
||||
this.inited = true;
|
||||
},
|
||||
|
||||
unload: function(event) {
|
||||
Services.prefs.removeObserver(gComposePane.startupDirListener.domain,
|
||||
gComposePane.startupDirListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -219,6 +219,17 @@
|
|||
localonly="true" writable="true"/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center" pack="start">
|
||||
<label value="&showAsDefault.label;" accesskey="&showAsDefault.accesskey;"/>
|
||||
<menulist id="defaultStartupDirList" flex="1"
|
||||
oncommand="gComposePane.setDefaultStartupDir(this.value);">
|
||||
<menupopup class="addrbooksPopup"
|
||||
none="&showAsDefaultLast.label;"
|
||||
alladdressbooks="true"
|
||||
mailinglists="true"/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel orient="vertical">
|
||||
|
|
|
@ -140,6 +140,8 @@ because displayed names don't have the comma in between. -->
|
|||
<!ENTITY newContactButton.accesskey "C">
|
||||
<!ENTITY newlistButton.label "New List">
|
||||
<!ENTITY newlistButton.accesskey "L">
|
||||
<!ENTITY showAsDefault.label "Default startup directory">
|
||||
<!ENTITY showAsDefault.accesskey "S">
|
||||
<!ENTITY editPropertiesButton.label "Edit">
|
||||
<!ENTITY propertiesContext.label "Properties">
|
||||
<!ENTITY propertiesContext.accesskey "i">
|
||||
|
|
|
@ -54,6 +54,9 @@
|
|||
<!ENTITY directoriesNone.label "None">
|
||||
<!ENTITY editDirectories.label "Edit Directories…">
|
||||
<!ENTITY editDirectories.accesskey "E">
|
||||
<!ENTITY showAsDefault.label "Default startup directory in the address book window:">
|
||||
<!ENTITY showAsDefault.accesskey "S">
|
||||
<!ENTITY showAsDefaultLast.label "Last used directory">
|
||||
|
||||
<!ENTITY sendOptionsDescription.label "Configure text format behavior">
|
||||
<!ENTITY sendOptions.label "Send Options…">
|
||||
|
|
|
@ -82,3 +82,21 @@ notification[value="addon-install-failed"] {
|
|||
#findbar-beforeReplaceSeparator {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* ::::: Address Book menuitem icons ::::: */
|
||||
|
||||
.abMenuItem[AddrBook="true"] {
|
||||
list-style-image: url("chrome://messenger/skin/addressbook/icons/addrbook.png");
|
||||
}
|
||||
|
||||
.abMenuItem[MailList="true"] {
|
||||
list-style-image: url("chrome://messenger/skin/addressbook/icons/ablist.png");
|
||||
}
|
||||
|
||||
.abMenuItem[AddrBook="true"][IsRemote="true"] {
|
||||
list-style-image: url("chrome://messenger/skin/addressbook/icons/remote-addrbook.png");
|
||||
}
|
||||
|
||||
.abMenuItem[AddrBook="true"][IsRemote="true"][IsSecure="true"] {
|
||||
list-style-image: url("chrome://messenger/skin/addressbook/icons/secure-remote-addrbook.png");
|
||||
}
|
||||
|
|
|
@ -18,57 +18,118 @@
|
|||
parent menulist. Defaults to URI but can be e.g. dirPrefId -->
|
||||
<field name="_value">this.getAttribute("value") || "URI"</field>
|
||||
|
||||
<field name="_stringBundle">null</field>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
// Init the address book cache.
|
||||
const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
|
||||
let directories = MailServices.ab.directories;
|
||||
while (directories && directories.hasMoreElements()) {
|
||||
var ab = directories.getNext();
|
||||
if (ab instanceof nsIAbDirectory && this._matches(ab))
|
||||
this._directories.push(ab);
|
||||
}
|
||||
|
||||
this._directories.sort(this._compare);
|
||||
|
||||
// Now create menuitems for all displayed directories.
|
||||
var menulist = this.parentNode;
|
||||
var value = this._value;
|
||||
this._directories.forEach(function (ab) {
|
||||
menulist.appendItem(ab.dirName, ab[value]);
|
||||
});
|
||||
if (this.hasAttribute("none")) {
|
||||
// Create a dummy menuitem representing no selection.
|
||||
this._directories.unshift(null);
|
||||
menulist.insertItemAt(0, this.getAttribute("none"), "");
|
||||
}
|
||||
|
||||
// Attempt to select the persisted or otherwise first directory.
|
||||
menulist.value = menulist.value;
|
||||
if (!menulist.selectedItem && this.hasChildNodes())
|
||||
menulist.selectedIndex = 0;
|
||||
Components.utils.import("resource:///modules/mailServices.js", this);
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm", this);
|
||||
Components.utils.import("resource:///modules/StringBundle.js", this);
|
||||
this._stringBundle = new this
|
||||
.StringBundle("chrome://messenger/locale/addressbook/addressBook.properties");
|
||||
|
||||
this._rebuild();
|
||||
const nsIAbListener = Components.interfaces.nsIAbListener;
|
||||
// Add a listener so we can update correctly if the list should change
|
||||
MailServices.ab.addAddressBookListener(this,
|
||||
nsIAbListener.itemAdded |
|
||||
nsIAbListener.directoryRemoved |
|
||||
nsIAbListener.itemChanged);
|
||||
this.MailServices.ab
|
||||
.addAddressBookListener(this,
|
||||
nsIAbListener.itemAdded |
|
||||
nsIAbListener.directoryItemRemoved |
|
||||
nsIAbListener.directoryRemoved |
|
||||
nsIAbListener.itemChanged);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
MailServices.ab.removeAddressBookListener(this);
|
||||
this.MailServices.ab.removeAddressBookListener(this);
|
||||
|
||||
// Empty out anything in the list.
|
||||
while (this.hasChildNodes())
|
||||
this.lastChild.remove();
|
||||
this._teardown();
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<method name="_rebuild">
|
||||
<parameter name="aSelectValue"/>
|
||||
<body><![CDATA[
|
||||
// Init the address book cache.
|
||||
this._directories.length = 0;
|
||||
const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
|
||||
let directories = this.MailServices.ab.directories;
|
||||
while (directories && directories.hasMoreElements()) {
|
||||
let ab = directories.getNext();
|
||||
if ((ab instanceof nsIAbDirectory) && this._matches(ab)) {
|
||||
this._directories.push(ab);
|
||||
if (this.getAttribute("mailinglists") == "true") {
|
||||
// Also append contained mailinglists.
|
||||
for (let list of this.fixIterator(ab.childNodes, Components.interfaces.nsIAbDirectory)) {
|
||||
if (this._matches(list))
|
||||
this._directories.push(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._sort();
|
||||
|
||||
this._teardown();
|
||||
|
||||
// Now create menuitems for all displayed directories.
|
||||
let menulist = this.parentNode;
|
||||
let value = this._value;
|
||||
for (let ab of this._directories) {
|
||||
let listItem = menulist.appendItem(ab.dirName, ab[value]);
|
||||
listItem.setAttribute("class", "menuitem-iconic abMenuItem");
|
||||
|
||||
// Style the items by type.
|
||||
if (ab.isMailList)
|
||||
listItem.setAttribute("MailList", "true");
|
||||
else
|
||||
listItem.setAttribute("AddrBook", "true");
|
||||
|
||||
if (ab.isRemote)
|
||||
listItem.setAttribute("IsRemote", "true");
|
||||
if (ab.isSecure)
|
||||
listItem.setAttribute("IsSecure", "true");
|
||||
}
|
||||
|
||||
if (this.hasAttribute("alladdressbooks")) {
|
||||
// Insert a menuitem representing All addressbooks.
|
||||
let allABLabel = this.getAttribute("alladdressbooks");
|
||||
if (allABLabel == "true")
|
||||
allABLabel = this._stringBundle.getString("allAddressBooks");
|
||||
const allABURI = "moz-abdirectory://?";
|
||||
this._directories.unshift(null);
|
||||
let listItem = menulist.insertItemAt(0, allABLabel, allABURI);
|
||||
listItem.setAttribute("class", "menuitem-iconic abMenuItem");
|
||||
listItem.setAttribute("AddrBook", "true");
|
||||
listItem.setAttribute("IsAllAB", "true");
|
||||
}
|
||||
|
||||
if (this.hasAttribute("none")) {
|
||||
// Create a dummy menuitem representing no selection.
|
||||
this._directories.unshift(null);
|
||||
let listItem = menulist.insertItemAt(0, this.getAttribute("none"), "");
|
||||
listItem.setAttribute("class", "menuitem-iconic abMenuItem");
|
||||
listItem.setAttribute("IsNone", "true");
|
||||
}
|
||||
|
||||
// Attempt to select the persisted or otherwise first directory.
|
||||
menulist.value = aSelectValue || this.parentNode.value;
|
||||
if (!menulist.selectedItem && this.hasChildNodes())
|
||||
menulist.selectedIndex = 0;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_teardown">
|
||||
<body><![CDATA[
|
||||
// Empty out anything in the list.
|
||||
// (Don't use menulist.removeAllItems() as it would remove
|
||||
// the menupopup with our special attributes too.)
|
||||
while (this.hasChildNodes())
|
||||
this.lastChild.remove();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- nsIAbListener methods -->
|
||||
<method name="onItemAdded">
|
||||
<parameter name="aParentDir"/>
|
||||
|
@ -76,12 +137,8 @@
|
|||
<body><![CDATA[
|
||||
// Are we interested in this new directory?
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList && this._matches(aItem)) {
|
||||
this._directories.push(aItem);
|
||||
this._directories.sort(this._compare);
|
||||
// Insert the new menuitem at the position to which it was sorted.
|
||||
this.parentNode.insertItemAt(this._directories.indexOf(aItem),
|
||||
aItem.dirName, aItem[this._value]);
|
||||
this._matches(aItem)) {
|
||||
this._rebuild();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -90,22 +147,24 @@
|
|||
<parameter name="aParentDir"/>
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList) {
|
||||
// Find the item in the list to remove
|
||||
// We can't use indexOf here because we need loose equality
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory) {
|
||||
// Find the item in the list to remove.
|
||||
// We can't use indexOf here because we need loose equality.
|
||||
for (var index = this._directories.length; --index >= 0; )
|
||||
if (this._directories[index] == aItem)
|
||||
break;
|
||||
if (index != -1)
|
||||
if (index != -1) {
|
||||
this._directories.splice(index, 1);
|
||||
// Are we removing the selected directory?
|
||||
if (this.parentNode.selectedItem ==
|
||||
this.removeChild(this.childNodes[index]))
|
||||
this.removeChild(this.childNodes[index])) {
|
||||
// If so, try to select the first directory, if available.
|
||||
if (this.hasChildNodes())
|
||||
this.firstChild.doCommand();
|
||||
else
|
||||
this.parentNode.selectedItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -116,26 +175,14 @@
|
|||
<parameter name="aOldValue"/>
|
||||
<parameter name="aNewValue"/>
|
||||
<body><![CDATA[
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList) {
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory) {
|
||||
// Find the item in the list to rename.
|
||||
// We can't use indexOf here because we need loose equality
|
||||
// We can't use indexOf here because we need loose equality.
|
||||
for (var oldIndex = this._directories.length; --oldIndex >= 0; )
|
||||
if (this._directories[oldIndex] == aItem)
|
||||
break;
|
||||
if (oldIndex != -1) {
|
||||
// Cache the matching item so that we can use indexOf next time.
|
||||
aItem = this._directories[oldIndex];
|
||||
var child = this.childNodes[oldIndex];
|
||||
child.label = aItem.dirName;
|
||||
this._directories.sort(this._compare);
|
||||
// Reorder the menuitems if renaming changed the directory index.
|
||||
var newIndex = this._directories.indexOf(aItem);
|
||||
if (newIndex < oldIndex)
|
||||
this.insertBefore(child, this.childNodes[newIndex]);
|
||||
else if (newIndex > oldIndex)
|
||||
this.insertBefore(child, this.childNodes[newIndex].nextSibling);
|
||||
}
|
||||
if (oldIndex != -1)
|
||||
this._rebuild();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -158,6 +205,43 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Sort all our directories. -->
|
||||
<method name="_sort">
|
||||
<body><![CDATA[
|
||||
let lists = {};
|
||||
let lastAB;
|
||||
// If there are any mailing lists, pull them out of the array temporarily.
|
||||
for (let d = 0; d < this._directories.length; d++) {
|
||||
if (this._directories[d].isMailList) {
|
||||
let [list] = this._directories.splice(d, 1);
|
||||
if (!(lastAB in lists))
|
||||
lists[lastAB] = [];
|
||||
lists[lastAB].push(list);
|
||||
d--;
|
||||
} else {
|
||||
lastAB = this._directories[d].URI;
|
||||
}
|
||||
}
|
||||
|
||||
this._directories.sort(this._compare);
|
||||
|
||||
// Push mailing lists back appending them after their respective
|
||||
// containing addressbook.
|
||||
for (let d = this._directories.length - 1; d >= 0; d--) {
|
||||
let abURI = this._directories[d].URI;
|
||||
if (abURI in lists) {
|
||||
lists[abURI].sort(function(a,b) { return a.dirName.localeCompare(b.dirName); });
|
||||
let listIndex = d;
|
||||
for (let list of lists[abURI]) {
|
||||
listIndex++;
|
||||
this._directories.splice(listIndex, 0, list);
|
||||
}
|
||||
delete lists[abURI];
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Used to sort directories in order -->
|
||||
<method name="_compare">
|
||||
<parameter name="a"/>
|
||||
|
|
Загрузка…
Ссылка в новой задаче