gnome-keyring with Python

The documentation on gnome-keyring I discovered helped me to access it successfully with Python. I’ve written a small module that fetches and stores a username and a password for some server.

Some notes:

  • The attributes are freeform, but there a some common attributes for network hosts. These are: “user”, “domain”, “server”, “object”, “protocol”, “authtype”, and “port”. Actually there is a convenience API for network hosts.
  • libgnome-keyring requires that the application is correctly set using g_set_application_name. Unfortunately the Python module gnomekeyring does not do that for us and pygtk does not provide a function to set the application name. Therefore you need to include the module gtk to make it work. (Filed as bug 460515.)Update: g_set_application_name was added to pygtk in the 2.13 development version.
  • Python’s find_network_password_sync function does not allow None to be passed as arguments. The C API allows NULL to be passed here. This means that this function is basically unusable in Python, since you never want to provide all values. (Filed as bug 460518.)

Documentation for libgnome-keyring

I was trying to find documentation for libgnome-keyring for little project I am writing, which accesses a password-protected web service. Unfortunately there is no real documentation for it. No API documentation (well, there are a total of two functions documented), no tutorial. Finally I found this document in GNOME’s Subversion repository. Better then nothing, but why isn’t this part of the API documentation?

Filed as bug 460475.

Update: It seems that libgnome-keyring has gained documentation a few weeks ago, so far only found in Subversion. Kudos to the maintainers!

Selection in GtkTextBuffer

I’ve recently played around with GtkTextBuffer. It’s a rather nice text editing widget (or rather widget part). Unfortunately it misses one functionality, which is also missing from GtkEditable derived widgets: A signal for selection changes. There are two workarounds:

  1. You can setup a notification on the “has-selection” property like this:
    buffer.connect("notify", on_buffer_notify)
    
    def on_buffer_notify(buffer, prop):
        if prop.name == "has-selection":
            if buffer.get_has_selection():
                ...
            else:
                ...
    

    This method only works if you are interested in whether there is a selection or not, not if you are interested in any selection changes. Also, this method works only for GtkTextBuffers, not for GtkEditables.

  2. Tomboy uses a timeout to check the selection status:
    namespace Tomboy
    {
    	public class NoteWindow : ForcedPresentWindow 
    	{
                    ...
    		public NoteWindow (Note note) : 
    			base (note.Title) 
    		{
                            ...
    			// Sensitize the Link toolbar button on text selection
    			mark_set_timeout = new InterruptableTimeout();
    			mark_set_timeout.Timeout  = UpdateLinkButtonSensitivity;
                            ...
                    }
    
                    ...
    
    		void UpdateLinkButtonSensitivity (object sender, EventArgs args)
    		{
    			link_button.Sensitive = (note.Buffer.Selection != null);
    		}
    
                    ...
            }
    }
    

    This method works, but seems a bit complicated, when a simple signal should do the trick.

Filed as bug #448261.

Porting Tomboy from C# to C++

Hubert Figuiere writes about porting Tomboy from C# to C++. I tried to leave a comment in his blog, but something doesn’t work, so here is my comment:

Porting Tomboy from C# to C++ seems like a step back to me. C# is a higher level language than C++ and is much easier to write good and clean code with than C++. C++ rises the maintenance burden.

Also, at the moment Tomboy’s code base is under heavy development with one WSOP project (Maria Soler Climent’s) and one Summer of Code project (mine) going on. The code base is changing rapidly, so it seems this is a bad time to do such porting.

Google Summer of Code and Networked Tomboy

My Google Summer of Code application, called Networked Tomboy was accepted. Just to quote myself:

Tomboy is a note-taking application for the GNOME desktop. As such it is evolving as a replacement for the traditional ‘sticky notes’ applet and offers several advantages, including easy formatting and wiki-style links. But currently Tomboy notes are limited to the desktop. That means that users can’t easily transfer their notes between different desktops (e.g. their home and work computer or their desktop and laptop PC) or publish their notes for other users.

This project is supposed to solve this problem. Using an abstraction of Tomboy’s data storage format and system, an alternative system for storing notes in a central repository will be developed. This repository can then be accessed by Tomboy instances. Additionally a note publishing system will be developed. It will allow to publish selected notes either on a local network (using Zeroconf) or to web pages.

I’m rather happy to get the opportunity to hack on a program that I use myself and that missed functionality I need.

Python Bindings for librsvg

Background: I started to re-write the old GNOME Chess application in Python. GNOME Chess is still a Gtk+ 1.2 application and as its Debian maintainer I want a modern version in Debian. Of course the chess board should be drawn with Cairo and the chess pieces were supposed to be SVG graphics. After a little research I noticed that the Debian package of pycairo did not enable SVG support. After I filed a bug report about this I found out that the cairo.svg module depends on the obsolete and not supported libsvg. Instead librsvg offers Cairo support and is the preferred solution. Only that there were no Python binding for librsvg.

So after fighting a whole day with pygtk, pyobject, and assorted tools, I am proud to present pyrsvg, Python bindings for librsvg. They are not really tested and probably need improvement. Please send any bugs or suggestions for improvement to me. In the long term I want this to become part gnome-python or gnome-python-extras.

Update: The bindings are now part of python-gnome-desktop (since version 2.15.1/2.16).

Activity Monitor

The Problem

Several applications need to know about user activity. This includes screen savers, RSI prevention tools like Workrave, and IM programs (for automatic away message). Currently each program has to implement activity tracking itself. This means that there is no unified configuration, but also that programs like movie players have to resort to hacks to prevent screen savers from activating. It’s also not possible for users to trigger a generic “away” event that causes the screen to be locked, the IM program to set the away status etc. pp.

A unified system would have the following requirements:

  • There needs to be an idle time, after which screensavers could active. for example.
  • There needs to an away time, after which the user is considered to be AFK. This could trigger screen locking, and IM status changes.
  • Programs must have the ability to signal user activity, so that screen savers won’t activate while watching a movie.
  • Programs must have the ability to temporarily shut the activity listening off. This is needed by xlock-like programs, where the program itself is the only authority to reenable user activity.

The Proposal

A central daemon (yay, another daemon!) communicates with other program via d-bus. This daemon listens for user activity, i.e. mouse movement and key presses. Basically there are four user states:

busy
The user is currently using the computer.
lazy
The user hasn’t used the computer for a set amount of time.
away
The user is away from the keyboard.
locked
Like “away”, only that wakeup events are ignored until the
mode is manually changed.

In general the possible mode changes are busy → lazy, busy → away, busy → locked, lazy → busy, lazy → away, lazy → locked, away → busy, away → locked, and locked → busy.

The following messages are sent by the daemon:

idle
This specifies are reason for the status change as parameter,
for example “timeout:600”, meaning that there was no user activity
for 600 seconds. This message may be repeated with reason “repeat”.
away
This message is sent when the user is away. It also includes
the reason, for example “timeout:1200” or “userrequest”. It may
also be repeated.
busy
This message is sent when the user returns to work. It has
an optional reason parameter, and may be repeated.

The daemon understands the following messages:

activity-ping
This is sent by some applications, like movie viewers every
few seconds to signal that the user is busy, although there is
no user activity.
gone-away
This is sent by applications when the user explicitly toggles
the away status, for example by selecting “lock screen” from the
system menu.
locked
Similar to gone-away, only that auto-wakeup is disabled. The only
entity to reenable listing to events is the sender of the locked
message. Therefore a detail string must be passed. This is used by
xlock-like applications to prevent applications from changing the
“away” status, just because someone moved the mouse.
unlocked
The corresponding unlock signal to the locked message. Must use
the same detail string.

Use Cases

Screen Saver
When the screen saver receives the away signal, it
turns on the screen saving (if it’s not already running). If it
receives the busy signal, it turns of the screen saver. It ignores
the other signals.
Away Button
When a user uses a potential away button in the system menu,
the menu sends the “gone-away” message to the daemon.
Screen Lock
When a user uses the “Lock Screen” button in the system
menu, the menu sends the “locked” signal to the daemon. It starts
the screen saver and listens to user input. When the correct
password has been entered, it sends the “unlocked” signal and
ends the screen saver mode.
Screen Saver with Locking
When the screen saver receives the away signal, it starts
screen saving, and sends the “locked” signal to the daemon. When
there is user input and the correct password is entered, it sends
the “unlocked” signal.
Instant Messengers
When the IM program receives the “away” signal, it turns
on the auto-responser and possibly the away method. The
auto-responder message may be modified according to the reason
detail parameter. When the IM program receives the busy signal,
it turns auto-responding and away status off.

To Do

  • The current proposal does not address RSI prevention programs like Workrave.
  • Security implications of the locked mode.
  • The disparity in screen saver responsibilities between normal screen saver activation and xlock activation.

ORBit 2.12.2-2

Uploaded a new version of ORBit2 that fixes bug #317352. It seems that at some point ORBit2 stopped building the API documentation by default, so it wasn’t included in liborbit2-dev anymore. Fixed that by providing the –enable-gtk-doc configure option. But then the API documentation is in a really bad state.

Also noticed that the linc-cleanup-sockets utility program hardcodes /tmp. Added a simple patch to GNOME bug #149394 that fixes this problem and commited it after I got Michael Meeks’ permission. This fix isn’t in the Debian package yet, though.

Thoughts on Notifications

There has been much talk lately about notifications in GNOME. Here are my thoughts. Basically there are different kinds of notifications:

  1. Notifications that need attention soon. This includes things like notebook battery running low, a phone call, an IM chat request, or an appointment. Generally these kinds of notifications need to draw attention to themselves without being distracting. While they need to taken care of, you normally want to finish the current sentence in the letter you are writing, read the current paragraph on the web page you are visiting, or quickly jot down your thoughts so they don’t get lost.Generally these kinds of notifications should only disappear when one of the following happens:
    • The user explicitly dismissed them (“I know that the battery is running low.”) or handles them (picks up the phone). Normally the notification itself should offer an easy way to do both.
    • The condition for the notification goes away. For example, a notebook running low on battery was reconnected to the power grid or a caller has hung up. The latter kind of notifications can then often be replaced by a type 2 notification.
    • The condition for the notification has become irrelevant. For example, a meeting is over according to the timetracking application, but the user has not taken action.

    In general such a notification should not go away automatically, since the situation has to be taken care off, even if the user is not currently at his computer. For example, a user has taken a coffee break and forgotten about a meeting. In the meantime the computer pops up a notification about it. If the notification would automatically disappear after a few minutes, the user might never notice that it had been there in the first place. If it stays, he will notice it and can still go to his meeting (better late than missing it completely).

    I think for this kind of notifications, popups are the best approach.

  2. Notifications about events that the user will want to check often, but that are not time critical. These kinds of notifications must be handled at some point, though. The poster child of this kind of notifications is of course e-mail. Such a notification should also provide the ability to quickly access the object the notification is about, for example open your inbox folder. Generally these kinds of notifications don’t go away, as long as the condition is true. If there is new e-mail, there is new e-mail.The best approach to these kinds of notifications is in my opinion icons in the panel, possibly using the notification applet. Icons are unobstrusive and can be checked quickly.
  3. Finally there is a group of things that aren’t notifications at all, but more information that the user wants to process from time to time. There is no harm if you miss a notification. Examples are news feeds or when somebody else added an appointment to your calendar. In the latter case, you would notice this appointment either when you are checking your calendar, or when the appointment is due.

The classification of many kinds of notifications are highly user-specific though. A user should be able to configure them, even though the fact that he is configuring the “notification level” can often be hidden. For example, a mail programm could have folder with differing flags: an “urgent” folder would generate notifications of the first kind, while a mailing list folder would generate generate no notifications. Normal e-mail generates type 2 notifications.

Finally, I will discuss some specific application and how they relate to the categories above, in my opinion:

e-mail
As described above, e-mail would normally generate notifications of type 2. A user can glance towards the notification area from time to time and if there is new mail, there will be a mail icon. This icon could even be varied to indicate which folder the mail is in, e.g. if it’s private or work related mail etc. Also, the may be urgent folder that generate notifications of type 1 or bulk mail folders that wouldn’t generate any notifications.
music player
In my opinion a music player should generate no notifications. It is quite obvious when a new track starts, because – well – the music changes. If you really want to know what the current song is, you can hover your pointer over the music player’s applet icon and it should show a popup with the current song title, artist, etc.
instant messaging
When someone is trying to contact you, a type 1 notification should be generated. You can choose whether to accept the talk request, or to reject it. (Though the latter does not necessarily mean that the other person needs to learns that you actively rejected their talk request.) If you just ignore the talk request, it would go away after 5 minutes and replaced by a type 2 notifcation that shows an icon in the notification bar. This indicated that there is an IM message waiting for you.

Joins and leaves are normally a type 3 notification, i.e. not something that usually appears on the screen. Of course a user should be able to flag some buddies specially, so that they would generate a type 2 notification if they join. This is useful if you are waiting for someone.

phone ringing
This works quite similar to the IM case. As long as someone is calling, there is type 1 notification that allows to to pick up the phone or to ignore the call. When the caller gives up, the type 1 notification is replaced by a type 2 notification. “XYZ tried to call you. They left the following message on the voice box: …”
news aggregators
New aggregators should usually generate type 3 notifications. Normally new news items are not immediatly interesting and people will just want to check the news from time to time. Of course it is possible that there are more important news that could get a type 2 or even a type 1 notification.
weather applet
This should usually not generate any notifications. It’s just something a user glances up to when they want to know the current temperature and conditions. There is an exception though: If there is a weather warning, the weather applet should show a type 1 notification that will go away when it’s either dismissed or the weather conditions changed again.
battery charge
This should generate a type 1 notification if the battery is running low. The notification will go away when it’s either dismissed or power is restored.
network stuff
Network switching This is also something that should happen automatically. Why bother the user with something that is mostly irrelevant? The same is true for connect/disconnect messages. As someone pointed out, just show an error when someone tries to initiate an action that requires a network connection and none is available.
new devices
No notification needed. Devices that were plugged in should just do the right thing: USB sticks should appear on the desktop, cameras should open an image storage program etc. pp.
appointments
Appointments should generate a type 1 notification. They need active dismissal and only go away automatically when the appointment is over. The latter case could also generate a “missed appointment” type 2 notification.