#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include <libempathy/empathy-debug.h>
#include <libempathy/empathy-utils.h>
#include <libempathy-gtk/empathy-account-chooser.h>
+#include <libempathy-gtk/empathy-geometry.h>
#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/util.h>
#include <telepathy-glib/proxy-subclass.h>
TpProxy *proxy;
TpProxySignalConnection *new_debug_message_signal;
TpProxySignalConnection *name_owner_changed_signal;
+ gulong invalid_signal_id;
/* Whether NewDebugMessage will be fired */
gboolean paused;
{
switch (level)
{
- case EMP_DEBUG_LEVEL_ERROR:
- return _("Error");
+ case TP_DEBUG_LEVEL_ERROR:
+ return "Error";
break;
- case EMP_DEBUG_LEVEL_CRITICAL:
- return _("Critical");
+ case TP_DEBUG_LEVEL_CRITICAL:
+ return "Critical";
break;
- case EMP_DEBUG_LEVEL_WARNING:
- return _("Warning");
+ case TP_DEBUG_LEVEL_WARNING:
+ return "Warning";
break;
- case EMP_DEBUG_LEVEL_MESSAGE:
- return _("Message");
+ case TP_DEBUG_LEVEL_MESSAGE:
+ return "Message";
break;
- case EMP_DEBUG_LEVEL_INFO:
- return _("Info");
+ case TP_DEBUG_LEVEL_INFO:
+ return "Info";
break;
- case EMP_DEBUG_LEVEL_DEBUG:
- return _("Debug");
+ case TP_DEBUG_LEVEL_DEBUG:
+ return "Debug";
break;
default:
g_assert_not_reached ();
g_slice_free (DebugMessage, dm);
}
+static void
+debug_message_list_free (gpointer data)
+{
+ GList *list = data;
+
+ g_list_foreach (list, (GFunc) debug_message_free, NULL);
+ g_list_free (list);
+}
+
static void
debug_window_cache_new_message (EmpathyDebugWindow *debug_window,
gdouble timestamp,
val = tp_g_value_slice_new_boolean (enabled);
- tp_cli_dbus_properties_call_set (priv->proxy, -1, EMP_IFACE_DEBUG,
+ tp_cli_dbus_properties_call_set (priv->proxy, -1, TP_IFACE_DEBUG,
"Enabled", val, NULL, NULL, NULL, NULL);
tp_g_value_slice_free (val);
GtkTreeIter iter;
gchar *name;
GList *old_messages;
- gint i;
+ guint i;
if (error != NULL)
{
if (old_messages != NULL)
{
g_hash_table_remove (priv->all_cms, name);
- g_list_foreach (old_messages, (GFunc) debug_message_free, NULL);
- g_list_free (old_messages);
+ debug_message_list_free (old_messages);
}
for (i = 0; i < messages->len; i++)
}
}
+static void
+proxy_invalidated_cb (TpProxy *proxy,
+ guint domain,
+ gint code,
+ gchar *msg,
+ EmpathyDebugWindowPriv *self)
+{
+ EmpathyDebugWindowPriv *priv = GET_PRIV (self);
+
+ /* Proxy has been invalidated so we can't disconnect the signal any more */
+ priv->new_debug_message_signal = NULL;
+}
+
static void
debug_window_cm_chooser_changed_cb (GtkComboBox *cm_chooser,
EmpathyDebugWindow *debug_window)
}
if (priv->proxy != NULL)
- g_object_unref (priv->proxy);
+ {
+ g_signal_handler_disconnect (priv->proxy, priv->invalid_signal_id);
+ g_object_unref (priv->proxy);
+ }
priv->proxy = proxy;
emp_cli_debug_call_get_messages (priv->proxy, -1,
debug_window_get_messages_cb, debug_window, NULL, NULL);
+ priv->invalid_signal_id = g_signal_connect (proxy, "invalidated",
+ G_CALLBACK (proxy_invalidated_cb), debug_window);
+
g_object_unref (dbus);
}
* just joined), we don't need to check whether the unique
* name is in the CM model. Hooray.
*/
- GtkTreeIter iter;
const gchar *name = arg0 + strlen (CM_WELL_KNOWN_NAME_PREFIX);
if (!g_hash_table_lookup (priv->all_cms, name))
{
+ GtkTreeIter iter;
DEBUG ("Adding new CM '%s' at %s.", name, arg2);
gtk_list_store_append (priv->cms, &iter);
/* Add empathy */
gtk_list_store_append (priv->cms, &iter);
gtk_list_store_set (priv->cms, &iter,
- COL_CM_NAME, "empathy",
- COL_CM_UNIQUE_NAME, "org.gnome.Empathy",
+ COL_CM_NAME, _(PACKAGE_NAME),
+ COL_CM_UNIQUE_NAME, "org.gnome."PACKAGE_NAME,
-1);
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->cm_chooser), 0);
tp_list_connection_names (priv->dbus, debug_window_list_connection_names_cb,
debug_window, NULL, NULL);
+ /* add Mission Control */
+ gtk_list_store_append (priv->cms, &iter);
+ gtk_list_store_set (priv->cms, &iter,
+ COL_CM_NAME, "misson-control",
+ COL_CM_UNIQUE_NAME, "org.freedesktop.Telepathy.MissionControl5",
+ -1);
+
priv->name_owner_changed_signal =
tp_cli_dbus_daemon_connect_to_name_owner_changed (priv->dbus,
debug_window_name_owner_changed_cb, debug_window, NULL, NULL, NULL);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
data->button, data->time);
+ g_object_ref_sink (menu);
+ g_object_unref (menu);
g_slice_free (MenuPopupData, user_data);
return FALSE;
}
+static gchar *
+debug_window_format_timestamp (gdouble timestamp)
+{
+ struct tm *tstruct;
+ char time_str[32];
+ gint ms;
+ time_t sec;
+ gchar *text;
+
+ ms = (int) ((timestamp - (int) timestamp)*1e6);
+ sec = (long) timestamp;
+ tstruct = localtime ((time_t *) &sec);
+ if (!strftime (time_str, sizeof (time_str), "%x %T", tstruct))
+ {
+ DEBUG ("Failed to format timestamp: %e", timestamp);
+ time_str[0] = '\0';
+ }
+
+ text = g_strdup_printf ("%s.%d", time_str, ms);
+
+ return text;
+}
+
+static void
+debug_window_time_formatter (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gdouble timestamp;
+ gchar *time_str;
+
+ gtk_tree_model_get (tree_model, iter, COL_DEBUG_TIMESTAMP, ×tamp, -1);
+
+ time_str = debug_window_format_timestamp (timestamp);
+
+ g_object_set (G_OBJECT (cell), "text", time_str, NULL);
+
+ g_free (time_str);
+}
+
static gboolean
debug_window_store_filter_foreach (GtkTreeModel *model,
GtkTreePath *path,
GFileOutputStream *output_stream = (GFileOutputStream *) user_data;
gchar *domain, *category, *message, *level_str, *level_upper;
gdouble timestamp;
- gchar *line;
+ gchar *line, *time_str;
GError *error = NULL;
gboolean out = FALSE;
level_upper = g_ascii_strup (level_str, -1);
- line = g_strdup_printf ("%s%s%s-%s: %e: %s\n",
+ time_str = debug_window_format_timestamp (timestamp);
+
+ line = g_strdup_printf ("%s%s%s-%s: %s: %s\n",
domain, EMP_STR_EMPTY (category) ? "" : "/",
- category, level_upper, timestamp, message);
+ category, level_upper, time_str, message);
+
+ g_free (time_str);
g_output_stream_write (G_OUTPUT_STREAM (output_stream), line,
strlen (line), NULL, &error);
gchar *tmp;
gchar *domain, *category, *message, *level_str, *level_upper;
gdouble timestamp;
- gchar *line;
+ gchar *line, *time_str;
gtk_tree_model_get (model, iter,
COL_DEBUG_TIMESTAMP, ×tamp,
level_upper = g_ascii_strup (level_str, -1);
- line = g_strdup_printf ("%s%s%s-%s: %e: %s\n",
+ time_str = debug_window_format_timestamp (timestamp);
+
+ line = g_strdup_printf ("%s%s%s-%s: %s: %s\n",
domain, EMP_STR_EMPTY (category) ? "" : "/",
- category, level_upper, timestamp, message);
+ category, level_upper, time_str, message);
+
+ g_free (time_str);
tmp = g_strconcat (*text, line, NULL);
g_free (text);
}
+static gboolean
+debug_window_key_press_event_cb (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ if ((event->state & GDK_CONTROL_MASK && event->keyval == GDK_w)
+ || event->keyval == GDK_Escape)
+ {
+ gtk_widget_destroy (widget);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+tree_view_search_equal_func_cb (GtkTreeModel *model,
+ gint column,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer search_data)
+{
+ gchar *str;
+ gint key_len;
+ gint len;
+ gint i;
+ gboolean ret = TRUE; /* The return value is counter-intuitive */
+
+ gtk_tree_model_get (model, iter, column, &str, -1);
+
+ key_len = strlen (key);
+ len = strlen (str) - key_len;
+
+ for (i = 0; i <= len; ++i)
+ {
+ if (!g_ascii_strncasecmp (key, str + i, key_len))
+ {
+ ret = FALSE;
+ break;
+ }
+ }
+
+ g_free (str);
+ return ret;
+}
+
static GObject *
debug_window_constructor (GType type,
guint n_construct_params,
gtk_window_set_title (GTK_WINDOW (object), _("Debug Window"));
gtk_window_set_default_size (GTK_WINDOW (object), 800, 400);
+ empathy_geometry_bind (GTK_WINDOW (object), "debug-window");
+
+ g_signal_connect (object, "key-press-event",
+ G_CALLBACK (debug_window_key_press_event_cb), NULL);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (object), vbox);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Debug"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_DEBUG,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_DEBUG,
-1);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Info"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_INFO,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_INFO,
-1);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Message"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_MESSAGE,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_MESSAGE,
-1);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Warning"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_WARNING,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_WARNING,
-1);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Critical"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_CRITICAL,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_CRITICAL,
-1);
gtk_list_store_append (level_store, &iter);
gtk_list_store_set (level_store, &iter,
COL_LEVEL_NAME, _("Error"),
- COL_LEVEL_VALUE, EMP_DEBUG_LEVEL_ERROR,
+ COL_LEVEL_VALUE, TP_DEBUG_LEVEL_ERROR,
-1);
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->level_filter), 0);
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "yalign", 0, NULL);
- gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
- -1, _("Time"), renderer, "text", COL_DEBUG_TIMESTAMP, NULL);
+ gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (priv->view),
+ -1, _("Time"), renderer,
+ (GtkTreeCellDataFunc) debug_window_time_formatter, NULL, NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
-1, _("Domain"), renderer, "text", COL_DEBUG_DOMAIN, NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view), priv->store_filter);
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->view),
+ COL_DEBUG_MESSAGE);
+ gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (priv->view),
+ tree_view_search_equal_func_cb, NULL, NULL);
+
/* Scrolled window */
priv->scrolled_win = g_object_ref (gtk_scrolled_window_new (NULL, NULL));
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_win),
while (g_hash_table_iter_next (&iter, (gpointer *) &key,
(gpointer *) &values))
{
- g_list_foreach (values, (GFunc) debug_message_free, NULL);
- g_list_free (values);
+ debug_message_list_free (values);
}
g_hash_table_destroy (priv->all_cms);
if (priv->proxy != NULL)
{
debug_window_set_enabled (EMPATHY_DEBUG_WINDOW (object), FALSE);
+ g_signal_handler_disconnect (priv->proxy, priv->invalid_signal_id);
g_object_unref (priv->proxy);
}
GtkWidget *
empathy_debug_window_new (GtkWindow *parent)
{
- g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
+ g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
return GTK_WIDGET (g_object_new (EMPATHY_TYPE_DEBUG_WINDOW,
"transient-for", parent, NULL));