Closed Bug 73868 Opened 24 years ago Closed 23 years ago

addressbook results pane, select address dialog results pane, ab sidebar should use outliner

Categories

(SeaMonkey :: MailNews: Address Book & Contacts, defect)

defect
Not set
normal

Tracking

(Not tracked)

VERIFIED FIXED
mozilla0.9.8

People

(Reporter: cathleennscp, Assigned: sspitzer)

References

()

Details

(Keywords: perf)

Attachments

(4 files, 44 obsolete files)

63.80 KB, image/jpeg
Details
51.69 KB, image/jpeg
Details
81.54 KB, text/plain
Details
604.28 KB, patch
dmosedale
: review+
Details | Diff | Splinter Review
need to convert addressbook to use new RDF outliner
QA Contact: esther → fenella
Blocks: 73948
--> me
Assignee: chuang → blake
QA Contact: fenella → nbaca
hey blake (and others), if possible, please hold off on this until I land #83023
Blocks: 25554
Target Milestone: --- → mozilla0.9.7
stephend, when you post your address book perf numbers on mozilla.org, can you add a link here? thinking ahead about this bug, for the addressbook "elements" pane, I want to create an addressbook view (implementing an nsIOutlinerView), instead of using the rdfliner. The performance improvements would be close to what we got when we converted the mailnews thread pane. switching from XUL templates | RDF datasource | addressbook db (mork) to outliner | addressbook view | addressbook db (mork) is quite a bit of work, but worth it. before starting on that work, I need to investigate what code uses the datasource that I'd be removing. I wouldn't be getting rid of the datasource behind the addressbook "addressbook / mailing list" pane. Like the folder pane, we'd switch over to use the rdfliner. blake, feel free to give this back to me.
taking from blake. I'm going to be working on ab perf.
Assignee: blakeross → sspitzer
No longer blocks: 107151
ok got the basics going. see the screen shot. I'll attach my initial patch, it's still a work in progress.
Status: NEW → ASSIGNED
No longer depends on: 83023
here's how the results pane currently works: rdf / xul tree templates (on top of) directory datasource (on top of) nsIAbDirectory (mork, ldap, outlook, etc). we learned from the thread pane that the way to make it fast and use less memory is to use outliner (which means now that we only have the content node for the outliner body, instead of content for every tree cell, tree row, etc for every entry in the addressbook), and to remove the datasource. what I've got so far is: outliner nsAbView (implements nsIAbView) nsIAbDirectory (mork, ldap, outlook, etc) showing data isn't hard (that part is working). the harder part is fixing all the other code in the fe that used to use the tree, and now has to use the outliner, including drag & drop, commands, etc.
Blocks: 83023
Summary: addressbook to use new outliner → addressbook results pane to use new outliner
Attachment #56207 - Attachment is obsolete: true
Just curious: did you try using the rdfliner for this? Did it not provide a big win? (Were you going to get rid of the AB datasource anyway?)
Attachment #56274 - Attachment is obsolete: true
> Just curious: did you try using the rdfliner for this? no, but I plan to for the "addressbook" pane, like we did for the folder pane. > Did it not provide a big win? yes, a big win. I haven't measured officially, but I see the difference between an opt build with the old way and a debug build with the new way in scrolling, ab loading, and startup (which loads the first ab). the bigger the AB, the bigger the win. it also allows to hide columns, and if we want, to add more columns easily. > (Were you going to get rid of the AB datasource > anyway?) there's no need to go throug the AB datasource for the results pane, as it just fwds on to nsIAbDirectory.
Attachment #56275 - Attachment is obsolete: true
Attachment #56279 - Attachment is obsolete: true
Attachment #56653 - Attachment is obsolete: true
loading a large ab is still slow, but I've found out why. *every* card is a listener on the addressbook. zoinks! removing that will make ab loading much, much faster. nsAddrDatabase::AddListener(nsAddrDatabase * const 0x05ce4830, nsIAddrDBListener * 0x086370f4) line 267 + 16 bytes nsAddrDatabase::CreateCard(nsIMdbRow * 0x05305068, unsigned int 0x00000000, nsIAbCard * * 0x08e37084) line 3757 nsAddrDatabase::CreateABCard(nsIMdbRow * 0x05305068, nsIAbCard * * 0x08e37084) line 3775 nsAddrDBEnumerator::CurrentItem(nsAddrDBEnumerator * const 0x08e37070, nsISupports * * 0x0012a73c) line 3522 + 52 bytes nsAbView::EnumerateCards(nsIAbDirectory * 0x05ce8a30) line 100 + 47 bytes nsAbView::Init(nsAbView * const 0x08e283a0, const char * 0x08e33040) line 81 + 17 bytes
finding more badness, but should be easy to fix. I've added all the column the spec requires, and I'm using the same column token in the xul as we do in the mork ab, so that in theory, we should be able to pass it back from GetCellText() without having to do string compares before we get to mork. unfortunately, the addressbook is horked on crack. so even if we call getCardValue("DisplayName"), we *still* do extra work. I'll make sure to get to that cleanup. now the available columns include: "Name", "Email", "Presence", "Screen Name", "Work Phone", "Organization", "Nick Name", "Home Phone", "Fax", "Pager", "Cellular", "Additional Email", "Title" and "Department". I'll attach a screen shot, and update the patch.
here's one really bad thing that the ab does: when loading a directory, we bloat (into memory) a nsIAbCard for each card in the database. that would be ok, if we only built it up with the card properties that we cared about, and if we did it lazily. but we don't instead, we copy all the properties (whether we ever need them or not). this is sucks ass with autocomplete, as we'll try to get all the attributes for each card, and not just the attributes we need for autocomplete.
my todo list for the next few days: 1) sorting 2) fix bloat, be lazy with nsIAbCard (help with autocomplete perf, footprint) 3) no strcmp, map right to mork. 4) get add / delete working (view will have to listen on db) 5) edit changes to work 6) double click to edit mailing list 7) get "Properties" button to work again 8) make sure ab sidebar works 9) remove the unnecessary datasource 10) sort indicators 11) menu items for sort 12) menu items for show / hide columns 13) start up, select first card. what works now: 1) use outliner 2) selection in outliner load card pane 3) add all columns per the spec, column picker, column reordering, persistence 4) improve ab load, every card is a no longer a listener on the db 5) double click to edit card 6) icons in result pane (card and mailing list)
Attached patch updated patch, add sorting (obsolete) — Splinter Review
Attachment #56781 - Attachment is obsolete: true
Attachment #56801 - Attachment is obsolete: true
Attachment #56809 - Attachment is obsolete: true
Attachment #56811 - Attachment is obsolete: true
Attachment #56846 - Attachment is obsolete: true
Attachment #56951 - Attachment is obsolete: true
this affects perf substantially, marking as a keyword
Keywords: perf
Attached patch updated patch (obsolete) — Splinter Review
Attachment #57468 - Attachment is obsolete: true
Attached patch updated patch, edit card working (obsolete) — Splinter Review
Attachment #57470 - Attachment is obsolete: true
here's what's left before I can land: 0) double clicking on list in folder pane to edit 1) sort indicators 2) make sure ab sidebar works 3) restore sort selection 4) drag n drop 5) make sure db or mailing list works 6) cmd updating (delete, properties, etc) 7) changing mailing list name doesn't always update folderpane 8) get "cards in ab" status text working again 9) test ab sync 10) double check for leaks 11) makefile / .mcp changes for mac and linux 12) test ab import 13) test ldap / outlook here's what needs to be done, after the landing: 1) fix bloat, be lazy with nsIAbCard (work on autocomplete perf, CAB perf) 2) no strcmp, map right to mork. 3) rename collecter -> collector 4) improve listener foo (too much going on) 5) default height for splitter (to save a paint) 6) more perf work, footprint work on ab.
updated todo list: here's what's left before I can land: a) fix select address dialog b) fix ab sidebar c) sending assertions (in addressbook) d) updates to mailing list not reflecting in card pane until repaint 1) double clicking in folder pane to edit mailing list 2) sort indicators 3) restore sort selection 4) drag n drop 5) make sure db or mailing list works 6) cmd updating (delete, properties, etc) 7) changing mailing list name doesn't always update folderpane 8) get "cards in ab" status text working again 9) test ab sync 10) double check for leaks 11) fix duplicate access keys 12) makefile / .mcp changes for mac and linux 13) test ab import 14) test ldap / outlook 15) test how it works with no AB. 16) show name as needs work 17) look for any XXXX / dump / printf 18) remove old results tree xul here's what needs to be done, after the landing: 1) fix bloat, be lazy with nsIAbCard (work on autocomplete perf, CAB perf) 2) no strcmp, map right to mork. 3) rename collecter -> collector 4) improve listener foo (too much going on) 5) default height for splitter (to save a paint) 6) more perf work, footprint work on ab.
Summary: addressbook results pane to use new outliner → addressbook results pane, select address dialog results pane, ab sidebar should use outliner
Attachment #57747 - Attachment is obsolete: true
Attachment #57946 - Attachment is obsolete: true
there's now a branch. win32: cvs co -r AB_OUTLINER_BRANCH mozilla/client.mak cd mozilla nmake -f client.mak linux: cvs co -r AB_OUTLINER_BRANCH mozilla/client.mk cd mozilla gmake -f client.mk mac: not yet see http://www.sspitzer.org/ab.html for the todo list, and the items completed.
I noticed the ETA on your AB page... There are going to be test builds before you land this (and turn it on) on the trunk, right?
there's are branch bits. see ftp://ftp.mozilla.org/pub/mozilla/nightly/latest-AB_OUTLINER/ there's a bunch of known issues that I'm working on. (see http://www.sspitzer.org/ab.html)
Seth, curious if you are doing ok with all the stuff you have on the list.. are you in need of assistance getting this one out of the way?
also some commercial bits on sweetlou for example, ftp://sweetlou/products/client/seamonkey/windows/32bit/x86/2001-12-05-18- AB_OUTLINER/
these are the changes for the branch, I still need to re-review all the changes, clean it up, apply to the trunk, and get a trunk based diff, for review.
Attachment #59197 - Attachment is obsolete: true
here's a patch for the trunk. I'm testing / self-reviewing it now.
Attachment #60960 - Attachment is obsolete: true
Attached patch patch for review. (obsolete) — Splinter Review
files removed: mailnews/addrbook/resources/content/abResultsTreeOverlay.xul mailnews/addrbook/resources/locale/en-US/abResultsTreeOverlay.dtd mailnews/addrbook/src/nsAbMDBRDFResource.h mailnews/addrbook/src/nsCardDataSource.h mailnews/addrbook/src/nsAbMDBRDFResource.cpp mailnews/addrbook/src/nsCardDataSource.cpp files added: (the trunk version of them are cat'd to the end of the patch, so you can review them) mailnews/addrbook/resources/content/abResultsPaneOverlay.xul mailnews/addrbook/resources/content/abResultsPane.js mailnews/addrbook/resources/content/addressbook-panel.js mailnews/addrbook/resources/locale/en-US/abResultsPaneOverlay.dtd mailnews/addrbook/public/nsIAbView.idl mailnews/addrbook/src/nsAbView.h mailnews/addrbook/src/nsAbView.cpp themes/classic/messenger/addressbook/mac/abResultsPane.css themes/classic/messenger/addressbook/win/abResultsPane.css themes/modern/messenger/addressbook/abResultsPane.css
Attachment #61163 - Attachment is obsolete: true
Here are some nits with the patch: + * Edits an existing mail in the directory + * defined by the uri, or pass in the card for the list in this function: +function goToggleSplitter( id, elementID ) you have some logic that relies on the element's |checked| property's value. You should check that it works, if you are messing with checkboxes, due to blake's recent landing to make .getAttribute("checked","false") not work (and replace it with .hasAttribute("checked")). I don't know if that affects you, just a heads-up for the record. + catch (ex) { + return 0; } What's the point of this? That function will terminate one line thereafter anyway... + var treechildren; + for (var i=0;i<children.length; i++) { + if (children[i].localName == "treechildren") { + treechildren = children[i]; + break; + } + } Did you mean to fetch all the nodes with localName "treechildren" into treechildren? Maybe this should be |treechildren += children[i]| then? (Otherwise treechildren will always be the last "treechildren" node...afaics) in this file: Index: mailnews/addrbook/resources/content/addressbook.js You are adding an old-style NPL-license. It should be a tri-license... in these files: Index: mailnews/addrbook/src/nsAbDirProperty.cpp Index: mailnews/addrbook/src/nsAbMDBDirProperty.cpp There's no newline at end of the file. This will hork some ports, IIRC. In these two cases: + if (lastName.Length()) + else if (firstName.Length()) you should probably check for !firstName.IsEmpty(), which I think is (will be?) cheaper to do. Suddenly, at a certain point in this patch, it became normal |cvs diff| output (as opposed to |cvs diff -u|)... This is very nice cleanup, it's gonna rock to be able to use a fast addressbook! r=hwaara
BTW, disregard the treechildren comment, I didn't notice the break in that loop.
hwaara, missed the |break;| semantics [short explanation for posterity] javascript:for(a=0;a<6;++a)break;document.write(a) outputs 0, not 6. @@ -137,9 +142,13 @@ // defined by the uri void addMailListToDatabase(in string uri); - // Edits an existing mail in the directory - // defined by the uri - void editMailListToDatabase(in string uri); + /** + * Edits an existing mail in the directory + * defined by the uri, or pass in the card for the list whitespace ^ RCS file: /cvsroot/mozilla/mailnews/addrbook/resources/content/abCardViewOverlay.js,v @@ -94,6 +94,14 @@ odd alignment, i'm assuming you should be indenting to match... +function GetAddressesFromURI(uri) +{ + var addresses = ""; + + var editList = GetDirectoryFromURI(uri); + var addressList = editList.addressLists; + if (addressList) { + var total = addressList.Count(); + if (total) { + for ( var i = 0; i < total; i++ ) { + var current = addressList.GetElementAt(i).QueryInterface(Components.interfaces.nsIAbCard); + + if (i == 0) + addresses = current.primaryEmail; + else + addresses += "," + current.primaryEmail; } - // for seperator all other display formats - else { - separator = cvPrefs.lastFirstSeparator; } } i think you should drop the if (total) js> function a(){try { for (;c<d;)throw "aa";} catch (e){return 1;}return 2;} js> function b(){try { for (;c<d+1;)throw "aa";} catch (e){return 1;}return 2;} js> var c=d=0;print (a()+" "+b()) 2 1 @@ -178,10 +200,27 @@ whitespace in +'d lines. + cvSetVisible(data.cvhDescription, false); + cvSetVisible(data.cvbDescription, false); you're doing a lot of paired hiding, wouldn't it make more sense to use some sort of grouping mechanism so you only hide one thing? + <description class="CardViewLink" hide="true" id="cvListNameBox"> + <html:p><html:a href="" id="cvListName"/></html:p></description> could you move </description> to line up w/ <description...> (either vertically or horizontally, i'm not picky. + if (gAbView) + return gAbView; + else + return null; brendan would say else after return: bad. i'll instead ask why not just return gAbView (showing my complete ignorance of the code). +function ChangeDirectoryByDOMNode(dirNode) ... +return; +} there's no need for this return. +function InvalidateResultsPane() +{ + var outliner = GetAbResultsOutliner(); + outliner.boxObject.invalidate(); } why not just GetAbResultsOutliner().boxObject.invalidate(); ? [note, rginda says my suggestion is ugly, so this suggestion like all others is discardable] +function GenerateAddressFromCard(card) +{ + var address = ""; + var name = card.displayName + if (name.length) { + address += "\"" + name + "\" "; + } + + if (card.isMailList) { + if (name.length) { + address += "<" + name + ">"; + } + } + else { + var email = card.primaryEmail; + if (email.length) { + address += "<" + email + ">"; + } + } + return address; +} would if (foo) work as well as if (foo.length)? <<<<<< +function GetParentDirectoryForMailingList(abURI) +{ + var parentURI = null; + + var abURIArr = abURI.split("/"); + /* + turn turn "moz-abmdbdirectory://abook.mab/MailList6" + into ["moz-abmdbdirectory:","","abook.mab","MailList6"] + then, turn ["moz-abmdbdirectory:","","abook.mab","MailList6"] + into "moz-abmdbdirectory://abook.mab" + */ + if (abURIArr.length == 4 && abURIArr[0] == "moz-abmdbdirectory:") { + parentURI = abURIArr[0] + "/" + abURIArr[1] + "/" + abURIArr[2]; + } + return parentURI; } ====== +function GetParentDirectoryForMailingList(abURI) +{ + /* + in "moz-abmdbdirectory://abook.mab/MailList6" + out "moz-abmdbdirectory://abook.mab" + */ + return abURI.match(RegExp("^moz-abmdbdirectory\://[^/]*/")); } >>>>>> +var abDirTreeObserver = { + onDragStart: function (aEvent, aXferData, aDragAction) this function appears to want to be a consumer of GetParentDirectoryForMailingList but is not <<<<<< + var targetArr = targetURI.split("/"); + var srcArr = srcURI.split("/"); + if (srcArr.length == targetArr.length && srcArr.length == 4) { + if (srcArr[0] == "moz-abmdbdirectory:" && + srcArr[0] == targetArr[0] && + srcArr[1] == targetArr[1] && + srcArr[2] == targetArr[2]) { + needToCopyCard = false; + } + } ====== if (GetParentDirectoryForMailingList(targetURI)==GetParentDirectoryForMailingList (srcURI)) needToCopyCard = false; >>>>>> [feel free to assign the ruturns of that function to local variables for readability] @@ -589,22 +619,19 @@ can you change from return(false); to return false; to match what i think is the predominant style? the tail of function UpdateCardView() is the same as the function OnClickedCard(card) RCS file: /cvsroot/mozilla/mailnews/addrbook/src/nsAbDirProperty.cpp,v \ No newline at end of file RCS file: /cvsroot/mozilla/mailnews/addrbook/src/nsAbMDBDirectory.cpp,v reeks of tabs (they appear to be in your + lines) + else { + if (lastName.Length()) + *aName = nsCRT::strdup(lastName.get()); + else if (firstName.Length()) + *aName = nsCRT::strdup(firstName.get()); + else + *aName = nsCRT::strdup(NS_LITERAL_STRING("").get()); + *aName = nsnull; + } [timeless] jag should i use: nsCRT::strdup(NS_LITERAL_STRING("").get()); <bz> timeless: why would use strdup there?? <jag> timeless: no <bz> timeless: that seems very wrong.... (embedded nulls and the like) <jag> timeless: ToNewUnicode(NS_LITERAL_STRING("")) if you really must <bz> timeless: that looks incredibly broken if (!lastName.IsEmpty()) *aName = ToNewUnicode(lastName); else if (!firstName.IsEmpty()) *aName = ToNewUnicode(firstName); else *aName = nsnull; a caller is doing: + if (NS_SUCCEEDED(abSession->GenerateNameFromCard(workCard, format, &aName)) && (aName)) the other caller does .get() so i think we have a problem + rv = abSession->GenerateNameFromCard(this, format, getter_Copies(properties [index_DisplayName])); + NS_ENSURE_SUCCESS(rv,rv); + if (*properties [index_DisplayName].get() == 0) { so i think this should be changed to: if (properties [index_DisplayName]) { sorry for the long review.
So far, besides the earlier reviews comments, these are all nits and up to you to change or not: some of the accessors (e.g., GetIsRemote) don't ensure the arg pointer is non-null - not sure if that's required or not currently. There's not much reason to change a single PRBool into a PRPackedBool since there will be no savings and could be a eensy teensy performance hit (not that it would matter in this code). In nsAbMDBDirProperty::GetValue* NS_ENSURE_SUCCESS(rv,rv); + return NS_OK; + these could all be NS_ASSERTION(NS_SUCCEEDED(rv)); return rv; which could generate one less return statement at the cost of not looking so pretty :-) . I've gotten to the aboutlook stuff so far, and I'm taking a break for now. Looks like a vast improvement so far.
In nsAddrDatabase, I think I see some tabs: + // we need to do this for dnd + PRUint32 key = 0; + err = GetIntColumn(cardRow, m_RecordKeyColumnToken, &key, 0); + PRUint32 count; + addressList->Count(&count); + + nsXPIDLString newEmail; + rv = newCard->GetPrimaryEmail(getter_Copies(newEmail)); + NS_ENSURE_SUCCESS(rv,rv); + + PRUint32 i; + for (i = 0; i < count; i++) { this left-over comment is a little cryptic //let it starts from 1 more tabs? I know sometimes cvs diff -uw shows funny things... + nsIMdbRow* cardRow = nsnull; + mdbOid rowOid; + rowOid.mOid_Scope = m_CardRowScopeToken; you can use an nsCOMPtr here if you want. + nsIMdbRow* cardRow = nsnull; and you might want to since I don't see you releasing this cardRow. This seems to be in several routines in this file so you might want to look over the uses of GetRow.
looks like tabs horked in > nsresult nsAbView::EnumerateCards() and in nsAbView::CreateCollationKey > // ensure restored selection is visible > if (cardWasSelected) { > if (mOutliner) > mOutliner->EnsureRowIsVisible(index); > } could be: if (cardWasSelected && mOutliner) mOutliner->EnsureRowIsVisible(index)
moving to 0.9.8, the AB_OUTLINER_BRANCH should land in early 0.9.8
Target Milestone: mozilla0.9.7 → mozilla0.9.8
sorry for the delay. I'll go work on the reviewers comments. the next patch will also have support for exporting addressbooks (to just .csv and .tab for now), some code cleanup, and some performance fixes to nsAbCardProperty::Get/SetCardValue(). I'll attach a new patch once I address all the comments.
new patch on the way. includes changes to export directories in .csv or .tab format. also some additional code cleanup (removed dead export code), and added file types for when doing text addressbook import. for the reviewers comments that I didn't address in the new patch: 1) > you have some logic that relies on the element's |checked| property's value. You > should check that it works, if you are messing with checkboxes, due to blake's > recent landing to make .getAttribute("checked","false") not work (and replace it > with .hasAttribute("checked")). The method in the patch works. has blake landed yet, or is he going to land? 2) > ChangeDirectoryByDOMNode(children[i]); > // XXX need this? return; I need that so I select just the first treeitem, instead of all the treeitems, and resulting in the the last one as being selected. 3) NS_ENSURE_SUCCESS(rv,rv); return NS_OK; vs NS_ASSERTION(NS_SUCCEEDED(rv),"..."); you are right, that in a non debug mode this results in one less if () check and one less return. I'm just not sure what to fill in for "...", so I've continued the pattern, since I get the assertion text for free. objections to me leaving it as is?
Attached patch updated patch (obsolete) — Splinter Review
updated patch, I haven't javadoc'd the new idl files (as dmose has requested) yet. this patch includes more cleanup, and code to handling exporting of directories to .csv / .tab formats.
Attachment #61192 - Attachment is obsolete: true
also in the last patch are some perf changes to Set/GetCardProperty() that code will hopefully go away, but until then, a long list of string compares is now some hairy switch statements that we can optimize more, by giving more common columns (last name, first name, primary email, phone, etc, stuff that commonly appears in the results pane) shorter code paths.
Attached patch updated patch (obsolete) — Splinter Review
localized some strings I forgot to localize, added a title to the export addressbook dialog, made it so if you delete the "current" addressbook (in the addressbook or the addressbook sidebar panel) we'll switch to the personal addressbook. I've fixed the nsIAbListener to do selective notification (like we do for folder listeners). we now delete the existing file on export (if the user confirmed to overwrite).
Attachment #61561 - Attachment is obsolete: true
Attached patch updated patch (obsolete) — Splinter Review
this patch fixes some problems with exporting, adds some code (but turned off with a comment) about how our .csv format is not like Outlook Express. this code also fixes a problem with the import code. the import code runs on another thread, so we need to proxy back to access the nsAddrDataBase when importing.
Attachment #61607 - Attachment is obsolete: true
this patch includes a new comment about how we should be integrating with the per server "maxHits" patch for ldap addressbooks, and has some ab / ldap cleanup.
Attachment #61636 - Attachment is obsolete: true
bloat / leak log when switching around between addressbooks (LDAP and local) the local ab code doesn't seem to leak, at least not the nsAb* objects. when using LDAP, we do leak. dmose says that might be a known problem, but we can investigate. here's the nsAb* object that leak, when you use ldap in addressbook. 108 nsAbBooleanConditionString 56 56 1 1 ( 1.00 +/- 0.00) 15 1 ( 1.69 +/- 0.66) 109 nsAbBooleanExpression 20 20 1 1 ( 1.00 +/- 0.00) 18 4 ( 2.63 +/- 1.43) 110 nsAbCardProperty 748 27676 552 37 ( 249.09 +/- 144.91) 5978 37 ( 254.44 +/- 153.75) 112 nsAbDirSearchListener 16 48 3 3 ( 2.00 +/- 1.00) 12 3 ( 2.71 +/- 1.10) 113 nsAbDirectoryQueryArguments 28 84 3 3 ( 2.00 +/- 1.00) 241 3 ( 2.98 +/- 1.09) 118 nsAbQueryLDAPMessageListener 68 204 3 3 ( 2.00 +/- 1.00) 27 6 ( 4.83 +/- 2.29)
Comment on attachment 61667 [details] [diff] [review] updated patch, includes some more clean up r=bienvenu
Attachment #61667 - Flags: review+
OK, here's my first set of comments; I'm only about 20% of the way through the patch, so there'll be more to come. Note that most of these are nits, and shouldn't hold up the landing of this patch, so if they should move to another bug, that's fine by me. nsAbFactory.cpp --------------- a) an extra commented out GENERIC_FACTORY_CONSTRUCTOR has been left here nsIAbCard.idl ------------- b) what's the point of getCardUnicharValue? nsIAttrDatabase.idl ------------------- c) getCardFromAttribute has "value" typed as a |string|. But values aren't necessarily just ASCII, right? ie shouldn't that be an |AString|? abCardViewOverlay.js ------------------ d) in GetAddressesFromURI, how about priming addresses with the first email address before beginning the loop and the start the loop with i=1? That way you don't have to evaluate the "if (i == 0)" on every pass through the loop. abCommon.js ----------- e) the license boilerplate added here is outdated; can you change it to the latest tri-license boilerplate from <http://www.mozilla.org/MPL>? f) GetSelectedAddresses: same as comment d g) GetSelectedRows: the |cards| variable doesn't appear to be used at all. h) GetSelectedRows: what's the point of outlinerSelection? why not just use gAbView.selection? i) GetSelectedRows: same as comment d j) GetSelectedAbCards: same as comment h k) GenerateAddressFromCard: I don't think it's necessary (and doesn't look so good) to have quotes around the display name if there's no unusual chars in it. One way to avoid that would be to have this function nsIMsgHeaderParser::MakeFullAddress under the hood? Although that seems to (in spite of the idl comments) use UTF8, so hmmmm.... I guess it depends what these generated addresses are used for. l) GetParentDirectoryFromMailingList: since the code here doesn't actually reference the abURI param, does this function work? And even if so, wouldn't it be significantly lighter weight to just search from the right end of the string for / and return a substring? general ------- a) any reason not to switch from addbook: to moz-addbook: URLs while we're here? b) for newly added methods, how about using AString instead of wstring? This will cut down on unnecessary mallocs(). c) I think you've missed adding yourself to the Contributor lists in some of the license boilerplates
Patch looks good. Here are couple of things I want to point out : 1. Looks like couple of globals (like gPrefs, gAddrbookSession in abCardViewOverlay.js) are defined in the middle of file, can be moved to the top. 2. You have already made note in the code to use string bundles (while copying cards, alerts, etc) in couple of places. If there is a major revision coming up, then you can fix those. Otherwise, a new bug will do. 3. Per http://www.mozilla.org/mailnews/specs/addressbook/ & section "Drag and Drop of Card Entries from One AB to Another", we should be doing a move instead of copy (copy when crtl key is used). If the change is simple fix this one. There is a open bug to track this already. I will get that one for you later. 4. looks like you forgot to remove #if 0 segment 5. if same primary addresses constitues equality, we shall get that into card's Eqauls API. 6. All that unused code from AddressBookParser::AddLdifRowToDatabase should go away. 7. + rv = abDataBase->GetCardFromAttribute(abDirectory, kPriEmailColumn, emailStr.get(), PR_TRUE /* lowerCase */, getter_AddRefs(existingCard)); if you care about the case here, the caseinsensitive boolean should be PR_FALSE...right..? r=bhuvan.
Additional comments; more to come, hopefully will finish tommorrow. abSelectAddressesDialog.js -------------------------- m) DropOnBucketPane: + var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService(); + if (dragService) + dragService = dragService.QueryInterface(Components.interfaces.nsIDragService); + if (!dragService) + return false; + Isn't it true that the only way drag service is gonna end up null will throw an exception? So I think try/catch is really what's needed here instead of those if statements. Same goes for the createInstance of |trans|, I think. n: DropOnBucketPane: it looks like this function returns |false| in all cases. Is this really what you want? addressbook.js -------------- o: outdated license boilerplate p: AddPrefObservers, RemovePrefObservers: does this syntax do the right thing? + var prefService = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); I thought the required syntax was .getService().QueryInterface(Components.interfaces.nsIPrefService). I seem to remember the currently used syntax causing problems with LDAP autocomplete. nsAbAddressCollecter.cpp, nsAbAutoCompleteSession.cpp: ------------------------------------------------------ q: any particular reason to use the CID for the message header parser rather than the contract ID? nsAbAutoCompleteSession.cpp --------------------------- r: how about using an NS_STATIC_CAST here, rather than C-style? + if (!aSubstrLen || (nsCRT::strlen(aString) < (PRUint32) aSubstrLen)) s: nsAbAutoCompleteSession::SearchDirectory(). any reason not to just use the libc version of strcmp here (since those are sometimes hand-optimized)? nsAbLDAPDirectoryQuery.cpp -------------------------- t: Assuming we don't mind a link-time dependency on libxpcom, you can get the proxy object service and an object all in one shot using NS_GetProxyForObject(), which is defined in nsIProxyObjectEventManager.idl. u: instead of using the deprecated n.EqualsWithConversion, how about using n.Equals(NS_LITERAL_STRING("card:nsIAbCard"))? nsAbMDBDirectory.cpp -------------------- v: There are a couple of instances of the c-style (const char *) cast; how about using NS_CONST_CAST instead? w: GetAbDatabase: Instead of using PL_strlen (instead of possibly hand-optimized libc version) and old string tech: + nsAutoString file; file.AssignWithConversion(&(mURI[PL_strlen(kMDBDirectoryRoot)])); how about one of: + NS_ConvertASCIItoUCS2 file(&(mURI[strlen(kMDBDirectoryRoot)])); or + NS_ConvertUTF8toUCS2 file(&(mURI[strlen(kMDBDirectoryRoot)])); nsAbQueryStringToExpression.cpp ------------------------------- x) nsISupports::AddRef is templatized in such a way that if you write this: + *expression = expr; + NS_IF_ADDREF(*expression); as this: + NS_IF_ADDREF(*expression = expr); it'll be compiled to code that is a bit faster. There are other instances of this in this patch, so you may wanna do a quick grep for NS_IF_ADDREF. nsAddrBookSession.cpp --------------------- y) NotifyDirectoryDeleted: c-style cast nsAddrDatabase.cpp ------------------ z) nsAddrDatabase::SetCardValue: any reason not to use NS_ConvertUCS2toUTF8 utf8str(value); instead of the INTL_ConvertFromUnicode stuff?
Remaining comments: nsAddressBook.cpp ----------------- A) The attribPairsType stuff looks like it duplicates code in nsAbLDAPProperties.cpp B) ::ExportDirectory: There doesn't appear to be any error checking on any of the calls through outputStream. Presumably we need to notice any errors (eg disk full) and propagate them to the UI. addressingWidgetOverlay.js -------------------------- C) DragOverTree, DropOnAddressingWidgetTrees: I think that .getService and .QueryInterface will throw exceptions for anything that's gonna make dragService or dataObj be null, so you probably need try/catch clauses here. fieldMapImport.js ----------------- D) same as C, with trans and dragService importDialog.js --------------- E) GetStringBundle: same as D F) ImportAddress: If it's really necessary to leave a dump() in production code (is it?), how about using a more meaningful message so that someone who hits this knows where to look? nsImportAddressBooks.cpp ------------------------ G) same as t abResultsPaneOverlay.xul abResultsPane.js addressbook-panel.js abResultsPaneOverlay.dtd abResultsPane.css (all versions) ------------------------ H) wrong license header addressbook-panel.js -------------------- I) gAddressBookPanelAbListener.onItemRemoved: you don't need the "directory &&" half of the if clause. If directory is null, the QI will have thrown an exception by this point, which will have kicked control to the catch clause. nsAbView.cpp ------------ J) why do all the NS_INTERFACE_MAP stuff by hand rather than using NS_IMPL_ISUPPORTS4()? K) ::GetURI(): how about using ToNewCString(mURI) instead of nsCRT::strdup? L) ::Init(): * if you make GENERATED_NAME be an NS_NAMED_LITERAL_STRING rather than a #define, wrapping it multiple times won't be necessary. * it looks as though actualSortColumn can be unnecessarily copied into twice in the same invocation. * it should be possible to use .Equals() and avoid the .get() required for strcmp * I think ToNewUnicode() is preferred to nsCRT::strdup() M) ::GetCellProperties * should the first if actually be |if (colID[0] != PRUnichar('G'))|? N) ::GetRowProperties: * why pre-initialize isMailList, since the existing value will be overwritten? * the call to properties->AppendElement() should be error-checked O) ::GetCardValue: * same as M * column can be declared as NS_LossyConvertUCS2toASCII column(colID); P) ::inplaceSortCallback(): same as M Q) ::GetSelectedCards(): NS_NewISupportsArray(selectedCards) seems to be called twice. As before, most of these are just nits; in general, this looks great and is clearly a huge step forward for the addressbook code.
I'm working on a patch for these issues. the only two I don't understand are two from bhuvan: 5. if same primary addresses constitues equality, we shall get that into card's Eqauls API. 6. All that unused code from AddressBookParser::AddLdifRowToDatabase should go away. bhuvan, can you elaborate?
5. if same primary addresses constitues equality, we shall get that into card's Eqauls API. I guess the real question is In nsAddrDatabase.cpp, at the context @@ -1656,22 +1568,64 @@ don't we already do, + if (!nsCRT::strcmp(newEmail.get(), currentEmail.get())) { while checking equality in + rv = newCard->Equals(currentCard, &equals); + NS_ENSURE_SUCCESS(rv,rv); If so, then I thought emailaddress check is redundant. If email is to be considered as a valid key to check while checking the equality, I thought that check can be placed in ::Equals() directly. 6. All that unused code from AddressBookParser::AddLdifRowToDatabase should go away. There are several instances of unused like the following in that routine - // else if ( -1 != colType.Find("charset") ) + // else if ( kNotFound != colType.Find("charset") ) // ioRow->AddColumn(ev, this->ColCharset(), yarn); Are we going to use any of these commented out code in the future..? If not, we should remove that code. bhuvan
thanks for the solid reviews. I've addressed all the comments (except for bhuvan's two, I'll go look into those.) new patch on the way. while I test my patch, and update my tree to the trunk, here's some feedback for what I didn't address: >l) GetParentDirectoryFromMailingList: since the code here doesn't >actually reference the abURI param, does this function work? And even >if so, wouldn't it be significantly lighter weight to just search from >the right end of the string for / and return a substring? whoops, not sure when abURI.match(RegExp()) became RegExp() I went back to the way I original did it, using split. 've added a comment to indicate that the function returns null when the uri is not a mailing list. >7. + rv = abDataBase->GetCardFromAttribute(abDirectory, >kPriEmailColumn, emailStr.get(), PR_TRUE /* lowerCase */, >getter_AddRefs(existingCard)); > >if you care about the case here, the caseinsensitive boolean should be >PR_FALSE...right..? fixed, the comment was wrong, the code was correct >q: any particular reason to use the CID for the message header parser >rather than the contract ID? fixed my usage and others, I noticed we had a mix of GetService and createInstance, so I switched them all to GetService(), as it is a service has no state. >u: instead of using the deprecated n.EqualsWithConversion, how about >using n.Equals(NS_LITERAL_STRING("card:nsIAbCard"))? even better that code can just be n.Equals("card:nsIAbCard"). I need to understand that code better to fully criticize what's going on. but on quick glance, it doesn't look kosher. >v: There are a couple of instances of the c-style (const char *) cast; >how about using NS_CONST_CAST instead? did foo.get() instead of (const char *)foo >z) nsAddrDatabase::SetCardValue: any reason not to use > >NS_ConvertUCS2toUTF8 utf8str(value); cleaned up a lot of the string foo, removed INTL_ConvertToUnicode() and INTL_ConvertFromUnicode() from nsDirPrefs.* > i) GetSelectedRows: same as comment d in this case, I'm interating over each range count, and then each value in each range count. so instead of just unrolling the first in a for loop I'd be unrolling the the first of the outer and more. I decided it wasn't worth it. > a) any reason not to switch from addbook: to moz-addbook: URLs while > we're here? I'll spin up a separate bug for that issue, for cavin, who will be working on printing and ab sync. > 3. Per http://www.mozilla.org/mailnews/specs/addressbook/ & section "Drag and > Drop of Card Entries from One AB to Another", we should be doing a move instead > of copy (copy when crtl key is used). If the change is simple fix this one. > There is a open bug to track this already. I will get that one for you later. yes, I've left it as a copy on purpose, until we discuss the behaviour. move has interesting issues, like what does it mean to move a mailing list? or move a card from directory 1 to directory 2, where the card is part of a mailing list on directory 1. > A) The attribPairsType stuff looks like it duplicates code in > nsAbLDAPProperties.cpp. it is. This table of columns, if we do it right, could be shared for import LDIF and .csv, exporting LDIF and .csv, and for LDAP. for now, I've removed the used ldif attributes from the table in nsAddrDatabase.cpp. getting all three places (import, export, LDAP) to use the same table is going to be an involved task, I'll spin it off to a seperate bug. > c) getCardFromAttribute has "value" typed as a |string|. But values > aren't necessarily just ASCII, right? ie shouldn't that be an |AString|? GetCardFromAttribute() and GetRowFromAttribute() require the value to be UTF8, I've fixed the variable name and added comments. >p: AddPrefObservers, RemovePrefObservers: does this syntax do the >right thing? > >I thought the required syntax was >.getService().QueryInterface(Components.interfaces.nsIPrefService). I >seem to remember the currently used syntax causing problems with LDAP >autocomplete. getService(Components.interfaces.nsIPrefService) works, we do it all over. I vaguely remember that with autocomplete, I'm not sure why we had to do that.
> 5. if same primary addresses constitues equality, we shall get that into > card's Eqauls API. now I understand. no, primary email address is not part of card equality, as you could have two cards with the same email. that's for comparing nsIAbCard instances, for cards in the local addressbook, we can use special attributes to determine if two nsIAbCards are the same. they way the addressbook code works, you could create more than on nsIAbCard for a given card in the addressbook. > 6. All that unused code from AddressBookParser::AddLdifRowToDatabase > should go away. I'll log a bug about cleaning up that code. it might be getting turned on, to expand our ldif import capabilities. patch coming soon...
Attached patch updated page (obsolete) — Splinter Review
this patch addresses the reviewers comments, and some polish: 1) existing or new profiles will only get the default columns, not all columns in the addressbook 2) when importing, we select the first item. 3) import module names are sorted. 4) "Text Files" -> "text files (LDIF, .csv, .tab, .txt)" 5) "converting mailbox from Text" -> "converting addresses from text file" 6) header parser, all callers do getService() instead of a mix of getService() and createInstance(). 7) after import of an addressbook, we now commit. there was a bug that if you quit right away, you won't save your imported ab. 8) support for "Map It!" addressbook feature.
Attachment #61667 - Attachment is obsolete: true
Comment on attachment 62530 [details] [diff] [review] updated page whoops, that patch has 2 conflicts.
Attachment #62530 - Attachment is obsolete: true
I'm not sure this is the right thread, but the address book really needs an address picker pane a la Netscape 4.76. Finding names by scrolling (with poor response time) a big address book is a total pain. I cannot get mailing lists to work at all. They do not import, do not display, and you cannot send mail to them! I tried the 12/7 build and was unable to use it at all because once one item (e.g., browser or mail) was opened, no others could be (like the address book).
> but the address book really needs an > address picker pane a la Netscape 4.76. Finding names by scrolling (with poor > response time) a big address book is a total pain. that's AB quick search, see http://bugzilla.mozilla.org/show_bug.cgi?id=83023 > I cannot get mailing lists to work at all. They do not import, do not display, > and you cannot send mail to them! can you log a bug to track this issue?
>> I cannot get mailing lists to work at all. They do not import, do not >> display, and you cannot send mail to them! > can you log a bug to track this issue? they work for me, so if you are having problems, please log a seperate bug.
Comment on attachment 62533 [details] [diff] [review] updated patch, fixed conflicts. r=dmose@netscape.com
Attachment #62533 - Flags: review+
this has sr=bienvenu. landed.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
Trunk build 2002-01-28-03: WinMe Trunk build 2002-01-28-08: Linux RH 7.1 Trunk build 2002-01-28-08: Mac 10.1 Verified Fixed.
Status: RESOLVED → VERIFIED
Product: Browser → Seamonkey
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: