static void
on_selection_changed (G_GNUC_UNUSED GtkTreeSelection* selection,
                      gpointer data)
{
  CallHistoryViewGtk* self = NULL;
  History::Contact *contact = NULL;

  self = CALL_HISTORY_VIEW_GTK (data);

  /* Reset old data. This also ensures GIO actions are
   * properly removed before adding new ones.
   */
  self->priv->contact_menu.reset ();

  /* Set or reset ContactActor data */
  call_history_view_gtk_get_selected (self, &contact);

  if (contact != NULL) {
    self->priv->contact_menu = Ekiga::GActorMenuPtr (new Ekiga::GActorMenu (*contact));
    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0,
                   self->priv->contact_menu->get_model (boost::assign::list_of (self->priv->menu)));
  }
  else
    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0, NULL);
}
static void
on_selection_changed (G_GNUC_UNUSED GtkTreeSelection* selection,
		      gpointer data)
{
  CallHistoryViewGtk* self = NULL;

  self = CALL_HISTORY_VIEW_GTK (data);

  g_signal_emit (self, signals[SELECTION_CHANGED_SIGNAL], 0);
}
/* GObject stuff */
static void
call_history_view_gtk_finalize (GObject* obj)
{
  CallHistoryViewGtk* view = NULL;

  view = CALL_HISTORY_VIEW_GTK (obj);

  delete view->priv;

  G_OBJECT_CLASS (call_history_view_gtk_parent_class)->finalize (obj);
}
static void
on_map_cb (G_GNUC_UNUSED GtkWidget *widget,
           gpointer data)
{
  GtkTreeSelection *selection = NULL;

  g_return_if_fail (IS_CALL_HISTORY_VIEW_GTK (data));
  CallHistoryViewGtk *self = CALL_HISTORY_VIEW_GTK (data);

  selection = gtk_tree_view_get_selection (self->priv->tree);
  on_selection_changed (selection, self);
}
/* react to user clicks */
static gint
on_clicked (G_GNUC_UNUSED GtkWidget *tree,
            GdkEventButton *event,
            gpointer data)
{
  CallHistoryViewGtk *self = CALL_HISTORY_VIEW_GTK (data);

  // take into account only clicks and Enter keys
  if (event->type != GDK_BUTTON_PRESS && event->type != GDK_2BUTTON_PRESS && event->type != GDK_KEY_PRESS)
    return FALSE;
  if (event->type == GDK_KEY_PRESS && ((GdkEventKey*)event)->keyval != GDK_KEY_Return && ((GdkEventKey*)event)->keyval != GDK_KEY_KP_Enter)
    return FALSE;

  if (event->type == GDK_BUTTON_PRESS && event->button == 3 && self->priv->contact_menu)
    gtk_menu_popup (GTK_MENU (self->priv->contact_menu->get_menu (boost::assign::list_of (self->priv->menu))),
                    NULL, NULL, NULL, NULL, event->button, event->time);

  if ((event->type == GDK_2BUTTON_PRESS && event->button == 1) || (event->type == GDK_KEY_PRESS))
    g_action_group_activate_action (G_ACTION_GROUP (g_application_get_default ()), "call", NULL);

  return TRUE;
}
/* GObject stuff */
static void
call_history_view_gtk_dispose (GObject* obj)
{
  CallHistoryViewGtk* view = NULL;

  view = CALL_HISTORY_VIEW_GTK (obj);

  if (view->priv->store) {

    g_object_unref (view->priv->store);
    view->priv->store = NULL;
  }

  if (view->priv->tree) {

    GtkTreeSelection* selection = NULL;

    selection = gtk_tree_view_get_selection (view->priv->tree);

    g_signal_handlers_disconnect_matched (selection,
					  (GSignalMatchType) G_SIGNAL_MATCH_DATA,
					  0, /* signal_id */
					  (GQuark) 0, /* detail */
					  NULL,	/* closure */
					  NULL,	/* func */
					  view /* data */);

    g_signal_handlers_disconnect_matched (view->priv->tree,
					  (GSignalMatchType) G_SIGNAL_MATCH_DATA,
					  0, /* signal_id */
					  (GQuark)0, /* detail */
					  NULL, /* closure */
					  NULL, /* func */
					  &(*(view->priv->book)) /* data */);
    view->priv->tree = NULL;
  }

  G_OBJECT_CLASS (call_history_view_gtk_parent_class)->dispose (obj);
}
static void
on_book_cleared (CallHistoryViewGtk* data)
{
  GtkListStore *store = NULL;
  GtkTreeSelection *selection = NULL;

  g_return_if_fail (IS_CALL_HISTORY_VIEW_GTK (data));
  CallHistoryViewGtk *self = CALL_HISTORY_VIEW_GTK (data);

  store = GTK_LIST_STORE (gtk_tree_view_get_model (self->priv->tree));
  selection = gtk_tree_view_get_selection (self->priv->tree);

  /* Reset old data. This also ensures GIO actions are
   * properly removed before adding new ones.
   */
  self->priv->contact_menu.reset ();

  if (selection)
    g_signal_handlers_block_by_func (selection, (gpointer) on_selection_changed, self);
  gtk_list_store_clear (store);
  if (selection)
    g_signal_handlers_unblock_by_func (selection, (gpointer) on_selection_changed, self);
}