Friday, June 10, 2011

Calendar Update Part II - After The Release

Following up on my promise to detail some of my future plans. But first, a word about that nasty memory leak.

Memory leak in pycairo or pango/cairo.


I am 80% confident that there's a bug in the python bindings shipped on ubuntu 10.10. I developed a minimal example, (full source here), which just draws some text repeatedly in a window. The relevant bit of this example is the following function:

def draw_text(self, cr, text, x, y, width):
        pcr = pangocairo.CairoContext(cr)
        lyt = pcr.create_layout()
        lyt.set_text(text)
        lyt.set_width(pango.units_from_double(width))
        lyt.set_wrap(pango.WRAP_WORD_CHAR)
        cr.move_to(x, y)
        pcr.show_layout(lyt)
        return lyt.get_pixel_size()[1]

This little script will om nom nom your memory -- over 100 mb of memory after just a few minutes, and I think we can all agree that even if this it's not the most efficient example, its memory usage should be nearly constant. I haven't yet opened a bug, because I still don't know which component(s) contain the actual leak. At least feel better that it's probably not something I'm doing wrong, which gives me the confidence to move forward with the release.

To mitigate against the leak, I threw in an optimization that ensures only one pangocairo context and one text layout is created, per expose event, per widget. This seems like a reasonable thing to do in general, so I will probably leave this optimization in even after the bug is fixed. Unfortunately, all this does is slow down the leak. The leak is still there, which means you still wouldn't want to leave the calendar application running indefinitely.

In passing I'd like to say that the idea that a pango layout needs to be associated to a particular context bothers me a lot. I wonder if I can get away with re-using layouts with different pangocairo contexts.

A better grammar

The current parser for recurrence expressions could use some serious help. The parser for the existing grammar is in the "proof-of-concept" stage of development. It's intuitive for simple things, but you will notice that parenthesis are needed to get correct parsing of more complicated examples. This is due to unresolved ambiguities in the grammar.

Most of the ambiguity could likely be resolved with associativity and precedence declarations, but when you're developing a new notation it's difficult to know in advance what the intiutive associativity is. Basically I didn't bother trying to get it right at all, and rely on parenthesis as a crutch. I recognize that this neither intuitive nor natural. Even I am surprised at how wrong the unparenthesized parse can be.

I am also aware that this approach is horribly anglo-centric. You would have to write separate parsers for  every language you wanted to support, and it's a good bet that language constructs don't always map onto each other so neatly.

I am also playing around with graphical approaches to the same problem, but to be perfectly honest they've all sucked so far. I might do a separate posting on one of them just to show you how god-awful it is.

A mouse-driven way to add recurrence exceptions.

When dragging a recurring event, the current behaviour is to shift the entire recurrence pattern. This is a deliberate choice on my part: it's a novel feature that I want to highlight it. Unfortunately, many times time what you actually want to do is shift just the occurrence you've selected, and occasionally you want to move all the events after the selected occurrence.

Note, you can do this now: however, you have to go through the text interface. Even I find this quite tedious. The solution most obvious to me is to introduce control and meta modifier keys, but I have found that other users do not share my enthusiasm for mouse modifiers. In usability parlance, we say that   modifiers are less discoverable than more explicit features.

Another idea would be to add some tool bar buttons that silently add modify the recurrence rules of the selected event. This would be fairly easy to do, but I have a couple of misgivings. The first is that the toolbar is getting crowded already. The second is that it won't be obvious what those buttons do at first. Clicking on the "except this occurrence" button will not produce an immediately visible change, only modify the behavior of future interaction. This would be especially be confusing if you hit the button by accident.

A more radical idea would be to place special "handles" on the clip itself. That way dragging from a handle could have a different meaning from dragging the clip itself. I am leaning towards this approach, but it is not without drawbacks of its own. For example, the handles compete for space with the event text. They will necessarily be small, which could hurt usability in a tablet.

Integration with other calendars

Syncing with Google Calendar and / or EDS
importing from, and exporting to, .ics.

This work ought to be pretty straight-forward given how the code is organized, but I haven't really looked in detail at the APIs / File formats I'd be working with. If you're interested in helping out with that, you know where to find me ;)

Event alarms

This might not be necessary if I can use something like EDS as the default back-end. But we'll see. Depending on how hard it is to map the concepts in my application onto the APIs exposed by EDS, it might be easier to roll my own implementation.

No comments: