Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Thunderbird/Lightning offers 5 different time intervals for refreshing remote calendars, between "Every Minute" and "Every 60 Minutes".

But, my work requires me to have over a dozen remote calendars, most of which won't change more often than once or twice a week. The result is that even on the longest refresh interval Thunderbird spend a lot of time re-downloading and updating calendar data that doesn't need to be updates, and slows to a crawl while it is doing so.

Is it possible to tweak/adjust Lightning to have longer refresh times than allowed by default (e.g. once per day)?

enter image description here

share|improve this question

1 Answer 1

up vote 2 down vote accepted

The refresh intervals are statically specified in the Lightning extension's source code, but Thunderbird extension code is all in Javascript and the XML dialect Gecko uses to specify user interfaces, so it's not particularly hard to add whatever intervals you need. Here's how you do so:

First, if you don't already have one handy, you'll need to download a copy of the Lightning install package. (The following assumes Lightning 1.9.1; the points of interest probably haven't changed much in a few versions, but for best results ensure that that's the version you're working with.)

Once you've got the .xpi file in hand, find a convenient, otherwise empty directory in which to unzip it -- an XPI installer is just a renamed zip file, so unzip, WinZip, WinRar, &c., &c., can all handle it. (You may have to rename it to '.xpi.zip' first, or right-click and "Open With...", depending.) Extract all of the files you find inside, preserving directories.

In general, you can usually find the code that handles a given dialog or other piece of UI functionality by hunting for strings that appear in it. In this case, I searched for 'Show Reminders':

me@box [lightning] $ find -exec grep -nH "Show Reminders" {} \;
Binary file ./chrome/calendar-en-GB.jar matches
Binary file ./chrome/calendar-en-US.jar matches
me@box [lightning] $ grep -a 'Show Reminders' chrome/calendar-en-US.jar
<!ENTITY calendarproperties.firealarms.label               "Show Reminders">

What this tells us is that, localization aside, the Lightning code internally refers to the string for which we're hunting as calendarproperties.firealarms.label. That's handy because now we know what to look for in the actual code; we'll find there at least one instance of that reference, and that instance will be very close to something that has to do with the dropdown we're interested in. So:

me@box [lightning] $ find -exec grep -nH 'calendarproperties.firealarms.label' {} \;
[many matches on i18n dialect files elided...]
./chrome/calendar/content/calendar/calendar-properties-dialog.xul:102:                  label="&calendarproperties.firealarms.label;"

Ah-ha! That's in a .xul file, so we know it defines a chunk of user interface; the label= looks like a label attribute for a UI control, which should mean we've found the code for the Edit Calendar dialog. The dropdown we're after appears shortly before the "Show Reminders" checkbox in the dialog, so it's a safe bet they'll be similarly juxtaposed in the source -- and, indeed, when we look into calendar-properties-dialog.xul, we see this in lines 79-89:

    <menulist id="calendar-refreshInterval-menulist"
              disable-with-calendar="true"
              label="&calendarproperties.refreshInterval.label;">
      <menupopup id="calendar-refreshInterval-menupopup">
        <!-- This will be filled programatically to reduce the number of needed strings -->
        <menuseparator id="calendar-refreshInterval-manual-separator"/>
        <menuitem id="calendar-refreshInterval-manual"
                  value="0"
                  label="&calendarproperties.refreshInterval.manual.label;"/>
      </menupopup>
    </menulist>

Huh. We're not quite home and dry, because the interval specifications don't live here. It would be nice if that comment mentioned exactly which source file contained the code responsible for filling the dropdown options, but perhaps that's something a seasoned XUL hacker wouldn't need to be told. That said, it shouldn't pose too much of a complication; we now have the ID for the dropdown menu, which will almost certainly be referenced in whatever code fills the dropdown, so:

me@box [lightning] $ find -exec grep -nH 'calendar-refreshInterval-menulist' {} \; 
./chrome/calendar/content/calendar/calendar-properties-dialog.js:91:        let value = getElementValue("calendar-refreshInterval-menulist");
./chrome/calendar/content/calendar/calendar-properties-dialog.js:153:        let menulist = document.getElementById("calendar-refreshInterval-menulist");
./chrome/calendar/content/calendar/calendar-properties-dialog.xul:79:        <menulist id="calendar-refreshInterval-menulist"

The third match points to the .xul file we already know about, and we can ignore it. The first match points to some code that's getting the currently selected value of the dropdown, and we can ignore that. The second match, on the other hand, takes a reference to the dropdown as a whole, and that's probably what we need. And, indeed, if we examine calendar-properties-dialog.js, in lines 154-162 we find:

    for each (let min in [1, 5, 15, 30, 60]) {
        let menuitem = createMenuItem(min);

        separator.parentNode.insertBefore(menuitem, separator);
        if (refreshInterval == min) {
            menulist.selectedItem = menuitem;
            foundValue = true;
        }
    }

And here we are! An array of values, expressed in minutes, which correspond with those you see in the Edit Calendar dropdown.

Now, looking at the way these menu items are set up, the whole process seems to assume that they'll only ever be expressed in minutes (e.g. the createMenuItem function, lines 137-146.) If we were going to contribute this change upstream, we'd definitely want to modify that function so that it can produce dropdown elements with labels in arbitrary units of time, such as "Every 4 hours", "Every 1 day", &c. We could still leave the underlying representation in minutes, but we'd want to clean up the display code so that it didn't look ugly.

However, since all you're really after is the functionality itself, we'll leave making it pretty as an exercise for the interested reader. Just add the intervals you want to the end of the array on line 154, as for example:

    for each (let min in [1, 5, 15, 30, 60, (60*4), (60*8), (60*12), (60*24)]) {

(Sure, you could add those as 240, 480, 720, and 1440, but why not let the interpreter do the work? Spend CPU time to save programmer time. This'll only be evaluated when you open the New Calendar and Edit Calendar dialogs, so you're not really making a lot of work for the computer to do.)

Once you've saved your changes and closed the file, all that remains is to repackage the updated Lightning code and install it in Thunderbird. That's quite simple:

me@box [lightning] $ zip -r lightning-1.9.1-me.xpi *

(Or use WinZip, WinRAR, &c., whatever you've got. The salient points are that the finished ZIP file must preserve directory structure, and that its filename must end in .xpi -- as on the unpacking step, it can be renamed after creation if need be.)

Then install your newly created XPI file as you would any Thunderbird add-on. Once you've done so and restarted Tbird, opening the Edit Calendar dropdown will produce this:

Modified 'Edit Calendar' dialog, showing newly added intervals

For the sake of completeness, I must mention that I haven't actually tested to confirm that the calendar actually refreshes with the intervals given, because something I haven't fixed yet is making my Thunderbird throw an exception when I select the Extensions tab in the Add-ons Manager -- I produced the above screenshot by creating a new Tbird profile and installing the modified Lightning add-on there.

That said, I have no reason to suspect there'd be a problem, since there's only the one place in the code where the interval length options are specified; once set in the dialog, they're stored with the Thunderbird config data.

Which brings up a point: if you know the GUIDs for the calendars whose refresh intervals you want to customize, you can do so in the "Config Editor" (i.e. about:config) offered in the Advanced tab of Thunderbird's Preferences dialog; change the value of calendar.registry.[guid].refreshinterval to however many minutes you like.

In order to do so, you do need to be able to map calendar GUIDs to names, which can be done pretty straightforwardly in about:config. If you type .name into the search box, many results will appear, but only a few of them will belong to the calendar.registry group, and all of those should be bolded since they're not present by default in Thunderbird; each of those values being a calendar name, and each result containing the calendar GUID in the property name, you can trivially construct a mapping between name and GUID. Then type .[guid].refreshinterval into the search box, customize the value, and you're done.

But that's a pain in the neck if you've got many calendars to deal with, and judging by what's visible of the list in the background of your screenshot, you have a sizable number of calendars to which to apply this change -- that being the case, I'm thinking the dialog change may give you an easier time of it.

Especially since you can download a version of Lightning, containing the modifications described in this post, here!

share|improve this answer
    
Wow -- thanks so much for the detailed and thorough answer! This will be a great guide as I look for other tweaks as well. A big +1, and I'll accept the answer once I've been able to confirm that the new refresh intervals work :-D –  anschauung May 3 '13 at 17:52
1  
Glad to be of help! I've been surprised by how easy it usually is to hack Thunderbird extensions so they do what I want, and I'm always happy to share what I've learned. :) –  Aaron Miller May 3 '13 at 17:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.