Archive for May, 2007

Tabbed 3-pane UI in TB

Saturday, May 26th, 2007

I’ve been spending some time prototyping what tabbed e-mail browsing might look like in Thunderbird. The work is going on in bug 218999 - I’ve attached a couple screen shots as well - one of a folder open in a tab, and one of a message .

Currently a tab can be either an open folder, or a stand-alone message. When you switch between folder tabs, we restore the selected folder and message. If you select a message tab, we turn the 3-pane UI into a stand-alone message window, but just by hiding the folder and thread panes :-) Each tab has its own view and history context (i.e., back and forward are per-tab, as in the browser).

As capabilities are added to the 3-pane UI, they should be able to be opened in tabs. For example, you should be able to open Lightning in a tab.

Right now, I’m just using a generic tab widget. So there’s no close button on the tab (you have to use the tab context menu to close the tab), and tabs can’t be scrolled. It would be great if some xul wizard could adapt the tabbrowser.xml widget for use in TB. I tried early on, but ended up with centered tabs with no close button.

People have asked for the ability to put any mail window in a tab in the 3-pane UI - e.g., a compose window, or an address book. I think that’s a fine ultimate goal, but beyond the scope of what I’m doing now.

I’m quickly becoming addicted to these tabs - I open my “new messages” virtual folder in one tab, open an other tab for reading rss feeds, one for my bugs folder, and perhaps one for a particular message I want to go back to later. I find myself wishing the “has new” indicator would be shown on the tab if the tab is open on a folder with new messages. One nice thing about keeping the new messages virtual folder in a tab is that I can go read other folders without losing the read messages in my new messages folder, which I would if I switched away and back.

If anyone is interested in helping out, please let me know!

- David

Milimail project

Monday, May 14th, 2007

There’s an interesting Thunderbird project going on to add some enterprise features to Thunderbird. It’s called Milimail, and it’s backed by the French Ministry of Defence and British Telecom. See www.milimail.org for more info.

Where appropriate, we hope to roll some of this work into the core Thunderbird.

For example, they’ve just implemented triple wrapping. A triple wrapped message is one that has been signed, then encrypted, then signed again. While not quite as exciting as this Tripel, it’s still exciting. See bug 380624 for more info.

fun with nsILocalFile

Friday, May 4th, 2007

Heh, well my first post went out with the date my blog was set up, and not the date I submitted the post, because I edited the dummy post that was initially set up. So this is just a quick post to describe some of the fun we had replacing nsIFileSpec with nsIFile/nsILocalFile

The single biggest gotcha with nsIFile is that if you open an output stream on a file, write to it, and close the stream, the file still thinks its file size is 0, on Windows, because nsLocalFileWin.cpp caches the file size and has no api for invalidating the cache. The workaround is to Clone the nsIFile, or create instance a new nsILocalFile, and InitWithFile(theOldFile), and use the cloned/new object. You can also call Exists(), which invalidates the cache, at least on Windows (not sure about Linux).

There’s no way to create an input+output stream on a file, using the gecko classes. Surprisingly, there’s apparently no code in Firefox that needs to both read and write to the same file, except for the fastload cache, which has its own way of doing that. So I created an nsMsgFileStream class that implements nsIOutputStream, nsIInputStream, and nsISeekableStream. There are two methods in nsMsgUtils.h for this class:

NS_MSG_BASE nsresult MsgGetFileStream(nsILocalFile *file, nsIOutputStream **fileStream);

NS_MSG_BASE nsresult MsgReopenFileStream(nsILocalFile *file, nsIInputStream *fileStream);

Once you have a stream like this, you can QI it to any particular interface. It’s just a wrapper around a PRFileDesc *, with no buffering or anything fancy. We mostly use this object to deal with local mail folders, e.g., reading and writing the x-mozilla-status lines, or updating the x-mozilla-keywords header.

It doesn’t implement nsILineInputStream, because it’s almost as easy to use NS_ReadLine. The one drawback of NS_ReadLine is that it throws off the position of the stream, because it reads ahead. You can use the line buffer to calculate the real offset into the stream, e.g, http://lxr.mozilla.org/mozilla/source/mailnews/local/src/nsLocalMailFolder.cpp#3998

If I made nsMsgFileStream implement nsILineInputStream, then it could fix Tell and Seek to adjust for the NS_ReadLine buffering, if needed.

- David