Category Archives: General

Maemomm: Maemo for C++, with gtkmm

gtkmm is now available for the new Maemo 3.0 “Bora” version, as used on the Nokia N800 Internet Tablet. It’s in the extras repository.

There are also gtkmm C++ bindings for the Maemo UI (hildon-libs and hildon-fm) widgets, covered in the online maemomm documentation. Nokia tasked Openismus with updating these bindings for the N800 and writing the documentation, which was done mostly by Johannes Schmid and Daniel Elstner in the last few weeks of 2006. Of course, no applications use maemomm just yet, though gtkmm is already used enthusiastically on other embedded devices, and the demand for gtkmm on Maemo has been strong, so let’s see what happens.

It’s a slightly cut-down version of gtkmm for embedded devices, but most programmers won’t notice much difference in the API. I’d welcome patches to reduce the code size and memory requirements even more. It’s gtkmm 2.6 for now, but it looks like Maemo will update to GTK+ 2.8 or 2.10 in the near future. For the “armel” architecture that runs on the device, the (stripped) gtkmm library is 1.4M, which is a (small part of the) small price to pay if you prefer C++.

libgnomedbmm: Database UI widgets for gtkmm

Johannes Schmid and Armin Burgmeier have almost finished the C++ bindings for libgnomedb for Openismus, and the work so far is now in GNOME’s subversion repository, in the gnomemmm/libgnomedbmm module. There are already working examples in svn. This needs the latest version of libgdamm, which we have updated for the latest libgda API.

They will soon start on the documentation, to show how to use this stuff easily.

This work is for a company (Openismus codename: “The Austrians”) making some specialized embedded Linux equipment, using gtkmm for the UI.

A screenshot of a libgnomedbmm example:
libgnomedbmm_example_form

Linux-compatible wireless USB adaptor that I can actually buy? (part 2)

This is a follow up to my previous post: Linux-compatible wireless USB adaptor that I can actually buy?

I was really sure that the ralink-based ASUS WL-167G would be the one. But no, the ASUS WL-167G does not work in Ubuntu Edgy or Ubuntu Feisty (herd 2). In fact, the (open source) Ralink drivers seem to be a problem on most recent Linux distros. I’ll try compiling the drivers myself soon, but I want an out-of-the-box working wireless USB adaptor.

Based on the comments to my previous post, I now think that the zd1211-based MSI US54SE is the one that is likely to really work out-of-the-box. It’s available in Germany.

As far as I can tell, there is not one single Wireless USB adaptor that’s (widely) available in the USA that will work out-of-the-box with Ubuntu Edgy. All the models that have worked before now have seem to have new unsupported chipsets, without changes of model name.

Linux-compatible wireless USB adaptor that I can actually buy?

Has anyone bought a USB WiFi adaptor (54 speed rather than 11, ideally), in the last few months that actually works with Linux (preferably Ubuntu) without using the Windows driver via ndiswrapper?

There are several reports of adaptors that worked out-of-the-box but all those adaptors now seem to be sold with the same model names, but with different chipsets that don’t have Linux drivers.

Or even a PCI card? They keep changing those chipsets too.

New printer: Lexmark E120n

I got tired of my HP Deskjet 3650 just sitting there flashing its light, though it has a new ink cartridge [1]. Even when it worked, the page often slipped while (slowly) printing, and the page took a while to dry.

So I bought a Lexmark E120n. It’s a small cheap laser printer rather than an inkjet printer. Refreshingly, it’s mono only – black and white. I rarely print color and I don’t want to worry about whether I have enough color as well as black ink. The HP 3650 went through a phase of printing everything in green, which I won’t miss.

More significantly, it’s networked by default (wired, not wireless), though you can use the USB connection instead. After powering on, it connects to your network and prints out a page to show you what IP Address it is using. It has a web-browser configuration UI at that address.

Lexmark E120n printer

The CD includes Linux drivers, and the html documentation on the CD states that they officially support Debian, Linspire, Red Hat, and SUSE Linux. All the Linux stuff is in the “unix” directory on the CD, though the readme.txt file there explicitly states that the directory name and other mentions of “unix” should not imply support for crufty old UNIX – it’s just Linux that’s supported.

Even when connecting over the network, you need to choose the printer driver. The GNOME/Ubuntu printer manager didn’t list this model of Lexmark printer. Also the CD doesn’t have a bare .PPD file, so the “Install Driver” feature can’t work. There is a .deb file (.rpm too) but it contains lots of other stuff that I’d rather not risk installing if I don’t need to.

Googling told me that I could instead just choose the “PCL 6/PCL XL Printer” model from the “Generic” manufacturer, after choosing to add a Network printer of type “CUPS Printer (IPP)”, specifying the IP address, and that works fine. I’m using Ubuntu Edgy. Update: Instead of using the generic PCL driver, use the PPD file that Sven mentioned in the comments – the generic one has problems printing graphics. Also, note that you can get the IP Address printout at any time by pressing the green arrow “continue” key.

When it prints, it has that pleasantly familiar airplane takeoff sound rather than the wheeze of an Inkjet. It’s quiet when on standby, though I’ll keep it turned off because it probably draws lots of power.

[1] If the 3650 was sending any status errors over the USB cable, they weren’t showing up anywhere in the GNOME printer UI. I did try installing the HP Deskjet 3650 driver and tools on a Windows laptop but, after self-extracting the 3600_enu_win2k_xp.exe file, it just showed me an otherwise empty and untitled error dialog with the text “1158:”. There was a button on the dialog, but it was empty too. Which was, frankly, Windowstastic.

Irrelevant Update: However, I absolutely can not get the thing to work with my girlfriend’s old Windows ME laptop. Lexmark say that the printer is supported on Windows ME, but the installer refuses to run, saying “This intallation method is not supported on this operating system”. Installing the driver manually via the wizard, typing in the IP address, because browsing doesn’t work, leads to Windows telling me that the printer is currently offline. I’m waiting for the Windows installation to become so broken that it must be replaced with Linux.

Creating GTK+ input methods

I have just implemented a GTK+ input method to allow input via multiple key presses, with a timeout, as on mobile phones.

(Update: here is a source tarball – improvements welcome. I’m now wondering how I can specify this as the default input method.)

I didn’t find any documentation about how to do this, but there are examples:

From these examples, I figured out the following, which I might try to get into the gtk-doc documentation later:

Functions that the shared library should export

The shared library must export:

  • im_module_init()
  • im_module_exit()
  • im_module_list()
  • im_module_create()

Updating gtk.immodules

The input modules must be listed in the /etc/gtk-2.0/gtk.immodules file, which is a cache of input modules information. Your Makefile should generate a new gtk.immodules file, using gtk-query-immodules-2.0, then install it.

Implementing a GtkIMContext

You must implement a GtkIMContext, an instance of which will be returned by your im_module_create() function.

Though most GObjects would have a *_get_type() function that calls g_type_register_static(), input modules need a *_register_type() function that takes a GTypeModule, which it provides to g_type_module_register_type(). This *_register_type() function should be called from your im_module_init() function. This means:

  • You can’t use the G_DEFINE_TYPE macro.
  • You can implement a *_get_type() function that just gets the GType if it has been registered by your *_register_type() function, but which fails otherwise. This seems to make if difficult (maybe impossible) to implement a GtkIMContext which is both directly usable and which may be a base class for other GtkIMContext implementations.

For “table-based” input methods, you can just derive from GtkIMContextSimple and call gtk_im_context_simple_add_table() with your table array, which specifies which sequences of characters can be used to specify an actual output character. When entering one of these intermediate characters an underline indicates that the user is in compose mode. Pressing the right arrow, or pressing a non-relevant character, accepts the displayed character. For instance, see the Tigrigna-Eritrean input method from GTK+, or the Esperanto input method in gtk-im-extra.

GtkIMContext has several virtual functions that you may want to override. These are not documented, but you can at least see their signatures in the GtkIMContext header file. The most important ones seem to be:

  • filter_keypress: This can emit the (undocumented) “commit” signal, sending a string when composing has finished, resulting in a character, and it can emit the “preedit_changed” signal, which will cause your get_preedit_string vfunc to be called.
  • get_preedit_string: This returns a string to be shown to the user, to indicate what character would be used if it were accepted. This can use Pango to show the pre-edit UI, such as underlined text to indicate a possible character.

GNOME bug-buddy magic

Today I noticed that GNOME’s bug-buddy crash reporter has become almost self-aware. The SoundJuicer audio ripper crashed (first time for me, and not reproducable). Bug-buddy reported the bug (without asking me for any sendmail nonsense), then showed me a clickable URL link to my bug. The magic:

  • It was actually not a new bug. It was an old bug, which bug-buddy/bugzilla had automatically identified as a duplicate, probably by comparing the stack trace. The comments in the bug report mentioned that it was actually caused by musicbrainz, but that musicbrainz fixed it in a later version. I added a comment about distros needing to update their musicbrainz version for the next person who finds themselves there.
  • A few seconds later, bugzilla sent me an email saying

    You recently submitted a bug report to GNOME Bugzilla using Bug-Buddy.

    Thank you for reporting this bug. This is actually caused by musicbrainz (used
    by sound-juicer). See for more information:
    http://bugs.musicbrainz.org/ticket/2262

That’s amazing.

Self-hosting Glom

Glom 1.3.5 has experimental support for self-hosting of its databases, so you should never again need to configure PosgreSQL.

It does this by starting its own PostgreSQL instance, supplying its own PostgreSQL configuration and data files, and connecting to it. Those files are stored in one directory, though I’d like to improve that directory structure. This vastly improves the user experience, so I expect this to bring a lot more users once I’ve shaken out the new bugs.

This should satisfy most people who were demanding support for SQLite instead of PostgreSQL. Unlike SQLite, this still allows you to share your database across the network with multiple users. Support for non-PostgreSQL external database servers is still possible, but that work is really not my priority.

I really do need to combine some of the dialogs. At the moment you see several dialogs, one after the other, to save a new file, choose a database name (and choose self-hosting or external hosting), then to connect or provide initial connection details.

glom_new_database_with_self_hosting

Glom: Showing related related records

The feature I mentioned in “SQL: joins and duplicates” is now implemented in Glom 1.3.3. It’s just a matter of choosing relationships from a tree rather than just a list, though it’s only 2 levels deep for now to keep it simple.

So if there are, for instance, Invoices with related Invoice Lines records, which refer to Products, then you could look at a Product details screen and see all the Invoices that use the Product (via their Invoice Lines records). If I added a 3rd level of child relationships then you could even see all the Customers (used by the Invoice table) that had ever been invoiced for the product.

Here’s a screenshot of the UI for the Licenses, Packages, Package Scans example:

glom_screenshot_related_related

The UI isn’t perfect. I don’t like that it’s enabled via a checkbox but I think the tree would be confusing if it was default. Trees in GtkComboBox widgets are also rendered as these confusing menus, but it could be replaced by a popup GtkTreeView some day. But I feel very satisfied that I’ve made it easy to do something that’s usually difficult, with only minor UI changes. Many thanks to Jerry Haltom for showing me how this could be done.

The SQL that’s generated is much the same as for regular related records (SELECT related_table.field1, related_table.field2 FROM related_table WHERE related_table_field3 = 123), but with an extra JOIN … AS … ON clause to link to the intermediate table, a slightly changed WHERE clause (to refer to that intermediate join), and a GROUP BY on the related table’s primary key to ensure that we get only one row for each related record. A sub-select query might be more efficient, but this allows me to reuse the existing code, and lets the user think in terms of the target related table rather than an intermediate one.

So using Glom’s –debug_sql now shows yet more complex SQL that you wouldn’t want to write yourself.

SQL: joins and duplicates.

Here’s a little SQL problem for the lazy web. It’s something that I’m trying to implement in Glom for the Repository Analyzer:

Let’s say we have these tables:

Packages:

package_name package_description
something something description
somethingelse something else description
somethingmore something more description

and Package Scans:

package_name version license_id
something 0.1 43
something 0.2 43
something 0.3 44
somethingelse 1.5 43
somethingmore 0.9 40

Now, I want to get the package.package_description for all packages that appear in package_scans with license_id 43, which would look like this:

‘something description’
‘something else description’

The best I can do so far is a SELECT on package_scans, doing a LEFT OUTER JOIN:

SELECT “relationship_package”.”package_description” FROM “package_scans” LEFT OUTER JOIN “packages” AS “relationship_package” ON (“package_scans”.”package_name” = “relationship_package”.”package_name”) WHERE “package_scans”.”license_id” = 43;

which gives me duplicates, like so:

‘something description’
‘something description’
‘something else description’

If possible I’d like to do this without GROUP BY. I feel there must be a simpler way to say “give me a row for each record in packages for which the (indirect) relationship is true”. If the main FROM table could somehow be packages, instead of package_scans, then the LEFT OUTER JOIN would cause me to have only one row for each relevant packages record. In general, Glom never gives you repeat rows because that’s confusing.

If I can figure out what SQL should be generated, I could imagine that I might get that result in Glom by defining a relationship in terms of a doubly-related field. So the user could say “Show me records from the packages_with_package_scan_license_id” relationship. That relationship would be defined as something like

records from packages where licenses.license_id == packages::package_scans::license_id

But maybe a GROUP BY option really is the clearest.

Update: I feel like the sub-select idea might be what I want, if I can figure the syntax out. I like the idea of showing records from a relationship that is itself defined by a link between a value and a field in another related set of records.