Category Archives: General

Testing Glade files

I often edit Glom’s .glade files by hand instead of using Glade (though that should get better now that we have a GtkSourceView catalog for Glade, and that Openismus is paying Tristan to do a little cleanup in Glade). But I often make mistakes, so I added some tests. These run when doing “make check”, for instance during “make distcheck”, thanks to the autotools’ lovely built-in features.

Here are links to the two tests, in case it’s useful to anybody else. Maybe other people have other useful tests?

  • Check the glade files for validity (a Glade DTD would make this even better if someone can finish it)
  • Check instantiation: Check that all top-level windows and dialogs can be instantiated and check that none have visible=true.?
    This is C++, with libxml++ and gtkmm, but it’s simple.
    It would need slightly cleverer code to get secondary top-level objects such as GtkAdjustments and GtkTreeBuffers, because gtk_builder_add_objects_from_file() fails unless you specify secondary objects explicitly. But we avoid using these in Glom, because it’s easy to break the code at runtime when one is added to the .glade file, and it’s less of a problem now that Glade doesn’t create them when the default values would be acceptable. Another workaround is to put all windows in their own .glade file, but that makes it hard to work with them all together in Glade.

gtkmm 2.20 released

Yesterday I released the API/ABI-stable gtkmm 2.20.0.

Some GNOME friends recently suggested that we should hype gtkmm more, and the applications that use it. I think they want us to use meaningless phrases like more-productive, ground-breaking, state-of-the-art, etc. I won’t do that, but it’s nice to note that gtkmm has now tracked the GTK+ 2 API for 7.5 years, and has officially followed the GNOME release schedule for 6 years. It is the pure C++ GUI toolkit that you can depend on, if you like that kind of thing, while still easily using other standard tools and APIs. Its ongoing development is entirely open.

It will help you write code that works and that you understand better. It won’t help you “just” write code in 10 times less time, or with 10 times less bugs, but nothing can because software development is difficult and likely to remain difficult.

I will take the opportunity to link to gtkmm’s documentation and to mention that a company, Openismus, funds its development and offers paid support and training.

What our Trainees Learn

After our successful year of training at Openismus, I thought I’d publish the rough bullet-point list that we used. Whoever we choose for the following year will repeat much the same process, with in-depth critique and a dose of reality.

These were our overall aims:

  • Familiarity with the programming languages, toolkits, and tools, beyond the average.
  • Good quality habits – documentation, ChangeLogs/commit-messages, bug filing, simple code.
  • Good communication – politeness, precision, knowing who/where to contact, tracking progress and following up.

And this is the stuff that we checked off along the way:

Knowledge of C

  • Respect for memory. True understanding of pointers.
    • Understanding of the many ways to use * and & and [], declaring and dereferencing.
    • Understanding of state (Such as a widget’s data, or a user_data struct, or a C++ class’s member variables.)
    • Understanding function pointers, including their weird syntax, made easier by use of typedefs.
  • Basic understanding of object-orientation – Write functions that have a namespaced prefix and that take a first self/this parameter.
    • Write init and free functions where appropriate.
    • Don’t use a prefix that is used by an existing library.
  • Use of enums (or defines if necessary, or static constants if appropriate) instead of magic numbers/strings.
  • Breaking code up into small blocks, separated by empty lines, with pseudo-code comments above each block. In small functions, of course.
  • Initializing local variables, even if you don’t think it’s necessary.
  • The GTK+ coding style, which is common for C.

Knowledge of GTK+

Familiarity with GTK+, to the level of implementing new widgets.

  • Reference-counting: Conventions and special cases (gstreamer and tinymail use a different convention, for instance).
  • Child widgets don’t really use reference-counting. They are destroyed by parents regardless.
  • Glade and GtkBuilder
  • Implement a new widget, doing some custom drawing and/or containing some child widgets. Make sure that you understand what the various construct/init/finalize/destroy/etc vfuncs do.

Other C stuff and basic tools

  • Tools: gdb, valgrind, svn, git, diff, patch.
  • Writing ChangeLog entries or commit messages (mentioning files and functions, and what changed in them and why).
  • autotools
  • gtk-doc syntax, and knowing what developers need to see in the documentation. Mention the what, when, why, how, and “see also”.
  • Familiarity with Clutter, to the level of implementing new actors. See the Openismus Clutter tutorial.
  • Fix some GNOME bugs, submitting patches. Maybe work with the gnome-love group.

Communication

  • Join the relevant GTK+, GNOME, Maemo, and Qt mailing lists.
  • Add Openismus employees to your GNOME bugzilla Users To Watch list. Someone will watch yours too.
  • Be repeatedly told to file bugs and patches, and to follow up on them. File bugs about documentation too.

Familiarity with C++ – at least the parts used by gtkmm and Qt

This takes more time than anything else, but its doable with motivation and mentoring from our experts.

  • Read a full book, such as Accelerated C++, cover to cover.
  • Understanding of classes, constructors, inheritance, polymorphism.
  • Understanding of references.
  • Understanding of const and mutable.
  • Templates. And template specializations.
  • Use of std containers.
  • Familiarity with gtkmm (easy because they know GTK+ already.)
  • The gtkmm coding style, which is common for C++.
  • The doxygen/javadoc syntax.
  • Wrap some new GTK+ API for gtkmm.
  • Fix a Glom bug. For instance, there are some simple Glom gnome-love bugs.
  • Familiarity with Qt. Understand what moc does. Do something real-world with it’s (quasi) model/view widgets. Understand QString historical oddities.
  • Maybe find a bug to fix in KDE.

Optimization work

  • Understanding processing, memory, and IO costs.
  • Avoiding premature optimization while avoiding obvious performance errors.
  • Using Oprofile, SysProf, system tap, etc.

Debian/Ubuntu packaging

  • Package a new version of an existing package, such as Glom, in the Openismus PPA.
  • Package something new for Ubuntu.

Embedded Linux

  • Use of Scratchbox with Maemo.
    • Port something to Maemo.
    • Package it for maemo-extras.
  • Using a BeagleBoard:
    • Set up the BeagleBoard and get something running.
    • Try to install Mer.
    • Putting a self-built distro on generic hardware (BeagleBoard), using Poky or OpenEmbedded.
  • Be aware of differences/pros/cons between Poky and OpenEmbedded.
  • Document how a customer might prepare and maintain a custom debian (or Ubuntu) distro for their embedded hardware project. For instance, how to install and use an autobuilder for packages.

Openismus Wants More Trainees

A little over a year ago, we hired our first batch of Openismus trainees. After an intensive year gaining knowledge and experience, I’m proud to say that David King and Michael Hasselmann have now graduated to regular work on customer projects. They’ve become solid developers in whom we have confidence, thanks to mentoring from all our other employees. Personally, creating these new development careers is one of the most worthwhile things I’ve done in my career.

So we need some more people to repeat our success. Here’s the text from the first time:

If you are smart and enthusiastic but you lack experience then we can provide the opportunity. You would work mostly on existing open source projects instead of customer projects, just to get experience with C, C++, GTK+ and Qt. Our developers would provide technical guidance and encourage you to work and communicate in a structured way, creating software that’s actually usable and useful.

This is also a great opportunity to move to Berlin – a wonderful city for young people. Munich may also be a possibility if necessary.

I’d also like to point out that we are very much an equal-opportunities employer. We get almost no applications from women or minority groups and that’s not good enough. We are a small company so every new person can make the place more like themselves.

Please send us an email telling us about yourself. Show enthusiasm and show us anything you’ve done in the open source world already. As before, I will filter out the least suitable candidates by expecting you to find the appropriate email address yourself. Unfortunately, as before, it’s unlikely that we’ll want to deal with visa paperwork if you are not already working in the EU.

Update: We think we have chosen our new trainees already. Stay tuned. Do bug me if I have not replied to you.

Glom 1.13/14 using boost::python

Finally Figured Out boost::python

After lots of experimentation and two previous failed attempts, Glom now uses boost::python, with very little use of the nasty Python C API remaining. This should make it easier to add Python API to easily access and set field/record/table/database details from the Python that’s used in calculated fields or button scripts.

Useful Things I Now Know about boost::python

boost::python is no fun to get started with, but it’s now far easier for me to use than the Python C API.

I’ve mentioned the awful boost::python documentation before. Here are some essential things that I figured out, which are not really documented. This is thanks to helpful people on the boost::python mailing list. Corrections welcome – there’s so much here that some of it must be wrong.

None of this is very obvious or pleasant. If anyone had their first real C++ experience with boost::python then I’d forgive them for being put off C++ for good. I love C++ so that would be unfortunate.

“Converting” between C and C++ object types

C++ to C: To get the underlying PyObject* from a boost::python::object (awful docs), when you need to use a C function:

PyObject* cobject = theobject.ptr();

To test for a boost::python::object with a null underlying PyObject*, do:

if(cppobject.ptr())

Do not do if(cppobject). That tests if the python object is actually a boolean that is PyTrue.

C to C++: To get a boost::python::object for a PyObject*, when you received one from a C function, but you then need to use the result in a C++ function, or just want the improved memory management:

  • If the C function gave you a reference that you should later unreference:
    boost::python::object cppobject( (boost::python::handle<>(cobject)) );

    (You need those extra brackets, for “interesting” compiler reasons.)

  • Or, if you need to take a reference.
    boost::python::object cppobject(boost::python::borrowed(cobject));

    (Yes. that’s horrible too. I see no reason to expose boost::python::handle in the API.)

  • However, you’ll need to use allow_null too to avoid exceptions if the PyObject* might be null. Well, any pointer could be null, so say hello to:
    boost::python::object cppobject(  (boost::python::handle<>(boost::python::allow_null(cobject))) );

    or

    boost::python::object(boost::python::borrowed(boost::python::allow_null(cobject)));

    (Shoot me now. No, reducing it to b::p::whatever is not a significant improvement.)
    I understand that a null PyObject* may sometimes be an exceptional unexpected event, but forcing the use of a try/catch by default just for a null pointer check is annoying. Explicit functions such as wrap() and wrap_not_null() would be so much easier.
    See the equivalent for gtkmm (plus calling reference() when necessary with non-widgets).

Using boost::python with your own wrapped C++ classes.

  • To get a boost::python::object for an instance of your C++ class that you’ve wrapped for Python with boost::python::class, just do:
    boost::python::object obj(new YourWrappedClass);
  • To get a C++ instance of your wrapped class from a boost::python::object, use boost::python::extract (as also mentioned generically below):
    boost::python::extract<MyClass*> extractor(cppobject);
    if(extractor.check()) myobject = extractor;

Others

  • To get a C++ value out of a boost::python::object do, for instance:
    boost::python::extract<std::string> extractor(cppobject);
    if(extractor.check()) mystring = extractor;

    You can do

    mystring = boost::python::extract<std::string>(cppobject)

    without the check() but that will throw an exception if the underlying type is not really what you expect.

  • boost::python likes to throw exceptions. I think it only ever throws boost::python::error_already_set, though the (Python) error is often not already set when it’s thrown. When the error is set, you’ll need to use Python C API to discover what it is.
  • To provide [] syntax in python for your wrapped class, you’ll need to know how the C API works. Add this voodoo to your boot::python::class declaration:
    .def("__getitem__", &MyClass::getitem)
    .def("__len__", &MyClass::len)

    Those methods can then have signatures like this:

    boost::python::object getitem(const boost::python::object& cppitem);
    long len() const;
  • To use Python date or time values, you will need to use C Python functions. For instance:
    PyObject* cobject = cppobject.ptr();
    int day = PyDateTime_GET_DAY(cobject);
    int month = PyDateTime_GET_MONTH(cobject);
    int year = PyDateTime_GET_YEAR(cobject) );

Boost has no .pc files

boost is a complete pain as a dependency. I understand that they don’t want to freeze API or ABI, because it’s a place for gradually improving API, though I think they should just have regular stable/devel phases with parallel installs. But I can’t forgive how difficult it is to get the header and linker options to use boost libraries. There are some m4 macros out there but they are hacky and fragile, and don’t actually work for boost::python. It shouldn’t be hard to provide pkg-config .pc files, so you wouldn’t need to do any compilation or linker checks in configure at all. I hacked some m4 code together based on some existing stuff, but I couldn’t recommend it.

So distro packagers won’t enjoy this new dependency. Sorry.

Openismus Website Now More Shiny

Daniel Borgmann has prettied up our Openismus website a little. The small touches make it easier on the eye. It’s no longer so adaptable to every screen size or font size, but it’s still relatively simple. It wasn’t us who broke the web, though we tried not to break it more.

Daniel would have liked to do much more impressive things, but I held him back because I like gradual iterative changes and very maintainable files. He did this without changing the content at all. We’ll see what happens next.

In Helsinki at the weekend, Monday and Tuesday

Liam says “broombroom soon Stinky Mama Papa mit”.

That means that we will be flying in an airplane on Friday to Helsinki. I’ll be around for work stuff on Monday and Tuesday too. Most afternoons are planned out already, and evenings are generally difficult with a child, but I hope to see random Nokia/Maemo people, maybe at lunch. I shall be pinging you.

We are looking forward to seeing old friends who we don’t get a chance to see often enough.

Kat, David, Mathias, and Daniel will be around too.

GtkToolPalette in GTK+ 2.20

We (Openismus) recently got our GtkToolPalette widget into GTK+’s git master, to be seen in recent GTK+ 2.19 (unstable) tarballs. We haven’t had much extra time for this kind of thing, so I’m glad it’s finally done after being worked on now and then by Mathias Hasselmann, Jan Arne Petersen and Johannes Schmid. Thanks to Matthias Clasen for valuable reviewing and cleanup.

We hope that this can replace the hand-coded tool palette widgets in Glade and Gimp, as well as making this easier for new applications. It replaces EggToolPalette in libegg, where we started the work. Please take a look and report any problems. I’m already using it in a Glom branch.

Here’s the GTK+ API reference for GtkToolPalette. There’s a GtkToolPalette example in gtk-demo.

And here’s a little introductory Gtk::ToolPalette chapter I wrote for the gtkmm (C++) book. Note that gtkmm’s API reference for this is mostly empty, but fixed already in git.

Peter Penz Joining Openismus

I’m pleased to say that Peter Penz will become an Openismus employee at the start of February. I’ve known and liked Peter since I worked with him six years ago in Linz, Austria on a proprietary C++ mobile phone platform. Back then I was impressed with his skill and temperament so I’ve watched with interest as he has become a core KDE maintainer via the Dolphin file manager.

Obviously Peter will help Openismus as we gain experience with Qt for Maemo 6 (Harmattan) in addition to our continued use of GTK+ and gtkmm.

Peter will work from home in Linz, occasionally visiting the office in Berlin. I like the idea of another office in Linz though.

Liam at Two

December’s long season of presents is over and Liam is now two years old.

He’s recently started the famous language explosion, learning several new words each day. He’s obviously aware that he speaks two languages, now learning to say both words instead of preferring the first one he’d learned. He still prefers hand gestures where he has learned them first, seeing no need to learn words for them too.

For the past couple of months Liam has spent the mornings in the crèche over the road. That’s why I’m online again every morning. It’s great for him to learn some independence and spend time with the same kids every day. Leaving him there in tears has been heart-breaking every morning for weeks, but now he’s happy to go there and is nonchalant about us leaving.

I was worried when he suddenly learned more German at the crèche, but that has settled down now. Still, I make an extra effort with plenty of English books and music and some DVDs of gentle British children’s TV from the 70s, such as The Wombles and Ivor the Engine.

The language explosion was accompanied by a sudden increase in general understanding and concentration. Now he happily listens as I read all of a Dr Seuss book to him and seems to understand narrative instead of just wanting to identify objects. His imaginative play is more complicated, with detailed routines.

We’ve had a little snow in Munich this week. Liam learned to walk in last year’s snow. I hope he remembers enjoying this year’s.