2003-09-21 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / tools / dbus-viewer.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-viewer.c Graphical D-BUS frontend utility
3  *
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include <config.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <gtk/gtk.h>
29 #include "dbus-tree-view.h"
30 #include <glib/dbus-gparser.h>
31 #include <glib/dbus-gutils.h>
32
33 #include <libintl.h>
34 #define _(x) dgettext (GETTEXT_PACKAGE, x)
35 #define N_(x) x
36
37 typedef struct
38 {
39   int refcount;
40   char *name;
41
42 } ServiceData;
43
44 static ServiceData*
45 service_data_new (const char *name)
46 {
47   ServiceData *sd;
48
49   sd = g_new0 (ServiceData, 1);
50
51   sd->refcount = 1;
52   sd->name = g_strdup (name);
53
54   return sd;
55 }
56
57 static void
58 service_data_ref (ServiceData *sd)
59 {
60   sd->refcount += 1;
61 }
62
63 static void
64 service_data_unref (ServiceData *sd)
65 {
66   sd->refcount -= 1;
67   if (sd->refcount == 0)
68     {
69       g_free (sd->name);
70       g_free (sd);
71     }
72 }
73
74 typedef struct
75 {
76   GtkWidget *window;
77   GtkWidget *treeview;
78   GtkWidget *service_menu;
79
80   GSList *services;
81   
82 } TreeWindow;
83
84 static void
85 window_closed_callback (GtkWidget  *window,
86                         TreeWindow *w)
87 {
88   g_assert (window == w->window);
89   w->window = NULL;
90   gtk_main_quit ();
91 }
92
93 static TreeWindow*
94 tree_window_new (void)
95 {
96   TreeWindow *w;
97   GtkWidget *sw;
98   GtkWidget *vbox;
99   GtkWidget *hbox;
100
101   /* Should use glade, blah */
102   
103   w = g_new0 (TreeWindow, 1);
104   w->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
105
106   gtk_window_set_title (GTK_WINDOW (w->window), "D-BUS Viewer");
107   gtk_window_set_default_size (GTK_WINDOW (w->window), 400, 500);
108
109   g_signal_connect (w->window, "destroy", G_CALLBACK (window_closed_callback),
110                     w);
111   gtk_container_set_border_width (GTK_CONTAINER (w->window), 6);
112
113   vbox = gtk_vbox_new (FALSE, 6);
114   gtk_container_add (GTK_CONTAINER (w->window), vbox);
115   
116   hbox = gtk_hbox_new (FALSE, 6);
117   gtk_container_add (GTK_CONTAINER (vbox), hbox);
118
119   /* Create tree view */
120   
121   sw = gtk_scrolled_window_new (NULL, NULL);
122   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
123                                   GTK_POLICY_AUTOMATIC,
124                                   GTK_POLICY_AUTOMATIC);
125
126   gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);
127
128   w->treeview = dbus_tree_view_new ();
129
130   gtk_container_add (GTK_CONTAINER (sw), w->treeview);
131
132   /* Create services option menu */
133
134   
135
136   /* Show everything */
137   gtk_widget_show_all (w->window);
138
139   return w;
140 }
141
142 static void
143 show_error_dialog (GtkWindow *transient_parent,
144                    GtkWidget **weak_ptr,
145                    const char *message_format,
146                    ...)
147 {
148   char *message;
149   va_list args;
150
151   if (message_format)
152     {
153       va_start (args, message_format);
154       message = g_strdup_vprintf (message_format, args);
155       va_end (args);
156     }
157   else
158     message = NULL;
159
160   if (weak_ptr == NULL || *weak_ptr == NULL)
161     {
162       GtkWidget *dialog;
163       dialog = gtk_message_dialog_new (transient_parent,
164                                        GTK_DIALOG_DESTROY_WITH_PARENT,
165                                        GTK_MESSAGE_ERROR,
166                                        GTK_BUTTONS_CLOSE,
167                                        message);
168
169       g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
170
171       if (weak_ptr != NULL)
172         {
173           *weak_ptr = dialog;
174           g_object_add_weak_pointer (G_OBJECT (dialog), (void**)weak_ptr);
175         }
176
177       gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
178       
179       gtk_widget_show_all (dialog);
180     }
181   else 
182     {
183       g_return_if_fail (GTK_IS_MESSAGE_DIALOG (*weak_ptr));
184
185       gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (*weak_ptr)->label), message);
186
187       gtk_window_present (GTK_WINDOW (*weak_ptr));
188     }
189 }
190
191 static void
192 usage (int ecode)
193 {
194   fprintf (stderr, "dbus-viewer [--version] [--help]\n");
195   exit (ecode);
196 }
197
198 static void
199 version (void)
200 {
201   printf ("D-BUS Message Bus Viewer %s\n"
202           "Copyright (C) 2003 Red Hat, Inc.\n"
203           "This is free software; see the source for copying conditions.\n"
204           "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
205           VERSION);
206   exit (0);
207 }
208
209 int
210 main (int argc, char **argv)
211 {
212   const char *prev_arg;
213   int i;
214   GSList *files;
215   gboolean end_of_args;
216   GSList *tmp;
217   
218   bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);
219   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
220   textdomain (GETTEXT_PACKAGE); 
221   
222   gtk_init (&argc, &argv);
223
224   end_of_args = FALSE;
225   files = NULL;
226   prev_arg = NULL;
227   i = 1;
228   while (i < argc)
229     {
230       const char *arg = argv[i];
231
232       if (!end_of_args)
233         {
234           if (strcmp (arg, "--help") == 0 ||
235               strcmp (arg, "-h") == 0 ||
236               strcmp (arg, "-?") == 0)
237             usage (0);
238           else if (strcmp (arg, "--version") == 0)
239             version ();
240           else if (arg[0] == '-' &&
241                    arg[1] == '-' &&
242                    arg[2] == '\0')
243             end_of_args = TRUE;
244           else if (arg[0] == '-')
245             {
246               usage (1);
247             }
248           else
249             {
250               files = g_slist_prepend (files, (char*) arg);
251             }
252         }
253       else
254         files = g_slist_prepend (files, (char*) arg);
255       
256       prev_arg = arg;
257       
258       ++i;
259     }
260
261   files = g_slist_reverse (files);
262
263   tmp = files;
264   while (tmp != NULL)
265     {
266       NodeInfo *node;
267       GError *error;
268       const char *filename;
269
270       filename = tmp->data;
271
272       error = NULL;
273       node = description_load_from_file (filename,
274                                          &error);
275       if (node == NULL)
276         {
277           g_assert (error != NULL);
278           show_error_dialog (NULL, NULL,
279                              _("Unable to load \"%s\": %s\n"),
280                              filename, error->message);
281           g_error_free (error);
282         }
283       else
284         {
285           TreeWindow *w;
286           char **path;
287           const char *name;
288
289           name = node_info_get_name (node);
290           if (name == NULL ||
291               name[0] != '/')
292             {
293               g_printerr (_("Assuming root node of \"%s\" is at path /, since no absolute path is specified"), filename);
294               name = "/";
295             }
296
297           path = _dbus_gutils_split_path (name);
298           
299           w = tree_window_new ();          
300           dbus_tree_view_update (GTK_TREE_VIEW (w->treeview),
301                                  (const char**) path,
302                                  node);
303           node_info_unref (node);
304
305           g_strfreev (path);
306         }
307       
308       tmp = tmp->next;
309     }
310
311   gtk_main ();
312   
313   return 0;
314 }
315
316
317
318
319
320