]> git.0d.be Git - empathy.git/blob - src/empathy-debug-dialog.c
Only connect to NewDebugMessage if the paused button is not pressed.
[empathy.git] / src / empathy-debug-dialog.c
1 /*
2 *  Copyright (C) 2009 Collabora Ltd.
3 *
4 *  This library is free software; you can redistribute it and/or
5 *  modify it under the terms of the GNU Lesser General Public
6 *  License as published by the Free Software Foundation; either
7 *  version 2.1 of the License, or (at your option) any later version.
8 *
9 *  This library is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *  Lesser General Public License for more details.
13 *
14 *  You should have received a copy of the GNU Lesser General Public
15 *  License along with this library; if not, write to the Free Software
16 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 *
18 *  Authors: Jonny Lamb <jonny.lamb@collabora.co.uk>
19 */
20
21 #include "config.h"
22
23 #include <glib/gi18n.h>
24 #include <gtk/gtk.h>
25
26 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
27 #include <libempathy/empathy-debug.h>
28 #include <libempathy/empathy-utils.h>
29
30 #include <libempathy-gtk/empathy-account-chooser.h>
31
32 #include <telepathy-glib/dbus.h>
33
34 #include "extensions/extensions.h"
35
36 #include "empathy-debug-dialog.h"
37
38 G_DEFINE_TYPE (EmpathyDebugDialog, empathy_debug_dialog,
39     GTK_TYPE_DIALOG)
40
41 enum
42 {
43   PROP_0,
44   PROP_PARENT
45 };
46
47 enum
48 {
49   COL_TIMESTAMP = 0,
50   COL_DOMAIN,
51   COL_CATEGORY,
52   COL_LEVEL,
53   COL_MESSAGE,
54   NUM_COLS
55 };
56
57 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyDebugDialog)
58 typedef struct
59 {
60   GtkWidget *filter;
61   GtkWindow *parent;
62   GtkWidget *view;
63   GtkWidget *account_chooser;
64   GtkListStore *store;
65   TpProxySignalConnection *signal_connection;
66   gboolean paused;
67   gboolean dispose_run;
68 } EmpathyDebugDialogPriv;
69
70 static const gchar *
71 log_level_to_string (guint level)
72 {
73   switch (level)
74     {
75     case EMP_DEBUG_LEVEL_ERROR:
76       return _("Error");
77       break;
78     case EMP_DEBUG_LEVEL_CRITICAL:
79       return _("Critical");
80       break;
81     case EMP_DEBUG_LEVEL_WARNING:
82       return _("Warning");
83       break;
84     case EMP_DEBUG_LEVEL_MESSAGE:
85       return _("Message");
86       break;
87     case EMP_DEBUG_LEVEL_INFO:
88       return _("Info");
89       break;
90     case EMP_DEBUG_LEVEL_DEBUG:
91       return _("Debug");
92       break;
93     default:
94       g_assert_not_reached ();
95       break;
96     }
97 }
98
99 static void
100 debug_dialog_add_message (EmpathyDebugDialog *debug_dialog,
101                           gdouble timestamp,
102                           const gchar *domain_category,
103                           guint level,
104                           const gchar *message)
105 {
106   EmpathyDebugDialogPriv *priv = GET_PRIV (debug_dialog);
107   gchar *domain, *category;
108   GtkTreeIter iter;
109
110   if (g_strrstr (domain_category, "/"))
111     {
112       gchar **parts = g_strsplit (domain_category, "/", 2);
113       domain = g_strdup (parts[0]);
114       category = g_strdup (parts[1]);
115       g_strfreev (parts);
116     }
117   else
118     {
119       domain = g_strdup (domain_category);
120       category = "";
121     }
122
123   gtk_list_store_append (priv->store, &iter);
124   gtk_list_store_set (priv->store, &iter,
125                       COL_TIMESTAMP, timestamp,
126                       COL_DOMAIN, domain,
127                       COL_CATEGORY, category,
128                       COL_LEVEL, log_level_to_string (level),
129                       COL_MESSAGE, message,
130                       -1);
131
132   g_free (domain);
133   g_free (category);
134 }
135
136 static void
137 debug_dialog_new_debug_message_cb (TpProxy *proxy,
138                                    gdouble timestamp,
139                                    const gchar *domain,
140                                    guint level,
141                                    const gchar *message,
142                                    gpointer user_data,
143                                    GObject *weak_object)
144 {
145   EmpathyDebugDialog *debug_dialog = (EmpathyDebugDialog *) user_data;
146
147   debug_dialog_add_message (debug_dialog, timestamp, domain, level,
148       message);
149 }
150
151 static void
152 debug_dialog_get_messages_cb (TpProxy *proxy,
153                               const GPtrArray *messages,
154                               const GError *error,
155                               gpointer user_data,
156                               GObject *weak_object)
157 {
158   EmpathyDebugDialog *debug_dialog = (EmpathyDebugDialog *) user_data;
159   EmpathyDebugDialogPriv *priv = GET_PRIV (debug_dialog);
160   gint i;
161
162   if (error != NULL)
163     {
164       DEBUG ("GetMessages failed: %s", error->message);
165       return;
166     }
167
168   for (i = 0; i < messages->len; i++)
169     {
170       GValueArray *values = g_ptr_array_index (messages, i);
171
172       debug_dialog_add_message (debug_dialog,
173           g_value_get_double (g_value_array_get_nth (values, 0)),
174           g_value_get_string (g_value_array_get_nth (values, 1)),
175           g_value_get_uint (g_value_array_get_nth (values, 2)),
176           g_value_get_string (g_value_array_get_nth (values, 3)));
177     }
178
179   if (!priv->paused)
180     {
181       /* Connect to NewDebugMessage */
182       priv->signal_connection = emp_cli_debug_connect_to_new_debug_message (proxy,
183           debug_dialog_new_debug_message_cb, debug_dialog, NULL, NULL, NULL);
184     }
185 }
186
187 static void
188 debug_dialog_account_chooser_changed_cb (GtkComboBox *account_chooser,
189                                          EmpathyDebugDialog *debug_dialog)
190 {
191   McAccount *account;
192   TpConnection *connection;
193   MissionControl *mc;
194   TpDBusDaemon *dbus;
195   GError *error = NULL;
196
197   mc = empathy_mission_control_dup_singleton ();
198   account = empathy_account_chooser_get_account (EMPATHY_ACCOUNT_CHOOSER (account_chooser));
199   connection = mission_control_get_tpconnection (mc, account, &error);
200
201   if (error != NULL)
202     {
203       DEBUG ("Getting the account's TpConnection failed: %s", error->message);
204       g_error_free (error);
205       return;
206     }
207
208   dbus = g_object_ref (tp_proxy_get_dbus_daemon (connection));
209
210   /* TODO: Fix this. */
211   connection = tp_connection_new (dbus,
212                                   "org.freedesktop.Telepathy.ConnectionManager.gabble",
213                                   "/org/freedesktop/Telepathy/debug",
214                                   &error);
215
216   if (error != NULL)
217     {
218       DEBUG ("Getting a new TpConnection failed: %s", error->message);
219       g_error_free (error);
220       return;
221     }
222
223   emp_cli_debug_call_get_messages (TP_PROXY (connection), -1,
224       debug_dialog_get_messages_cb, debug_dialog, NULL, NULL);
225
226   g_object_unref (connection);
227   g_object_unref (account);
228   g_object_unref (dbus);
229 }
230
231 static GObject *
232 debug_dialog_constructor (GType type,
233                           guint n_construct_params,
234                           GObjectConstructParam *construct_params)
235 {
236   GObject *object;
237   EmpathyDebugDialogPriv *priv;
238   GtkWidget *vbox;
239   GtkWidget *toolbar;
240   GtkWidget *image;
241   GtkToolItem *item;
242   GtkCellRenderer *renderer;
243   GtkWidget *scrolled_win;
244
245   object = G_OBJECT_CLASS (empathy_debug_dialog_parent_class)->constructor
246     (type, n_construct_params, construct_params);
247   priv = GET_PRIV (object);
248
249   gtk_window_set_title (GTK_WINDOW (object), _("Debug Window"));
250   gtk_window_set_default_size (GTK_WINDOW (object), 800, 400);
251   gtk_window_set_transient_for (GTK_WINDOW (object), priv->parent);
252
253   vbox = GTK_DIALOG (object)->vbox;
254
255   toolbar = gtk_toolbar_new ();
256   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
257   gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE);
258   gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_SMALL_TOOLBAR);
259   gtk_widget_show (toolbar);
260
261   gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
262
263   /* Account */
264   item = gtk_tool_item_new ();
265   gtk_widget_show (GTK_WIDGET (item));
266   gtk_container_add (GTK_CONTAINER (item), gtk_label_new (_("Account ")));
267   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
268
269   priv->account_chooser = empathy_account_chooser_new ();
270   empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser),
271       (EmpathyAccountChooserFilterFunc) mc_account_is_enabled, NULL);
272   g_signal_connect (priv->account_chooser, "changed",
273       G_CALLBACK (debug_dialog_account_chooser_changed_cb), object);
274   gtk_widget_show (priv->account_chooser);
275
276   item = gtk_tool_item_new ();
277   gtk_widget_show (GTK_WIDGET (item));
278   gtk_container_add (GTK_CONTAINER (item), priv->account_chooser);
279   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
280
281   item = gtk_separator_tool_item_new ();
282   gtk_widget_show (GTK_WIDGET (item));
283   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
284
285   /* Save */
286   item = gtk_tool_button_new_from_stock (GTK_STOCK_SAVE);
287   gtk_widget_show (GTK_WIDGET (item));
288   gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
289   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
290
291   /* Clear */
292   item = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR);
293   gtk_widget_show (GTK_WIDGET (item));
294   gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
295   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
296
297   item = gtk_separator_tool_item_new ();
298   gtk_widget_show (GTK_WIDGET (item));
299   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
300
301   /* Pause */
302   priv->paused = FALSE;
303   image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU);
304   gtk_widget_show (image);
305   item = gtk_toggle_tool_button_new ();
306   gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (item), !priv->paused);
307   gtk_widget_show (GTK_WIDGET (item));
308   gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
309   gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), _("Pause"));
310   gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), image);
311   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
312
313   item = gtk_separator_tool_item_new ();
314   gtk_widget_show (GTK_WIDGET (item));
315   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
316
317   /* Level */
318   item = gtk_tool_item_new ();
319   gtk_widget_show (GTK_WIDGET (item));
320   gtk_container_add (GTK_CONTAINER (item), gtk_label_new (_("Level ")));
321   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
322
323   priv->filter = gtk_combo_box_new_text ();
324   gtk_widget_show (priv->filter);
325
326   item = gtk_tool_item_new ();
327   gtk_widget_show (GTK_WIDGET (item));
328   gtk_container_add (GTK_CONTAINER (item), priv->filter);
329   gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
330
331   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("All"));
332   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Debug"));
333   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Info"));
334   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Message"));
335   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Warning"));
336   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Critical"));
337   gtk_combo_box_append_text (GTK_COMBO_BOX (priv->filter), _("Error"));
338
339   gtk_combo_box_set_active (GTK_COMBO_BOX (priv->filter), 0);
340   gtk_widget_show (GTK_WIDGET (priv->filter));
341
342   /* Debug treeview */
343   priv->view = gtk_tree_view_new ();
344
345   renderer = gtk_cell_renderer_text_new ();
346
347   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
348       -1, _("Time"), renderer, "text", COL_TIMESTAMP, NULL);
349   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
350       -1, _("Domain"), renderer, "text", COL_DOMAIN, NULL);
351   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
352       -1, _("Category"), renderer, "text", COL_CATEGORY, NULL);
353   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
354       -1, _("Level"), renderer, "text", COL_LEVEL, NULL);
355   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view),
356       -1, _("Message"), renderer, "text", COL_MESSAGE, NULL);
357
358   priv->store = gtk_list_store_new (NUM_COLS, G_TYPE_DOUBLE,
359       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
360
361   /* Fill treeview */
362   debug_dialog_account_chooser_changed_cb (GTK_COMBO_BOX (priv->account_chooser),
363       EMPATHY_DEBUG_DIALOG (object));
364
365   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view),
366       GTK_TREE_MODEL (priv->store));
367
368   /* Scrolled window */
369   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
370   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
371       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
372
373   gtk_widget_show (priv->view);
374   gtk_container_add (GTK_CONTAINER (scrolled_win), priv->view);
375
376   gtk_widget_show (scrolled_win);
377   gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
378
379   gtk_widget_show (GTK_WIDGET (object));
380
381   return object;
382 }
383
384 static void
385 empathy_debug_dialog_init (EmpathyDebugDialog *empathy_debug_dialog)
386 {
387   EmpathyDebugDialogPriv *priv =
388       G_TYPE_INSTANCE_GET_PRIVATE (empathy_debug_dialog,
389       EMPATHY_TYPE_DEBUG_DIALOG, EmpathyDebugDialogPriv);
390
391   empathy_debug_dialog->priv = priv;
392
393   priv->dispose_run = FALSE;
394 }
395
396 static void
397 debug_dialog_set_property (GObject *object,
398                            guint prop_id,
399                            const GValue *value,
400                            GParamSpec *pspec)
401 {
402   EmpathyDebugDialogPriv *priv = GET_PRIV (object);
403
404   switch (prop_id)
405     {
406       case PROP_PARENT:
407         priv->parent = GTK_WINDOW (g_value_dup_object (value));
408         break;
409       default:
410         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
411         break;
412     }
413 }
414
415 static void
416 debug_dialog_get_property (GObject *object,
417                            guint prop_id,
418                            GValue *value,
419                            GParamSpec *pspec)
420 {
421   EmpathyDebugDialogPriv *priv = GET_PRIV (object);
422
423   switch (prop_id)
424     {
425       case PROP_PARENT:
426         g_value_set_object (value, priv->parent);
427         break;
428       default:
429         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430         break;
431     }
432 }
433
434 static void
435 debug_dialog_dispose (GObject *object)
436 {
437   EmpathyDebugDialog *selector = EMPATHY_DEBUG_DIALOG (object);
438   EmpathyDebugDialogPriv *priv = GET_PRIV (selector);
439
440   if (priv->dispose_run)
441     return;
442
443   priv->dispose_run = TRUE;
444
445   if (priv->parent)
446     g_object_unref (priv->parent);
447
448   if (priv->store)
449     g_object_unref (priv->store);
450
451   if (priv->signal_connection)
452     tp_proxy_signal_connection_disconnect (priv->signal_connection);
453
454   (G_OBJECT_CLASS (empathy_debug_dialog_parent_class)->dispose) (object);
455 }
456
457 static void
458 empathy_debug_dialog_class_init (EmpathyDebugDialogClass *klass)
459 {
460   GObjectClass *object_class = G_OBJECT_CLASS (klass);
461   object_class->constructor = debug_dialog_constructor;
462   object_class->dispose = debug_dialog_dispose;
463   object_class->set_property = debug_dialog_set_property;
464   object_class->get_property = debug_dialog_get_property;
465   g_type_class_add_private (klass, sizeof (EmpathyDebugDialogPriv));
466
467   g_object_class_install_property (object_class, PROP_PARENT,
468       g_param_spec_object ("parent", "parent", "parent",
469       GTK_TYPE_WINDOW, G_PARAM_CONSTRUCT_ONLY |
470       G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
471 }
472
473 /* public methods */
474
475 GtkWidget *
476 empathy_debug_dialog_new (GtkWindow *parent)
477 {
478   return GTK_WIDGET (g_object_new (EMPATHY_TYPE_DEBUG_DIALOG,
479       "parent", parent, NULL));
480 }