Migrating from SexyIconEntry to GtkEntry

GTK+ 2.16 supports showing icons inside a GtkEntry, similar to SexyIconEntry. Porting from SexyIconEntry to GtkEntry is relatively straightforward. The main difference between the two APIs is that SexyIconEntry uses GtkImage widgets in a somewhat awkward way as storage vehicles for icons, while GtkEntry allows to specify icons via pixbufs, stock ids, icon names or GIcons. So, if your code uses e.g.:

1
2
image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
sexy_icon_entry_set_icon (entry, SEXY_ICON_ENTRY_PRIMARY, image);

you can get rid of the image, and directly write:

1
gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_NEW);

The signals SexyIconEntry::icon-pressed and SexyIconEntry::icon-released have been renamed to "icon-press" and "icon-release" to avoid problems due to signal name clashes. Also, the signature of the signals has changed from

1
2
3
void (*icon_pressed) (SexyIconEntry         *entry, 
                      SexyIconEntryPosition  icon_pos,
                      int                    button)

to

1
2
3
void (*icon_press) (GtkEntry              *entry, 
                    GtkEntryIconPosition  icon_pos,
                    GdkEventButton       *event)

The new signature has the advantage that the signal handler can use the timestamp of the event, e.g. for passing it to gtk_menu_popup(). When adapting an existing signal handler to the new signature, you should note that the button number is easily available as event->button, as shown in the following example:

1
2
3
4
5
6
7
8
9
10
11
12
static void
icon_pressed_cb (SexyIconEntry         *entry,
                 SexyIconEntryPosition  position,
                 int                    button,
                 gpointer               data)
{
  GtkMenu *menu = data;

  if (position == SEXY_ICON_ENTRY_PRIMARY)
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
                    button, GDK_CURRENT_TIME);
}

can be ported as:

1
2
3
4
5
6
7
8
9
10
11
12
static void
icon_press_cb (GtkEntry             *entry,
               GtkEntryIconPosition  position,
               GdkEventButton       *event,
               gpointer              data)
{
  GtkMenu *menu = data;

  if (position == GTK_ENTRY_ICON_PRIMARY)
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
                    event->button, event->time);
}

Another difference is that SexyIconEntry offers manual control of the icon prelighting, via sexy_icon_entry_set_icon_highlight(). GtkEntry prelights automatically when appropriate, depending on whether the icon is activatable and sensitive. You should make sure that your icons are properly marked as activatable or nonactivatable and sensitive or insensitive:

GtkEntry has no direct equivalent of the special-purpose function sexy_icon_entry_add_clear_button(). If you need this functionality, the following code works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static void
icon_pressed_cb (GtkEntry       *entry,
                 gint            position,
                 GdkEventButton *event,
                 gpointer        data)
{
  if (position == GTK_ENTRY_ICON_SECONDARY)
    gtk_entry_set_text (entry, "");
}

static void
text_changed_cb (GtkEntry   *entry,
                 GParamSpec *pspec,
                 GtkWidget  *button)
{
  gboolean has_text;

  has_text = gtk_entry_get_text_length (entry) > 0;
  gtk_entry_set_icon_sensitive (entry,
                                GTK_ENTRY_ICON_SECONDARY,
                                has_text);
}


  /* ... */
 
  /* Set up the clear icon */
  gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
                                 GTK_ENTRY_ICON_SECONDARY,
                                 GTK_STOCK_CLEAR);
  g_signal_connect (entry, "icon-press",
                    G_CALLBACK (icon_pressed_cb), NULL);
  g_signal_connect (entry, "notify::text",
                    G_CALLBACK (text_changed_cb), find_button);
 
  /* ... */