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:
aceman 2016-11-23 22:30:39 +02:00
Родитель 66aff97b13
Коммит 50102bf1fb
9 изменённых файлов: 295 добавлений и 68 удалений

Просмотреть файл

@ -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"/>