Index: libedataserverui/e-source-option-menu.h
===================================================================
--- libedataserverui/e-source-option-menu.h	(revision 7978)
+++ libedataserverui/e-source-option-menu.h	(working copy)
@@ -25,7 +25,7 @@
 
 #include "libedataserver/e-source-list.h"
 
-#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkcombobox.h>
 
 #define E_TYPE_SOURCE_OPTION_MENU			(e_source_option_menu_get_type ())
 #define E_SOURCE_OPTION_MENU(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE_OPTION_MENU, ESourceOptionMenu))
@@ -39,13 +39,13 @@
 typedef struct _ESourceOptionMenuClass   ESourceOptionMenuClass;
 
 struct _ESourceOptionMenu {
-	GtkOptionMenu parent;
+	GtkComboBox parent;
 
 	ESourceOptionMenuPrivate *priv;
 };
 
 struct _ESourceOptionMenuClass {
-	GtkOptionMenuClass parent_class;
+	GtkComboBoxClass parent_class;
 
 	void (* source_selected) (ESourceOptionMenu *menu,
 				  ESource *selected_source);
Index: libedataserverui/ChangeLog
===================================================================
--- libedataserverui/ChangeLog	(revision 7978)
+++ libedataserverui/ChangeLog	(working copy)
@@ -1,3 +1,11 @@
+2007-08-21  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #460649
+
+	* e-source-option-menu.h:
+	* e-source-option-menu.c:
+	Rewritten to subclass gtk_combo_box instead of gtk_option_menu.
+
 2007-08-19  Kevin Piche  <kpiche@gmail.com>
 
 	** Fix for bug #464569
Index: libedataserverui/e-source-option-menu.c
===================================================================
--- libedataserverui/e-source-option-menu.c	(revision 7978)
+++ libedataserverui/e-source-option-menu.c	(working copy)
@@ -24,16 +24,262 @@
 #include <config.h>
 #endif
 
-#include <gtk/gtkmenu.h>
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtkprivate.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderer.h>
+#include <gtk/gtkcellrenderertext.h>
 
 #include "e-source-option-menu.h"
 
-/* We set data on each menu item specifying the corresponding ESource using this key.  */
-#define MENU_ITEM_SOURCE_DATA_ID	"ESourceOptionMenu:Source"
+/* ------------------------------------------------------------------------- */
+/* ------------------------ begin of GdkColor cell renderer ---------------- */
+/* ------------------------------------------------------------------------- */
 
+#define GTK_TYPE_CELL_RENDERER_COLOR			(gtk_cell_renderer_color_get_type ())
+#define GTK_CELL_RENDERER_COLOR(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_RENDERER_COLOR, GtkCellRendererColor))
+#define GTK_CELL_RENDERER_COLOR_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_COLOR, GtkCellRendererColorClass))
+#define GTK_IS_CELL_RENDERER_COLOR(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_RENDERER_COLOR))
+#define GTK_IS_CELL_RENDERER_COLOR_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_RENDERER_COLOR))
+#define GTK_CELL_RENDERER_COLOR_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER_COLOR, GtkCellRendererColorClass))
 
+typedef struct _GtkCellRendererColor GtkCellRendererColor;
+typedef struct _GtkCellRendererColorClass GtkCellRendererColorClass;
+
+struct _GtkCellRendererColor
+{
+	GtkCellRenderer parent;
+
+	/*< private >*/
+	gboolean have_color;
+	GdkColor color;
+};
+
+struct _GtkCellRendererColorClass
+{
+	GtkCellRendererClass parent_class;
+
+	/* Padding for future expansion */
+	void (*_gtk_reserved1) (void);
+	void (*_gtk_reserved2) (void);
+	void (*_gtk_reserved3) (void);
+	void (*_gtk_reserved4) (void);
+};
+
+GType            gtk_cell_renderer_color_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *gtk_cell_renderer_color_new      (void);
+
+static void gtk_cell_renderer_color_get_property  (GObject                    *object,
+						    guint                       param_id,
+						    GValue                     *value,
+						    GParamSpec                 *pspec);
+static void gtk_cell_renderer_color_set_property  (GObject                    *object,
+						    guint                       param_id,
+						    const GValue               *value,
+						    GParamSpec                 *pspec);
+static void gtk_cell_renderer_color_finalize   (GObject                    *object);
+static void gtk_cell_renderer_color_get_size   (GtkCellRenderer            *cell,
+						 GtkWidget                  *widget,
+						 GdkRectangle               *rectangle,
+						 gint                       *x_offset,
+						 gint                       *y_offset,
+						 gint                       *width,
+						 gint                       *height);
+static void gtk_cell_renderer_color_render     (GtkCellRenderer            *cell,
+						 GdkDrawable                *window,
+						 GtkWidget                  *widget,
+						 GdkRectangle               *background_area,
+						 GdkRectangle               *cell_area,
+						 GdkRectangle               *expose_area,
+						 GtkCellRendererState        flags);
+
+
+enum {
+	PROP_ZERO,
+	PROP_COLOR
+};
+
+G_DEFINE_TYPE (GtkCellRendererColor, gtk_cell_renderer_color, GTK_TYPE_CELL_RENDERER)
+
+static void
+gtk_cell_renderer_color_init (GtkCellRendererColor *cellcolor)
+{
+	((GtkCellRenderer*)cellcolor)->xpad = 4;
+	cellcolor->have_color = FALSE;
+}
+
+static void
+gtk_cell_renderer_color_class_init (GtkCellRendererColorClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+
+	object_class->finalize = gtk_cell_renderer_color_finalize;
+
+	object_class->get_property = gtk_cell_renderer_color_get_property;
+	object_class->set_property = gtk_cell_renderer_color_set_property;
+
+	cell_class->get_size = gtk_cell_renderer_color_get_size;
+	cell_class->render = gtk_cell_renderer_color_render;
+
+	g_object_class_install_property (object_class,
+				   PROP_COLOR,
+				   g_param_spec_boxed ("color",
+						      ("Color Info"),
+						      ("The color to render"),
+						      GDK_TYPE_COLOR,
+						      GTK_PARAM_READWRITE));
+}
+
+static void
+gtk_cell_renderer_color_finalize (GObject *object)
+{
+	(* G_OBJECT_CLASS (gtk_cell_renderer_color_parent_class)->finalize) (object);
+}
+
+static void
+gtk_cell_renderer_color_get_property (GObject        *object,
+				      guint           param_id,
+				      GValue         *value,
+				      GParamSpec     *pspec)
+{
+	GtkCellRendererColor *cellcolor = GTK_CELL_RENDERER_COLOR (object);
+  
+	switch (param_id) {
+	case PROP_COLOR: {
+		GdkColor color = cellcolor->color;
+
+		if (!cellcolor->have_color) {
+			color.pixel = 0;
+			color.red = 0;
+			color.green = 0;
+			color.blue = 0;
+		}
+
+		g_value_set_boxed (value, &color);
+	} break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+	break;
+    }
+}
+
+
+static void
+gtk_cell_renderer_color_set_property (GObject      *object,
+				       guint         param_id,
+				       const GValue *value,
+				       GParamSpec   *pspec)
+{
+	GtkCellRendererColor *cellcolor = GTK_CELL_RENDERER_COLOR (object);
+  
+	switch (param_id) {
+	case PROP_COLOR: {
+		GdkColor *color = g_value_get_boxed (value);
+
+		cellcolor->have_color = color != NULL;
+		if (color)
+			cellcolor->color = *color;
+	} break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+	break;
+    }
+}
+
+GtkCellRenderer *
+gtk_cell_renderer_color_new (void)
+{
+	return g_object_new (GTK_TYPE_CELL_RENDERER_COLOR, NULL);
+}
+
+static void
+gtk_cell_renderer_color_get_size (GtkCellRenderer *cell,
+				  GtkWidget       *widget,
+				  GdkRectangle    *cell_area,
+				  gint            *x_offset,
+				  gint            *y_offset,
+				  gint            *width,
+				  gint            *height)
+{
+	gint color_width  = 16;
+	gint color_height = 16;
+	gint calc_width;
+	gint calc_height;
+
+	calc_width  = (gint) cell->xpad * 2 + color_width;
+	calc_height = (gint) cell->ypad * 2 + color_height;
+  
+	if (cell_area && color_width > 0 && color_height > 0) {
+		if (x_offset) {
+			*x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
+					(1.0 - cell->xalign) : cell->xalign) * 
+					(cell_area->width - calc_width));
+			*x_offset = MAX (*x_offset, 0);
+		}
+
+		if (y_offset) {
+			*y_offset = (cell->yalign *
+				(cell_area->height - calc_height));
+			*y_offset = MAX (*y_offset, 0);
+		}
+	} else {
+		if (x_offset) *x_offset = 0;
+		if (y_offset) *y_offset = 0;
+	}
+
+	if (width)
+		*width = calc_width;
+
+	if (height)
+		*height = calc_height;
+}
+
+static void
+gtk_cell_renderer_color_render (GtkCellRenderer      *cell,
+				GdkWindow            *window,
+				GtkWidget            *widget,
+				GdkRectangle         *background_area,
+				GdkRectangle         *cell_area,
+				GdkRectangle         *expose_area,
+				GtkCellRendererState  flags)
+
+{
+	GtkCellRendererColor *cellcolor = (GtkCellRendererColor *) cell;
+	GdkRectangle pix_rect;
+	GdkRectangle draw_rect;
+	GdkGC *gc;
+
+	if (!cellcolor->have_color)
+		return;
+
+	gtk_cell_renderer_color_get_size (cell, widget, cell_area,
+					  &pix_rect.x,
+					  &pix_rect.y,
+					  &pix_rect.width,
+					  &pix_rect.height);
+
+	pix_rect.x += cell_area->x + cell->xpad;
+	pix_rect.y += cell_area->y + cell->ypad;
+	pix_rect.width  -= cell->xpad * 2;
+	pix_rect.height -= cell->ypad * 2;
+
+	if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) ||
+	    !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect))
+		return;
+
+	gdk_colormap_alloc_color (gdk_colormap_get_system(), &cellcolor->color, FALSE, TRUE);
+	
+	gc = gdk_gc_new (window);
+	gdk_gc_set_foreground (gc, &cellcolor->color);
+	gdk_draw_rectangle (window, gc, TRUE, pix_rect.x, pix_rect.y, draw_rect.width, draw_rect.height);
+	g_object_unref (gc);
+}
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------  end of GdkColor cell renderer  ---------------- */
+/* ------------------------------------------------------------------------- */
+
 struct _ESourceOptionMenuPrivate {
 	ESourceList *source_list;
 
@@ -54,24 +300,31 @@
 
 static guint signals[NUM_SIGNALS] = { 0 };
 
-G_DEFINE_TYPE (ESourceOptionMenu, e_source_option_menu, GTK_TYPE_OPTION_MENU)
+G_DEFINE_TYPE (ESourceOptionMenu, e_source_option_menu, GTK_TYPE_COMBO_BOX)
 
 /* Selecting a source.  */
-static void
-select_source_foreach_menu_item (GtkWidget *menu_item,
-				 ForeachMenuItemData *data)
+static gboolean
+select_source_foreach_item (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer pdata)
 {
-	ESource *source = gtk_object_get_data (GTK_OBJECT (menu_item), MENU_ITEM_SOURCE_DATA_ID);
+	ForeachMenuItemData *data = (ForeachMenuItemData *)pdata;
+	ESource *source = NULL;
+	gpointer *p = NULL;
 
 	if (data->found_source)
-		return;
+		return FALSE;
 
+	gtk_tree_model_get (model, iter, 0, &p, -1);
+
+	if (p)
+		source = (ESource *)p;
+
 	if (source && e_source_equal (source, data->source)) {
 		data->found_source = source;
-		gtk_option_menu_set_history (GTK_OPTION_MENU (data->option_menu), data->i);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (data->option_menu), data->i);
 	}
 
 	data->i ++;
+	return FALSE;
 }
 
 static void
@@ -84,11 +337,17 @@
 	foreach_data->option_menu = menu;
 	foreach_data->source = source;
 
-	gtk_container_foreach (GTK_CONTAINER (GTK_OPTION_MENU (menu)->menu),
-			       (GtkCallback) select_source_foreach_menu_item, foreach_data);
+	gtk_tree_model_foreach (gtk_combo_box_get_model (GTK_COMBO_BOX (menu)),
+			       select_source_foreach_item, foreach_data);
 
 	if (foreach_data->found_source) {
-		menu->priv->selected_source = foreach_data->found_source;
+		if (menu->priv->selected_source != menu->priv->selected_source) {
+			if (menu->priv->selected_source)
+				g_object_unref (menu->priv->selected_source);
+			menu->priv->selected_source = foreach_data->found_source;
+			if (menu->priv->selected_source)
+				g_object_ref (menu->priv->selected_source);
+		}
 		g_signal_emit (menu, signals[SOURCE_SELECTED], 0, foreach_data->found_source);
 	}
 
@@ -99,22 +358,57 @@
 /* Menu callback.  */
 
 static void
-menu_item_activate_callback (GtkMenuItem *menu_item,
-			     ESourceOptionMenu *option_menu)
+combo_box_changed_cb (GtkComboBox *combobox, gpointer *data)
 {
-	ESource *source = gtk_object_get_data (GTK_OBJECT (menu_item), MENU_ITEM_SOURCE_DATA_ID);
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	ESource *source = NULL;
 
+	model = gtk_combo_box_get_model (combobox);
+
+	if (model && gtk_combo_box_get_active_iter (combobox, &iter)) {
+		gpointer *p = NULL;
+
+		gtk_tree_model_get (model, &iter, 0, &p, -1);
+
+		source = (ESource*)p;
+	}
+
 	if (source != NULL)
-		select_source (option_menu, source);
+		select_source (E_SOURCE_OPTION_MENU (combobox), source);
 }
 
+/* Functions to keep the combo box in sync with the ESourceList.  */
 
-/* Functions to keep the menu in sync with the ESourceList.  */
+static gboolean
+unref_sources (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+{
+	gpointer *p = NULL;
 
+	gtk_tree_model_get (model, iter, 0, &p, -1);
+
+	if (p)
+		g_object_unref ((ESource *)p);
+
+	return FALSE;
+}
+
 static void
+free_combo_data (ESourceOptionMenu *option_menu)
+{
+	GtkTreeModel *ldata;
+
+	ldata = gtk_combo_box_get_model (GTK_COMBO_BOX (option_menu));
+
+	if (ldata)
+		gtk_tree_model_foreach (ldata, unref_sources, NULL);
+}
+
+static void
 populate (ESourceOptionMenu *option_menu)
 {
-	GtkWidget *menu = gtk_menu_new ();
+	GtkTreeIter lp;
+	GtkTreeModel *ldata;
 	GSList *groups = e_source_list_peek_groups (option_menu->priv->source_list);
 	GSList *p;
 	ESource *first_source = NULL;
@@ -122,51 +416,55 @@
 	int selected_item = -1;
 	int i;
 
+	g_signal_handlers_disconnect_by_func (G_OBJECT (option_menu), G_CALLBACK (combo_box_changed_cb), NULL);
+
+	free_combo_data (option_menu);
+
+	ldata = GTK_TREE_MODEL(
+		gtk_list_store_new (4,
+			G_TYPE_POINTER, /* pointer to source itself - NULL for groups, need free for sources */
+			G_TYPE_BOOLEAN, /* sensitivity, FALSE for groups, TRUE for sources */
+			GDK_TYPE_COLOR, /* color for the item, NULL for groups, any for sources */
+			G_TYPE_STRING   /* item title */
+		));
+
 	i = 0;
 	for (p = groups; p != NULL; p = p->next) {
 		ESourceGroup *group = E_SOURCE_GROUP (p->data);
-		GtkWidget *item1 = gtk_menu_item_new_with_label (e_source_group_peek_name (group));
 		GSList *q;
 
-		gtk_widget_set_sensitive (item1, FALSE);
-		gtk_widget_show (item1);
-		gtk_menu_append (GTK_MENU (menu), item1);
-
+		gtk_list_store_append (GTK_LIST_STORE (ldata), &lp);
+		gtk_list_store_set (GTK_LIST_STORE (ldata), &lp,
+					0, NULL,
+					1, FALSE,
+					2, NULL,
+					3, e_source_group_peek_name (group),
+					-1);
+		
 		i ++;
 
 		for (q = e_source_group_peek_sources (group); q != NULL; q = q->next) {
 			ESource *source = E_SOURCE (q->data);
 			char *label = g_strconcat ("    ", e_source_peek_name (source), NULL);
 			const char *colour = e_source_peek_color_spec (source);
-			GtkWidget *item2 = gtk_image_menu_item_new_with_label (label);
-			g_free (label);
+			GdkColor c;
 
-			if (colour) {
-				GdkPixmap *pixmap;
-				GdkColor c;
-				GdkGC *gc;
+			g_object_ref (source);
 
-				pixmap = gdk_pixmap_new (gdk_get_default_root_window (), 16, 16, -1);
+			if (colour)
 				gdk_color_parse (colour, &c);
-				gdk_colormap_alloc_color (gdk_colormap_get_system(), &c, FALSE, TRUE);
 
-				gc = gdk_gc_new (gdk_get_default_root_window ());
-				gdk_gc_set_foreground (gc, &c);
-				gdk_draw_rectangle (pixmap, gc, TRUE, 0, 0, 16, 16);
-				g_object_unref (gc);
+			gtk_list_store_append (GTK_LIST_STORE (ldata), &lp);
+			gtk_list_store_set (GTK_LIST_STORE (ldata), &lp,
+					0, source,
+					1, TRUE,
+					2, colour ? &c : NULL,
+					3, label,
+					-1);
 
-				gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item2), gtk_image_new_from_pixmap (pixmap, NULL));
-			}
+			g_free (label);
 
-			gtk_object_set_data_full (GTK_OBJECT (item2), MENU_ITEM_SOURCE_DATA_ID, source,
-						  (GtkDestroyNotify) g_object_unref);
-			g_object_ref (source);
 
-			g_signal_connect (item2, "activate", G_CALLBACK (menu_item_activate_callback), option_menu);
-
-			gtk_widget_show (item2);
-			gtk_menu_append (GTK_MENU (menu), item2);
-
 			if (first_source_item == -1) {
 				first_source_item = i;
 				first_source = source;
@@ -179,10 +477,10 @@
 		}
 	}
 
-	gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (option_menu), ldata);
 
 	if (selected_item != -1) {
-		gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), selected_item);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (option_menu), selected_item);
 	} else {
 		if (option_menu->priv->selected_source != NULL)
 			g_object_unref (option_menu->priv->selected_source);
@@ -190,8 +488,12 @@
 		if (option_menu->priv->selected_source != NULL)
 			g_object_ref (option_menu->priv->selected_source);
 
-		gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), first_source_item);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (option_menu), first_source_item);
 	}
+
+	g_signal_connect (G_OBJECT (option_menu), "changed", G_CALLBACK (combo_box_changed_cb), NULL);
+
+	g_object_unref (G_OBJECT (ldata));
 }
 
 
@@ -227,6 +529,8 @@
 		priv->selected_source = NULL;
 	}
 
+	free_combo_data (E_SOURCE_OPTION_MENU (object));
+
 	(* G_OBJECT_CLASS (e_source_option_menu_parent_class)->dispose) (object);
 }
 
@@ -266,10 +570,19 @@
 e_source_option_menu_init (ESourceOptionMenu *source_option_menu)
 {
 	ESourceOptionMenuPrivate *priv;
+	GtkCellRenderer *r;
 
 	priv = g_new0 (ESourceOptionMenuPrivate, 1);
 
 	source_option_menu->priv = priv;
+	
+	r = gtk_cell_renderer_color_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (source_option_menu), r, FALSE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (source_option_menu), r, "color", 2, "sensitive", 1, NULL);
+
+	r = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (source_option_menu), r, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (source_option_menu), r, "text", 3, "sensitive", 1, NULL);
 }
 
 
