]> git.sur5r.net Git - glabels/blob - glabels2/src/gnome-recent-view-bonobo.c
Initial revision
[glabels] / glabels2 / src / gnome-recent-view-bonobo.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /**
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as
5  * published by the Free Software Foundation; either version 2 of the
6  * License, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16  *
17  * Authors:
18  *   James Willcox <jwillcox@cs.indiana.edu>
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <gtk/gtk.h>
29 #include <gconf/gconf-client.h>
30 #include <libbonoboui.h>
31 #include <libgnomevfs/gnome-vfs.h>
32 #include "gnome-recent-model.h"
33 #include "gnome-recent-view.h"
34 #include "gnome-recent-view-bonobo.h"
35 #include "gnome-recent-util.h"
36 #include "gnome-recent-marshal.h"
37
38 #define GNOME_RECENT_VERB_NAME "-uri-"
39
40 struct _GnomeRecentViewBonobo {
41         GObject parent_instance;        /* We emit signals */
42
43         BonoboUIComponent *uic;
44         gchar *path;                    /* The menu path where our stuff
45                                          *  will go
46                                          */
47
48         gulong changed_cb_id;
49
50         GnomeRecentModel *model;
51 };
52
53 struct _GnomeRecentViewBonoboClass {
54         GObjectClass parent_class;
55         
56         void (*activate) (GnomeRecentViewBonobo *view, const gchar *uri);
57 };
58
59 struct _GnomeRecentViewBonoboMenuData {
60         GnomeRecentViewBonobo *view;
61         gchar *uri;
62 };
63
64 typedef struct _GnomeRecentViewBonoboMenuData GnomeRecentViewBonoboMenuData;
65
66 enum {
67         ACTIVATE,
68         LAST_SIGNAL
69 };
70
71 /* GObject properties */
72 enum {
73         PROP_BOGUS,
74         PROP_UI_COMPONENT,
75         PROP_MENU_PATH
76 };
77
78 static guint gnome_recent_view_bonobo_signals[LAST_SIGNAL] = { 0 };
79
80 static void
81 gnome_recent_view_bonobo_clear (GnomeRecentView *view_parent)
82 {
83         gint i=1;
84         gboolean done=FALSE;
85         gchar *appname;
86         GnomeRecentModel *model;
87         GnomeRecentViewBonobo *view;
88
89         g_return_if_fail (view_parent);
90         view = GNOME_RECENT_VIEW_BONOBO (view_parent);
91         g_return_if_fail (view->uic);
92
93         model = gnome_recent_view_get_model (GNOME_RECENT_VIEW (view));
94         appname = gnome_recent_model_get_appname (model);
95         
96         while (!done)
97         {
98                 gchar *verb_name = g_strdup_printf ("%s%s%d", appname,GNOME_RECENT_VERB_NAME, i);
99                 gchar *item_path = g_strconcat (view->path, "/", verb_name, NULL);
100                 if (bonobo_ui_component_path_exists (view->uic, item_path, NULL))
101                         bonobo_ui_component_rm (view->uic, item_path, NULL);
102                 else
103                         done=TRUE;
104
105                 g_free (item_path);
106                 g_free (verb_name);
107
108                 i++;
109         }
110
111         g_free (appname);
112 }
113
114 static void
115 gnome_recent_view_bonobo_menu_cb (BonoboUIComponent *uic, gpointer data, const char *cname)
116 {
117         gboolean ret;
118         GnomeRecentViewBonoboMenuData *md = (GnomeRecentViewBonoboMenuData *) data;
119         GnomeRecentModel *model;
120
121         g_return_if_fail (md);
122         g_return_if_fail (md->uri);
123         g_return_if_fail (md->view);
124         g_return_if_fail (GNOME_IS_RECENT_VIEW_BONOBO (md->view));
125
126         ret = FALSE;
127         g_signal_emit (G_OBJECT(md->view),
128                        gnome_recent_view_bonobo_signals[ACTIVATE], 0,
129                        md->uri, &ret);
130
131         if (!ret) {
132                 model = gnome_recent_view_get_model (GNOME_RECENT_VIEW (md->view));
133                 gnome_recent_model_delete (model, md->uri);
134         }
135 }
136
137 static void
138 gnome_recent_view_bonobo_menu_data_destroy_cb (gpointer data, GClosure *closure)
139 {
140         GnomeRecentViewBonoboMenuData *md = data;
141
142         g_free (md->uri);
143         g_free (md);
144 }
145
146
147 static void
148 gnome_recent_view_bonobo_set_list (GnomeRecentViewBonobo *view, GSList *list)
149 {
150         BonoboUIComponent* ui_component;
151         unsigned int i;
152         gchar *label = NULL;
153         gchar *verb_name = NULL;
154         gchar *tip = NULL;
155         gchar *escaped_name = NULL;
156         gchar *item_path = NULL;
157         gchar *uri;
158         gchar *cmd;
159         gchar *appname;
160         GnomeRecentViewBonoboMenuData *md;
161         GnomeRecentModel *model;
162         GClosure *closure;
163
164         g_return_if_fail (view);
165
166         ui_component = view->uic;
167         g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui_component));
168
169         model = gnome_recent_view_get_model (GNOME_RECENT_VIEW (view));
170         appname = gnome_recent_model_get_appname (model);
171
172         gnome_recent_view_bonobo_clear (GNOME_RECENT_VIEW (view));
173         
174         bonobo_ui_component_freeze (ui_component, NULL);
175
176         for (i = 1; i <= g_slist_length (list); ++i)
177         {
178                 
179                 /* this is what gets passed to our private "activate" callback */
180                 md = (GnomeRecentViewBonoboMenuData *)g_malloc (sizeof (GnomeRecentViewBonoboMenuData));
181                 md->view = view;
182                 md->uri = g_strdup (g_slist_nth_data (list, i-1));
183
184                 /* Maybe we should use a gnome-vfs call here?? */
185                 uri = g_path_get_basename (g_slist_nth_data (list, i - 1));
186         
187                 escaped_name = gnome_recent_util_escape_underlines (uri);
188
189                 tip =  g_strdup_printf (_("Open %s"), uri);
190
191                 verb_name = g_strdup_printf ("%s%s%d", appname,GNOME_RECENT_VERB_NAME, i);
192                 cmd = g_strdup_printf ("<cmd name = \"%s\" /> ", verb_name);
193                 bonobo_ui_component_set_translate (ui_component, "/commands/", cmd, NULL);
194
195                 closure = g_cclosure_new (G_CALLBACK (gnome_recent_view_bonobo_menu_cb),
196                                           md, gnome_recent_view_bonobo_menu_data_destroy_cb);
197                                           
198                 bonobo_ui_component_add_verb_full (ui_component, verb_name,
199                                                    closure); 
200                 
201                 if (i < 10)
202                         label = g_strdup_printf ("_%d. %s", i, escaped_name);
203                 else
204                         label = g_strdup_printf ("%d. %s", i, escaped_name);
205                         
206                 
207                 
208                 item_path = g_strconcat (view->path, "/", verb_name, NULL);
209
210                 if (bonobo_ui_component_path_exists (ui_component, item_path, NULL))
211                 {
212                         bonobo_ui_component_set_prop (ui_component, item_path, 
213                                                       "label", label, NULL);
214
215                         bonobo_ui_component_set_prop (ui_component, item_path, 
216                                                       "tip", tip, NULL);
217                 }
218                 else
219                 {
220                         gchar *xml;
221
222                         xml = g_strdup_printf ("<menuitem name=\"%s\" "
223                                                 "verb=\"%s\""
224                                                 " _label=\"%s\"  _tip=\"%s\" "
225                                                 "hidden=\"0\" />", 
226                                                 verb_name, verb_name, label,
227                                                 tip);
228
229                         bonobo_ui_component_set_translate (ui_component, view->path, xml, NULL);
230
231                         g_free (xml); 
232                 }
233                 
234                 g_free (label);
235                 g_free (verb_name);
236                 g_free (tip);
237                 g_free (escaped_name);
238                 g_free (item_path);
239                 g_free (uri);
240                 g_free (cmd);
241         }
242
243
244         bonobo_ui_component_thaw (ui_component, NULL);
245 }
246
247 static void
248 model_changed_cb (GnomeRecentModel *model, GSList *list, GnomeRecentViewBonobo *view)
249 {
250         gnome_recent_view_bonobo_set_list (view, list);
251 }
252
253
254
255 static void
256 gnome_recent_view_bonobo_populate (GnomeRecentViewBonobo *view)
257 {
258         GnomeRecentModel *model;
259         GSList *list;
260
261         model = gnome_recent_view_get_model (GNOME_RECENT_VIEW (view));
262         list = gnome_recent_model_get_list (model);
263
264         gnome_recent_view_bonobo_set_list (view, list);
265 }
266
267 static GnomeRecentModel *
268 gnome_recent_view_bonobo_get_model (GnomeRecentView *view_parent)
269 {
270         GnomeRecentViewBonobo *view;
271         
272         g_return_val_if_fail (view_parent, NULL);
273         view = GNOME_RECENT_VIEW_BONOBO (view_parent);
274         
275         return view->model;
276 }
277
278 static void
279 gnome_recent_view_bonobo_set_model (GnomeRecentView *view_parent, GnomeRecentModel *model)
280 {
281         GnomeRecentViewBonobo *view;
282         
283         g_return_if_fail (view_parent);
284         view = GNOME_RECENT_VIEW_BONOBO (view_parent);
285         
286         if (view->model)
287                 g_signal_handler_disconnect (G_OBJECT (view->model),
288                                              view->changed_cb_id);
289         
290         view->model = model;
291         view->changed_cb_id = g_signal_connect (G_OBJECT (model), "changed",
292                                         G_CALLBACK (model_changed_cb), view);
293
294         gnome_recent_view_bonobo_populate (view);
295 }
296
297 static void
298 gnome_recent_view_bonobo_set_property (GObject *object,
299                            guint prop_id,
300                            const GValue *value,
301                            GParamSpec *pspec)
302 {
303         GnomeRecentViewBonobo *view = GNOME_RECENT_VIEW_BONOBO (object);
304
305         switch (prop_id)
306         {
307                 case PROP_UI_COMPONENT:
308                         gnome_recent_view_bonobo_set_ui_component (GNOME_RECENT_VIEW_BONOBO (view),
309                                                        BONOBO_UI_COMPONENT (g_value_get_object (value)));
310                 break;
311                 case PROP_MENU_PATH:
312                         view->path = g_strdup (g_value_get_string (value));
313                 break;
314                 default:
315                 break;
316         }
317 }
318
319 static void
320 gnome_recent_view_bonobo_get_property (GObject *object,
321                            guint prop_id,
322                            GValue *value,
323                            GParamSpec *pspec)
324 {
325         GnomeRecentViewBonobo *view = GNOME_RECENT_VIEW_BONOBO (object);
326
327         switch (prop_id)
328         {
329                 case PROP_UI_COMPONENT:
330                         g_value_set_pointer (value, view->uic);
331                 break;
332                 case PROP_MENU_PATH:
333                         g_value_set_string (value, g_strdup (view->path));
334                 break;
335                 default:
336                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
337         }
338 }
339
340 static void
341 gnome_recent_view_bonobo_class_init (GnomeRecentViewBonoboClass * klass)
342 {
343         GObjectClass *object_class;
344
345         
346         object_class = G_OBJECT_CLASS (klass);
347
348         object_class->set_property = gnome_recent_view_bonobo_set_property;
349         object_class->get_property = gnome_recent_view_bonobo_get_property;
350
351         gnome_recent_view_bonobo_signals[ACTIVATE] = g_signal_new ("activate",
352                         G_OBJECT_CLASS_TYPE (object_class),
353                         G_SIGNAL_RUN_LAST,
354                         G_STRUCT_OFFSET (GnomeRecentViewBonoboClass, activate),
355                         NULL, NULL,
356                         gnome_recent_BOOLEAN__STRING,
357                         G_TYPE_BOOLEAN, 1,
358                         G_TYPE_STRING);
359
360         g_object_class_install_property (object_class,
361                                          PROP_UI_COMPONENT,
362                                          g_param_spec_object ("ui-component",
363                                            "UI Component",
364                                            "BonoboUIComponent for menus.",
365                                            bonobo_ui_component_get_type(),
366                                            G_PARAM_READWRITE));
367
368         g_object_class_install_property (object_class,
369                                          PROP_MENU_PATH,
370                                          g_param_spec_string ("ui-path",
371                                            "Path",
372                                            "The path to put the menu items.",
373                                            "/menus/File/GnomeRecentDocuments",
374                                            G_PARAM_READWRITE));
375
376
377         klass->activate = NULL;
378 }
379
380 static void
381 gnome_recent_view_init (GnomeRecentViewClass *iface)
382 {
383         iface->do_clear = gnome_recent_view_bonobo_clear;
384         iface->do_get_model = gnome_recent_view_bonobo_get_model;
385         iface->do_set_model = gnome_recent_view_bonobo_set_model;
386 }
387
388
389 static void
390 gnome_recent_view_bonobo_init (GnomeRecentViewBonobo * recent)
391 {
392         /* maybe should remove this */
393 }
394
395 void
396 gnome_recent_view_bonobo_set_ui_component (GnomeRecentViewBonobo *view, BonoboUIComponent *uic)
397 {
398         g_return_if_fail (view);
399         g_return_if_fail (uic);
400
401         view->uic = uic;
402 }
403
404 void
405 gnome_recent_view_bonobo_set_ui_path (GnomeRecentViewBonobo *view, const gchar *path)
406 {
407         g_return_if_fail (view);
408         g_return_if_fail (path);
409
410         view->path = g_strdup (path);
411 }
412
413 BonoboUIComponent *
414 gnome_recent_view_bonobo_get_ui_component (GnomeRecentViewBonobo *view)
415 {
416         g_return_val_if_fail (view, NULL);
417
418         return view->uic;
419 }
420
421 gchar *
422 gnome_recent_view_bonobo_get_ui_path (GnomeRecentViewBonobo *view)
423 {
424         g_return_val_if_fail (view, NULL);
425
426         return g_strdup (view->path);
427 }
428
429 /**
430  * gnome_recent_view_bonobo_new:
431  * @appname: The name of your application.
432  * @limit:  The maximum number of items allowed.
433  *
434  * This creates a new GnomeRecentViewBonobo object.
435  *
436  * Returns: a GnomeRecentViewBonobo object
437  */
438 GnomeRecentViewBonobo *
439 gnome_recent_view_bonobo_new (BonoboUIComponent *uic, const gchar *path)
440 {
441         GnomeRecentViewBonobo *view;
442
443         g_return_val_if_fail (uic, NULL);
444         g_return_val_if_fail (path, NULL);
445
446         view = GNOME_RECENT_VIEW_BONOBO (g_object_new (gnome_recent_view_bonobo_get_type (),
447                                            "ui-path",
448                                            path,
449                                            "ui-component",
450                                            uic, NULL));
451
452         g_return_val_if_fail (view, NULL);
453         
454         return view;
455 }
456
457 /**
458  * gnome_recent_view_bonobo_get_type:
459  * @:
460  *
461  * This returns a GType representing a GnomeRecentViewBonobo object.
462  *
463  * Returns: a GType
464  */
465 GType
466 gnome_recent_view_bonobo_get_type (void)
467 {
468         static GType gnome_recent_view_bonobo_type = 0;
469
470         if(!gnome_recent_view_bonobo_type) {
471                 static const GTypeInfo gnome_recent_view_bonobo_info = {
472                         sizeof (GnomeRecentViewBonoboClass),
473                         NULL, /* base init */
474                         NULL, /* base finalize */
475                         (GClassInitFunc)gnome_recent_view_bonobo_class_init, /* class init */
476                         NULL, /* class finalize */
477                         NULL, /* class data */
478                         sizeof (GnomeRecentViewBonobo),
479                         0,
480                         (GInstanceInitFunc) gnome_recent_view_bonobo_init
481                 };
482
483                 static const GInterfaceInfo view_info =
484                 {
485                         (GInterfaceInitFunc) gnome_recent_view_init,
486                         NULL,
487                         NULL
488                 };
489
490                 gnome_recent_view_bonobo_type = g_type_register_static (G_TYPE_OBJECT,
491                                                         "GnomeRecentViewBonobo",
492                                                         &gnome_recent_view_bonobo_info, 0);
493                 g_type_add_interface_static (gnome_recent_view_bonobo_type,
494                                              GNOME_TYPE_RECENT_VIEW,
495                                              &view_info);
496         }
497
498         return gnome_recent_view_bonobo_type;
499 }
500