/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2009 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* Authors: Richard Hult <richard@imendio.com>
* Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
+ * Davyd Madeley <davyd.madeley@collabora.co.uk>
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
+#include <gdk/gdkkeysyms.h>
#include <telepathy-glib/util.h>
#include <libmissioncontrol/mc-enum-types.h>
#include <libempathy/empathy-utils.h>
#include <libempathy/empathy-status-presets.h>
+// FIXME - what's the correct debug flag?
+#define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
+#include <libempathy/empathy-debug.h>
+
#include "empathy-ui-utils.h"
#include "empathy-images.h"
#include "empathy-presence-chooser.h"
typedef struct {
EmpathyIdle *idle;
+ gboolean editing_status;
int block_set_editing;
+ int block_changed;
McPresence state;
const gchar *status);
static void presence_chooser_custom_activate_cb (GtkWidget *item,
gpointer user_data);
-static void presence_chooser_dialog_show (void);
+static void presence_chooser_dialog_show (GtkWindow *parent);
G_DEFINE_TYPE (EmpathyPresenceChooser, empathy_presence_chooser, GTK_TYPE_COMBO_BOX_ENTRY);
ENTRY_TYPE_BUILTIN,
ENTRY_TYPE_SAVED,
ENTRY_TYPE_CUSTOM,
+ ENTRY_TYPE_SEPARATOR,
+ ENTRY_TYPE_EDIT_CUSTOM,
};
static GtkTreeModel *
}
}
+
+ /* add a separator */
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_TYPE, ENTRY_TYPE_SEPARATOR,
+ -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_STATE_ICON_NAME, GTK_STOCK_EDIT,
+ COL_STATUS_TEXT, "",
+ COL_DISPLAY_MARKUP, "Edit Custom Messages...",
+ COL_TYPE, ENTRY_TYPE_EDIT_CUSTOM,
+ -1);
return GTK_TREE_MODEL (store);
}
if (!shown) return;
- g_print ("popup shown\n");
-
GtkTreeModel *model = create_model ();
gtk_combo_box_set_model (GTK_COMBO_BOX (self), GTK_TREE_MODEL (model));
if (editing)
{
+ priv->editing_status = TRUE;
gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
GTK_ENTRY_ICON_SECONDARY,
GTK_STOCK_OK);
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry),
GTK_ENTRY_ICON_SECONDARY,
- "Set status");
- // FIXME - is this nice?
+ _("Set status"));
gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
GTK_ENTRY_ICON_PRIMARY,
FALSE);
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry),
GTK_ENTRY_ICON_SECONDARY,
NULL);
- // FIXME - also this
gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
GTK_ENTRY_ICON_PRIMARY,
TRUE);
- // FIXME - move the focus somewhere
+ /* attempt to get the toplevel for this widget */
+ GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (GTK_WIDGET_TOPLEVEL (window) && GTK_IS_WINDOW (window))
+ {
+ /* unset the focus */
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ }
- /* update the status with MC */
- const char *status = gtk_entry_get_text (GTK_ENTRY (entry));
- empathy_idle_set_presence (priv->idle, priv->state, status);
+ priv->editing_status = FALSE;
}
}
+static void
+mc_set_custom_state (EmpathyPresenceChooser *self)
+{
+ EmpathyPresenceChooserPriv *priv = GET_PRIV (self);
+ GtkWidget *entry = gtk_bin_get_child (GTK_BIN (self));
+
+ /* update the status with MC */
+ const char *status = gtk_entry_get_text (GTK_ENTRY (entry));
+ DEBUG ("Sending state to MC-> %s (%s)\n",
+ g_enum_get_value (g_type_class_peek (MC_TYPE_PRESENCE),
+ priv->state)->value_name,
+ status);
+ empathy_idle_set_presence (priv->idle, priv->state, status);
+}
+
static void
ui_set_custom_state (EmpathyPresenceChooser *self,
McPresence state,
const char *icon_name;
priv->block_set_editing++;
+ priv->block_changed++;
icon_name = empathy_icon_name_for_presence (state);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
icon_name);
gtk_entry_set_text (GTK_ENTRY (entry), status);
+ priv->block_changed--;
priv->block_set_editing--;
}
GtkEntry *entry)
{
set_status_editing (self, FALSE);
+ mc_set_custom_state (self);
}
static void
entry_activate_cb (EmpathyPresenceChooser *self,
GtkEntry *entry)
{
- g_print ("ACTIVATE! (form of a dragon)\n");
-
set_status_editing (self, FALSE);
+ mc_set_custom_state (self);
+}
+
+static gboolean
+entry_key_press_event_cb (EmpathyPresenceChooser *self,
+ GdkEventKey *event,
+ GtkWidget *entry)
+{
+ EmpathyPresenceChooserPriv *priv = GET_PRIV (self);
+
+ if (priv->editing_status && event->keyval == GDK_Escape)
+ {
+ /* the user pressed Escape, undo the editing */
+ set_status_editing (self, FALSE);
+ presence_chooser_presence_changed_cb (self);
+
+ return TRUE;
+ }
+
+ return FALSE; /* send this event elsewhere */
}
static void
changed_cb (GtkComboBox *self, gpointer user_data)
{
EmpathyPresenceChooserPriv *priv = GET_PRIV (self);
- g_print ("Changed\n");
+
+ if (priv->block_changed) return;
GtkTreeIter iter;
char *icon_name;
if (!gtk_combo_box_get_active_iter (self, &iter))
{
/* the combo is being edited to a custom entry */
- set_status_editing (EMPATHY_PRESENCE_CHOOSER (self), TRUE);
+ if (!priv->editing_status)
+ {
+ set_status_editing (EMPATHY_PRESENCE_CHOOSER (self), TRUE);
+ }
return;
}
-1);
GtkWidget *entry = gtk_bin_get_child (GTK_BIN (self));
- gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
- GTK_ENTRY_ICON_PRIMARY,
- icon_name);
- if (type == ENTRY_TYPE_CUSTOM)
+ if (type == ENTRY_TYPE_EDIT_CUSTOM)
{
+ /* recover the status that was unset because COL_STATUS_TEXT
+ * is "". Unfortunately if you try and set COL_STATUS_TEXT to
+ * NULL, it generates a g_critical. I wonder if there is a
+ * better way around this. */
+ const char *status = empathy_idle_get_status (priv->idle);
+ priv->block_set_editing++;
+ gtk_entry_set_text (GTK_ENTRY (entry), status);
+ priv->block_set_editing--;
+
+ /* attempt to get the toplevel for this widget */
+ GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (!GTK_WIDGET_TOPLEVEL (window) || !GTK_IS_WINDOW (window))
+ {
+ window = NULL;
+ }
+
+ presence_chooser_dialog_show (GTK_WINDOW (window));
+ }
+ else if (type == ENTRY_TYPE_CUSTOM)
+ {
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ icon_name);
+
/* grab the focus */
gtk_widget_grab_focus (entry);
+
set_status_editing (EMPATHY_PRESENCE_CHOOSER (self), TRUE);
}
else
g_free (icon_name);
}
+static gboolean
+combo_row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ int type;
+ gtk_tree_model_get (model, iter,
+ COL_TYPE, &type,
+ -1);
+
+ return (type == ENTRY_TYPE_SEPARATOR);
+}
+
static void
empathy_presence_chooser_init (EmpathyPresenceChooser *chooser)
{
- //GtkWidget *arrow;
- //GtkWidget *alignment;
EmpathyPresenceChooserPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (chooser,
EMPATHY_TYPE_PRESENCE_CHOOSER, EmpathyPresenceChooserPriv);
-
chooser->priv = priv;
GtkTreeModel *model = create_model ();
gtk_combo_box_set_model (GTK_COMBO_BOX (chooser), GTK_TREE_MODEL (model));
- gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (chooser), COL_STATUS_TEXT);
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (chooser),
+ COL_STATUS_TEXT);
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (chooser),
+ combo_row_separator_func,
+ NULL, NULL);
GtkWidget *entry = gtk_bin_get_child (GTK_BIN (chooser));
gtk_entry_set_icon_activatable (GTK_ENTRY (entry),
g_signal_connect_object (entry, "activate",
G_CALLBACK (entry_activate_cb), chooser,
G_CONNECT_SWAPPED);
+ g_signal_connect_object (entry, "key-press-event",
+ G_CALLBACK (entry_key_press_event_cb), chooser,
+ G_CONNECT_SWAPPED);
+ // FIXME - should this also happen when the user presses TAB ?
GtkCellRenderer *renderer;
gtk_cell_layout_clear (GTK_CELL_LAYOUT (chooser));
g_signal_connect_swapped (priv->idle, "notify",
G_CALLBACK (presence_chooser_presence_changed_cb),
chooser);
+
+ g_object_set (chooser,
+ // FIXME: this string sucks
+ "tooltip-text", _("Set your presence and current status"),
+ NULL);
}
static void
McPresence flash_state;
const gchar *status;
- g_print (" > presence_chooser_presence_changed_cb\n");
-
priv = GET_PRIV (chooser);
- state = empathy_idle_get_state (priv->idle);
+ priv->state = state = empathy_idle_get_state (priv->idle);
status = empathy_idle_get_status (priv->idle);
flash_state = empathy_idle_get_flash_state (priv->idle);
- g_print ("status = %s\n", status);
-
- // FIXME - we need to either find an entry in the model or add one
+ /* look through the model and attempt to find a matching state */
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser));
GtkTreeIter iter;
gboolean valid, match_state = FALSE, match = FALSE;
COL_TYPE, &m_type,
-1);
- if (m_type == ENTRY_TYPE_CUSTOM)
+ if (m_type == ENTRY_TYPE_CUSTOM ||
+ m_type == ENTRY_TYPE_SEPARATOR ||
+ m_type == ENTRY_TYPE_EDIT_CUSTOM)
{
continue;
}
if (match)
{
- g_print ("GOT MATCH\n");
+ priv->block_changed++;
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser), &iter);
+ priv->block_changed--;
}
else
{
- g_print ("NO MATCH\n");
// FIXME - do we insert the match into the menu?
ui_set_custom_state (chooser, state, status);
}
static gboolean
presence_chooser_flash_timeout_cb (EmpathyPresenceChooser *chooser)
{
-#if 0
EmpathyPresenceChooserPriv *priv;
McPresence state;
static gboolean on = FALSE;
state = priv->flash_state_2;
}
- gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
- empathy_icon_name_for_presence (state),
- GTK_ICON_SIZE_MENU);
+ GtkWidget *entry = gtk_bin_get_child (GTK_BIN (chooser));
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ empathy_icon_name_for_presence (state));
on = !on;
-#endif
+
return TRUE;
}
g_source_remove (priv->flash_timeout_id);
priv->flash_timeout_id = 0;
}
-
- /*
- gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
- empathy_icon_name_for_presence (state),
- GTK_ICON_SIZE_MENU);
- */
+ GtkWidget *entry = gtk_bin_get_child (GTK_BIN (chooser));
+
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ empathy_icon_name_for_presence (state));
// FIXME - what does this do?
// priv->last_state = state;
presence_chooser_custom_activate_cb (GtkWidget *item,
gpointer user_data)
{
- presence_chooser_dialog_show ();
+ presence_chooser_dialog_show (NULL);
}
static McPresence
}
static void
-presence_chooser_dialog_show (void)
+presence_chooser_dialog_show (GtkWindow *parent)
{
GladeXML *glade;
gchar *filename;
gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (message_dialog->comboboxentry_message), 0);
- /* FIXME: Set transian for a window ? */
+ if (parent)
+ {
+ gtk_window_set_transient_for (
+ GTK_WINDOW (message_dialog->dialog),
+ parent);
+ }
gtk_widget_show_all (message_dialog->dialog);
}