Earlier, when I mentioned that I was going to work on polish, I was thinking of a rather unfortunate line in my original roadmap that honestly just said “polish.” I started this chunk of my GSoC project with a new list of things I have been putting off for said polish phase, and it turned out to be quite substantial. I have several cool new things this week.

First, I added a simple, custom container widget that allocates space for all of it children – whether or not they are visible – and distributes that space among the visible children. This way, our Break Schedule dialog is always the same shape, even though its contents change. This is sort of like using a GtkStack with the homogeneous property set to true. Once I wrapped my head around size requests and allocations and requisitions, it was really easy to implement. I’m not sure if it’s correct, strictly speaking, but it works for me.

class FixedSizeGrid : Gtk.Grid {
	public FixedSizeGrid() {
		Object();
	}

	public override void adjust_size_request (Gtk.Orientation orientation, ref int minimum_size, ref int natural_size) {
		foreach (Gtk.Widget widget in this.get_hidden_children()) {
			int widget_allocated_size = 0;

			if (orientation == Gtk.Orientation.VERTICAL && this.orientation == Gtk.Orientation.VERTICAL) {
				widget_allocated_size = widget.get_allocated_height();
			} else if (orientation == Gtk.Orientation.HORIZONTAL && this.orientation == Gtk.Orientation.HORIZONTAL) {
				widget_allocated_size = widget.get_allocated_width();
			}

			minimum_size += widget_allocated_size;
			natural_size += widget_allocated_size;

			widget.adjust_size_request(orientation, ref minimum_size, ref natural_size);
		}

		base.adjust_size_request(orientation, ref minimum_size, ref natural_size);
	}

	private List get_hidden_children() {
		var hidden_children = new List();
		foreach (Gtk.Widget widget in this.get_children()) {
			if (! widget.is_visible()) hidden_children.append(widget);
		}
		return hidden_children;
	}
}

The big thing I worked on over the last two weeks was making the break timer service remember its state between sessions. Break Timer will remember if you need to take a break after you log out or restart the computer, and in the future it will be able to keep track of interesting statistics very easily. This also makes it much, much harder to “cheat,” by accident or intentionally, because it will always pick up where it left off.

I decided to store the program’s state in the user’s cache folder using a json file, since we can work with json-glib quite nicely from Vala code. That happens when the process is (cleanly) interrupted or when gnome-session says it’s time to stop. (Thanks to Guilhem Bonnefille on gnome-devel-list for pointing me in the right direction about gnome-session). When the application starts, it reads that cache file and updates all its timers and counters accordingly. The way I implemented this leaves the door wide open for keeping breaks in sync between systems, over the network, which would be really cool.

I ran some finicky problems working on this; I guess I don’t usually have to work with quite as many moving parts. I was very glad that several years of people extolling the virtues of test-driven development (most recently David Cameron’s awesome Quality Assurance course at SFU) finally rubbed off on me: as soon as I wrote a test case for the problem I was working on, it all got way easier. And I got a (slightly clunky) test case for free! I must remember to do more of that.

2 Responses

  1. Hi, I’ve been using gnome-break-timer for a while – thanks for all your work. One thing though, I’ve just rebuilt it and I cannot set the frequency of breaks that I need as you can nolonger specify a custom break time (I used dconf-editor but that’s not very user friendly). Also will the new feature that remembers the time left take account of the time that has past since the user logged out? With the older version I was running until today (rev 168 from bzr) sometimes if I hibernate when a break is overdue then I get messages about my break being 15 hours overdue when I restart the next day, it doesn’t seem to realize I’ve had a break while the computer was off.

    • Yep! For any time that it has not been monitoring activity, Break Timer assumes you weren’t using the computer. So, if a break starts, then you turn off the computer for ten minutes and then turn it on again, it shouldn’t bother you at all :)

      I remember running into that problem with sleep, too. I recently added a test that simulates sleep and hibernate, and it should be passing now in the latest builds. I’ll take a closer look, though – I haven’t actually used hibernate in a while.

      We got rid of the “other” time input for now, to make it clearer how long durations and intervals should be relative to each other (more to avoid confusion than corner cases) and to get rid of that weird stack of modal dialogs. Not the best reason, so I’d kind of like to have it back, but I think it needs a different input mechanism. Something that plainly says “these are the kinds of values we’re thinking of”. Simply adding more choices could do fine, though, so, out of curiosity, what were the values you had entered?

      Thank you, Phil!

Leave a comment

Your email address will not be published. Required fields are marked *